Print this page
*** NO COMMENTS ***

*** 1,12 **** /* ! * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ /* ! * Copyright 2005-08 Adaptec, Inc. ! * Copyright (c) 2005-08 Adaptec Inc., Achim Leubner * Copyright (c) 2000 Michael Smith * Copyright (c) 2001 Scott Long * Copyright (c) 2000 BSDi * All rights reserved. * --- 1,13 ---- /* ! * Copyright 2008 Sun Microsystems, Inc. All rights reserved. ! * Use is subject to license terms. */ /* ! * Copyright (c) 2010-12 PMC-Sierra, Inc. ! * Copyright (c) 2005-10 Adaptec Inc., Achim Leubner * Copyright (c) 2000 Michael Smith * Copyright (c) 2001 Scott Long * Copyright (c) 2000 BSDi * All rights reserved. *
*** 29,38 **** --- 30,41 ---- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ + #pragma ident "@(#)aac.c 1.19 08/01/29 SMI" + #include <sys/modctl.h> #include <sys/conf.h> #include <sys/cmn_err.h> #include <sys/ddi.h> #include <sys/devops.h>
*** 41,61 **** #include <sys/ddidmareq.h> #include <sys/scsi/scsi.h> #include <sys/ksynch.h> #include <sys/sunddi.h> #include <sys/byteorder.h> #include "aac_regs.h" #include "aac.h" /* ! * FMA header files */ #include <sys/ddifm.h> #include <sys/fm/protocol.h> #include <sys/fm/util.h> #include <sys/fm/io/ddi.h> /* * For minor nodes created by the SCSA framework, minor numbers are * formed by left-shifting instance by INST_MINOR_SHIFT and OR in a * number less than 64. * --- 44,80 ---- #include <sys/ddidmareq.h> #include <sys/scsi/scsi.h> #include <sys/ksynch.h> #include <sys/sunddi.h> #include <sys/byteorder.h> + #include <sys/utsname.h> #include "aac_regs.h" #include "aac.h" /* ! * FMA header files, macros */ #include <sys/ddifm.h> #include <sys/fm/protocol.h> #include <sys/fm/util.h> #include <sys/fm/io/ddi.h> + #ifndef DDI_FM_DEVICE + #define DDI_FM_DEVICE "device" + #define DDI_FM_DEVICE_NO_RESPONSE "no_response" + #define ddi_fm_acc_err_clear(a, b) + #endif + #define aac_fm_service_impact(a, b) { \ + if (aac_fm_valid) \ + ddi_fm_service_impact(a, b); \ + } + #define aac_fm_acc_err_clear(a, b) { \ + if (aac_fm_valid) \ + ddi_fm_acc_err_clear(a, b); \ + } + char _depends_on[] = "misc/scsi"; + /* * For minor nodes created by the SCSA framework, minor numbers are * formed by left-shifting instance by INST_MINOR_SHIFT and OR in a * number less than 64. *
*** 77,90 **** #define AAC_PD(t) ((t) - AAC_MAX_LD) #define AAC_DEV(softs, t) (((t) < AAC_MAX_LD) ? \ &(softs)->containers[(t)].dev : \ ((t) < AAC_MAX_DEV(softs)) ? \ &(softs)->nondasds[AAC_PD(t)].dev : NULL) - #define AAC_DEVCFG_BEGIN(softs, tgt) \ - aac_devcfg((softs), (tgt), 1) - #define AAC_DEVCFG_END(softs, tgt) \ - aac_devcfg((softs), (tgt), 0) #define PKT2AC(pkt) ((struct aac_cmd *)(pkt)->pkt_ha_private) #define AAC_BUSYWAIT(cond, timeout /* in millisecond */) { \ if (!(cond)) { \ int count = (timeout) * 10; \ while (count) { \ --- 96,105 ----
*** 146,177 **** #define CARD_IS_UNKNOWN(i) (i == AAC_UNKNOWN_CARD) #define BUF_IS_READ(bp) ((bp)->b_flags & B_READ) #define AAC_IS_Q_EMPTY(q) ((q)->q_head == NULL) #define AAC_CMDQ(acp) (!((acp)->flags & AAC_CMD_SYNC)) ! #define PCI_MEM_GET32(softs, off) \ ! ddi_get32((softs)->pci_mem_handle, \ ! (void *)((softs)->pci_mem_base_vaddr + (off))) ! #define PCI_MEM_PUT32(softs, off, val) \ ! ddi_put32((softs)->pci_mem_handle, \ ! (void *)((softs)->pci_mem_base_vaddr + (off)), \ (uint32_t)(val)) ! #define PCI_MEM_GET16(softs, off) \ ! ddi_get16((softs)->pci_mem_handle, \ ! (void *)((softs)->pci_mem_base_vaddr + (off))) ! #define PCI_MEM_PUT16(softs, off, val) \ ! ddi_put16((softs)->pci_mem_handle, \ ! (void *)((softs)->pci_mem_base_vaddr + (off)), (uint16_t)(val)) ! /* Write host data at valp to device mem[off] repeatedly count times */ ! #define PCI_MEM_REP_PUT8(softs, off, valp, count) \ ! ddi_rep_put8((softs)->pci_mem_handle, (uint8_t *)(valp), \ ! (uint8_t *)((softs)->pci_mem_base_vaddr + (off)), \ count, DDI_DEV_AUTOINCR) ! /* Read device data at mem[off] to host addr valp repeatedly count times */ ! #define PCI_MEM_REP_GET8(softs, off, valp, count) \ ! ddi_rep_get8((softs)->pci_mem_handle, (uint8_t *)(valp), \ ! (uint8_t *)((softs)->pci_mem_base_vaddr + (off)), \ count, DDI_DEV_AUTOINCR) #define AAC_GET_FIELD8(acc, d, s, field) \ (d)->field = ddi_get8(acc, (uint8_t *)&(s)->field) #define AAC_GET_FIELD32(acc, d, s, field) \ (d)->field = ddi_get32(acc, (uint32_t *)&(s)->field) --- 161,192 ---- #define CARD_IS_UNKNOWN(i) (i == AAC_UNKNOWN_CARD) #define BUF_IS_READ(bp) ((bp)->b_flags & B_READ) #define AAC_IS_Q_EMPTY(q) ((q)->q_head == NULL) #define AAC_CMDQ(acp) (!((acp)->flags & AAC_CMD_SYNC)) ! #define PCI_MEM_GET32(softs, i, off) \ ! ddi_get32((softs)->pci_mem_handle[i], \ ! (uint32_t *)((softs)->pci_mem_base_vaddr[i] + (off))) ! #define PCI_MEM_PUT32(softs, i, off, val) \ ! ddi_put32((softs)->pci_mem_handle[i], \ ! (uint32_t *)((softs)->pci_mem_base_vaddr[i] + (off)), \ (uint32_t)(val)) ! #define PCI_MEM_GET16(softs, i, off) \ ! ddi_get16((softs)->pci_mem_handle[i], \ ! (uint16_t *)((softs)->pci_mem_base_vaddr[i] + (off))) ! #define PCI_MEM_PUT16(softs, i, off, val) \ ! ddi_put16((softs)->pci_mem_handle[i], \ ! (uint16_t *)((softs)->pci_mem_base_vaddr[i] + (off)), (uint16_t)(val)) ! /* Write host data at valp to device mem[i][off] repeatedly count times */ ! #define PCI_MEM_REP_PUT8(softs, i, off, valp, count) \ ! ddi_rep_put8((softs)->pci_mem_handle[i], (uint8_t *)(valp), \ ! (uint8_t *)((softs)->pci_mem_base_vaddr[i] + (off)), \ count, DDI_DEV_AUTOINCR) ! /* Read device data at mem[i][off] to host addr valp repeatedly count times */ ! #define PCI_MEM_REP_GET8(softs, i, off, valp, count) \ ! ddi_rep_get8((softs)->pci_mem_handle[i], (uint8_t *)(valp), \ ! (uint8_t *)((softs)->pci_mem_base_vaddr[i] + (off)), \ count, DDI_DEV_AUTOINCR) #define AAC_GET_FIELD8(acc, d, s, field) \ (d)->field = ddi_get8(acc, (uint8_t *)&(s)->field) #define AAC_GET_FIELD32(acc, d, s, field) \ (d)->field = ddi_get32(acc, (uint32_t *)&(s)->field)
*** 182,217 **** (uint8_t *)&(s)->field, (r), DDI_DEV_AUTOINCR) #define AAC_REP_GET_FIELD32(acc, d, s, field, r) \ ddi_rep_get32((acc), (uint32_t *)&(d)->field, \ (uint32_t *)&(s)->field, (r), DDI_DEV_AUTOINCR) ! #define AAC_ENABLE_INTR(softs) { \ ! if (softs->flags & AAC_FLAGS_NEW_COMM) \ ! PCI_MEM_PUT32(softs, AAC_OIMR, ~AAC_DB_INTR_NEW); \ ! else \ ! PCI_MEM_PUT32(softs, AAC_OIMR, ~AAC_DB_INTR_BITS); \ ! softs->state |= AAC_STATE_INTR; \ ! } ! #define AAC_DISABLE_INTR(softs) { \ ! PCI_MEM_PUT32(softs, AAC_OIMR, ~0); \ ! softs->state &= ~AAC_STATE_INTR; \ ! } ! #define AAC_STATUS_CLR(softs, mask) PCI_MEM_PUT32(softs, AAC_ODBR, mask) ! #define AAC_STATUS_GET(softs) PCI_MEM_GET32(softs, AAC_ODBR) ! #define AAC_NOTIFY(softs, val) PCI_MEM_PUT32(softs, AAC_IDBR, val) ! #define AAC_OUTB_GET(softs) PCI_MEM_GET32(softs, AAC_OQUE) ! #define AAC_OUTB_SET(softs, val) PCI_MEM_PUT32(softs, AAC_OQUE, val) #define AAC_FWSTATUS_GET(softs) \ ((softs)->aac_if.aif_get_fwstatus(softs)) #define AAC_MAILBOX_GET(softs, mb) \ ((softs)->aac_if.aif_get_mailbox((softs), (mb))) #define AAC_MAILBOX_SET(softs, cmd, arg0, arg1, arg2, arg3) \ ((softs)->aac_if.aif_set_mailbox((softs), (cmd), \ (arg0), (arg1), (arg2), (arg3))) - #define AAC_MGT_SLOT_NUM 2 #define AAC_THROTTLE_DRAIN -1 #define AAC_QUIESCE_TICK 1 /* 1 second */ #define AAC_QUIESCE_TIMEOUT 180 /* 180 seconds */ #define AAC_DEFAULT_TICK 10 /* 10 seconds */ --- 197,228 ---- (uint8_t *)&(s)->field, (r), DDI_DEV_AUTOINCR) #define AAC_REP_GET_FIELD32(acc, d, s, field, r) \ ddi_rep_get32((acc), (uint32_t *)&(d)->field, \ (uint32_t *)&(s)->field, (r), DDI_DEV_AUTOINCR) ! #define AAC_OUTB_GET(softs) PCI_MEM_GET32(softs, 0, AAC_OQUE) ! #define AAC_OUTB_SET(softs, val) PCI_MEM_PUT32(softs, 0, AAC_OQUE, val) ! #define AAC_SET_INTR(softs, enable) \ ! ((softs)->aac_if.aif_set_intr((softs), (enable))) ! #define AAC_STATUS_CLR(softs, mask) \ ! ((softs)->aac_if.aif_status_clr((softs), (mask))) ! #define AAC_STATUS_GET(softs) \ ! ((softs)->aac_if.aif_status_get(softs)) ! #define AAC_NOTIFY(softs, val) \ ! ((softs)->aac_if.aif_notify((softs), (val))) ! #define AAC_FWSTATUS_GET(softs) \ ((softs)->aac_if.aif_get_fwstatus(softs)) #define AAC_MAILBOX_GET(softs, mb) \ ((softs)->aac_if.aif_get_mailbox((softs), (mb))) #define AAC_MAILBOX_SET(softs, cmd, arg0, arg1, arg2, arg3) \ ((softs)->aac_if.aif_set_mailbox((softs), (cmd), \ (arg0), (arg1), (arg2), (arg3))) + #define AAC_SEND_COMMAND(softs, slotp) \ + ((softs)->aac_if.aif_send_command((softs), (slotp))) #define AAC_THROTTLE_DRAIN -1 #define AAC_QUIESCE_TICK 1 /* 1 second */ #define AAC_QUIESCE_TIMEOUT 180 /* 180 seconds */ #define AAC_DEFAULT_TICK 10 /* 10 seconds */
*** 218,261 **** #define AAC_SYNC_TICK (30*60) /* 30 minutes */ /* Poll time for aac_do_poll_io() */ #define AAC_POLL_TIME 60 /* 60 seconds */ - /* IOP reset */ - #define AAC_IOP_RESET_SUCCEED 0 /* IOP reset succeed */ - #define AAC_IOP_RESET_FAILED -1 /* IOP reset failed */ - #define AAC_IOP_RESET_ABNORMAL -2 /* Reset operation abnormal */ - /* * Hardware access functions */ static int aac_rx_get_fwstatus(struct aac_softstate *); static int aac_rx_get_mailbox(struct aac_softstate *, int); static void aac_rx_set_mailbox(struct aac_softstate *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); static int aac_rkt_get_fwstatus(struct aac_softstate *); static int aac_rkt_get_mailbox(struct aac_softstate *, int); static void aac_rkt_set_mailbox(struct aac_softstate *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); /* * SCSA function prototypes */ static int aac_attach(dev_info_t *, ddi_attach_cmd_t); static int aac_detach(dev_info_t *, ddi_detach_cmd_t); static int aac_reset(dev_info_t *, ddi_reset_cmd_t); - static int aac_quiesce(dev_info_t *); - static int aac_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); /* * Interrupt handler functions */ - static int aac_query_intrs(struct aac_softstate *, int); - static int aac_add_intrs(struct aac_softstate *); - static void aac_remove_intrs(struct aac_softstate *); - static int aac_enable_intrs(struct aac_softstate *); - static int aac_disable_intrs(struct aac_softstate *); static uint_t aac_intr_old(caddr_t); static uint_t aac_intr_new(caddr_t); static uint_t aac_softintr(caddr_t); /* --- 229,277 ---- #define AAC_SYNC_TICK (30*60) /* 30 minutes */ /* Poll time for aac_do_poll_io() */ #define AAC_POLL_TIME 60 /* 60 seconds */ /* * Hardware access functions */ + static void aac_rx_set_intr(struct aac_softstate *, int); + static void aac_rx_status_clr(struct aac_softstate *, int); + static int aac_rx_status_get(struct aac_softstate *); + static void aac_rx_notify(struct aac_softstate *, int); static int aac_rx_get_fwstatus(struct aac_softstate *); static int aac_rx_get_mailbox(struct aac_softstate *, int); static void aac_rx_set_mailbox(struct aac_softstate *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); + static int aac_rx_send_command(struct aac_softstate *, struct aac_slot *); static int aac_rkt_get_fwstatus(struct aac_softstate *); static int aac_rkt_get_mailbox(struct aac_softstate *, int); static void aac_rkt_set_mailbox(struct aac_softstate *, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); + static void aac_src_set_intr(struct aac_softstate *, int); + static void aac_src_status_clr(struct aac_softstate *, int); + static int aac_src_status_get(struct aac_softstate *); + static void aac_src_notify(struct aac_softstate *, int); + static int aac_src_get_fwstatus(struct aac_softstate *); + static int aac_src_get_mailbox(struct aac_softstate *, int); + static void aac_src_set_mailbox(struct aac_softstate *, uint32_t, uint32_t, + uint32_t, uint32_t, uint32_t); + static int aac_src_send_command(struct aac_softstate *, struct aac_slot *); + static int aac_srcv_get_mailbox(struct aac_softstate *, int); + static void aac_srcv_set_mailbox(struct aac_softstate *, uint32_t, uint32_t, + uint32_t, uint32_t, uint32_t); /* * SCSA function prototypes */ static int aac_attach(dev_info_t *, ddi_attach_cmd_t); static int aac_detach(dev_info_t *, ddi_detach_cmd_t); static int aac_reset(dev_info_t *, ddi_reset_cmd_t); /* * Interrupt handler functions */ static uint_t aac_intr_old(caddr_t); static uint_t aac_intr_new(caddr_t); static uint_t aac_softintr(caddr_t); /*
*** 273,283 **** /* * Sync FIB operation functions */ int aac_sync_mbcommand(struct aac_softstate *, uint32_t, uint32_t, ! uint32_t, uint32_t, uint32_t, uint32_t *); static int aac_sync_fib(struct aac_softstate *, uint16_t, uint16_t); /* * Command queue operation functions */ --- 289,299 ---- /* * Sync FIB operation functions */ int aac_sync_mbcommand(struct aac_softstate *, uint32_t, uint32_t, ! uint32_t, uint32_t, uint32_t, uint32_t *, uint32_t *); static int aac_sync_fib(struct aac_softstate *, uint16_t, uint16_t); /* * Command queue operation functions */
*** 305,355 **** static void aac_free_fib(struct aac_slot *); /* * Internal functions */ ! static void aac_cmd_fib_header(struct aac_softstate *, struct aac_cmd *, ! uint16_t); static void aac_cmd_fib_rawio(struct aac_softstate *, struct aac_cmd *); static void aac_cmd_fib_brw64(struct aac_softstate *, struct aac_cmd *); static void aac_cmd_fib_brw(struct aac_softstate *, struct aac_cmd *); static void aac_cmd_fib_sync(struct aac_softstate *, struct aac_cmd *); static void aac_cmd_fib_scsi32(struct aac_softstate *, struct aac_cmd *); static void aac_cmd_fib_scsi64(struct aac_softstate *, struct aac_cmd *); - static void aac_cmd_fib_startstop(struct aac_softstate *, struct aac_cmd *); static void aac_start_waiting_io(struct aac_softstate *); static void aac_drain_comp_q(struct aac_softstate *); int aac_do_io(struct aac_softstate *, struct aac_cmd *); - static int aac_sync_fib_slot_bind(struct aac_softstate *, struct aac_cmd *); - static void aac_sync_fib_slot_release(struct aac_softstate *, struct aac_cmd *); - static void aac_start_io(struct aac_softstate *, struct aac_cmd *); static int aac_do_poll_io(struct aac_softstate *, struct aac_cmd *); static int aac_do_sync_io(struct aac_softstate *, struct aac_cmd *); - static int aac_send_command(struct aac_softstate *, struct aac_slot *); static void aac_cmd_timeout(struct aac_softstate *, struct aac_cmd *); static int aac_dma_sync_ac(struct aac_cmd *); static int aac_shutdown(struct aac_softstate *); static int aac_reset_adapter(struct aac_softstate *); static int aac_do_quiesce(struct aac_softstate *softs); static int aac_do_unquiesce(struct aac_softstate *softs); static void aac_unhold_bus(struct aac_softstate *, int); static void aac_set_throttle(struct aac_softstate *, struct aac_device *, int, int); /* * Adapter Initiated FIB handling function */ ! static void aac_save_aif(struct aac_softstate *, ddi_acc_handle_t, ! struct aac_fib *, int); ! static int aac_handle_aif(struct aac_softstate *, struct aac_aif_command *); /* ! * Event handling related functions */ ! static void aac_timer(void *); ! static void aac_event_thread(struct aac_softstate *); ! static void aac_event_disp(struct aac_softstate *, int); /* * IOCTL interface related functions */ static int aac_open(dev_t *, int, int, cred_t *); --- 321,369 ---- static void aac_free_fib(struct aac_slot *); /* * Internal functions */ ! static void aac_cmd_fib_header(struct aac_softstate *, struct aac_slot *, ! uint16_t, uint16_t); static void aac_cmd_fib_rawio(struct aac_softstate *, struct aac_cmd *); + static void aac_cmd_fib_rawio2(struct aac_softstate *, struct aac_cmd *); + static uint_t aac_convert_sgraw2(struct aac_softstate *, struct aac_cmd *, + uint_t, uint_t, uint_t, uint16_t *); static void aac_cmd_fib_brw64(struct aac_softstate *, struct aac_cmd *); static void aac_cmd_fib_brw(struct aac_softstate *, struct aac_cmd *); static void aac_cmd_fib_sync(struct aac_softstate *, struct aac_cmd *); + static void aac_cmd_aif_request(struct aac_softstate *, struct aac_cmd *); + static void aac_aifreq_complete(struct aac_softstate *, struct aac_cmd *); static void aac_cmd_fib_scsi32(struct aac_softstate *, struct aac_cmd *); static void aac_cmd_fib_scsi64(struct aac_softstate *, struct aac_cmd *); static void aac_start_waiting_io(struct aac_softstate *); static void aac_drain_comp_q(struct aac_softstate *); int aac_do_io(struct aac_softstate *, struct aac_cmd *); static int aac_do_poll_io(struct aac_softstate *, struct aac_cmd *); static int aac_do_sync_io(struct aac_softstate *, struct aac_cmd *); static void aac_cmd_timeout(struct aac_softstate *, struct aac_cmd *); static int aac_dma_sync_ac(struct aac_cmd *); static int aac_shutdown(struct aac_softstate *); static int aac_reset_adapter(struct aac_softstate *); static int aac_do_quiesce(struct aac_softstate *softs); static int aac_do_unquiesce(struct aac_softstate *softs); static void aac_unhold_bus(struct aac_softstate *, int); static void aac_set_throttle(struct aac_softstate *, struct aac_device *, int, int); + static int aac_atoi(char **pptr); + static void aac_config_pd(void *); /* * Adapter Initiated FIB handling function */ ! static int aac_handle_aif(struct aac_softstate *, struct aac_fib *); /* ! * Timeout handling thread function */ ! static void aac_daemon(void *); /* * IOCTL interface related functions */ static int aac_open(dev_t *, int, int, cred_t *);
*** 363,385 **** static void aac_fm_init(struct aac_softstate *); static void aac_fm_fini(struct aac_softstate *); static int aac_fm_error_cb(dev_info_t *, ddi_fm_error_t *, const void *); int aac_check_acc_handle(ddi_acc_handle_t); int aac_check_dma_handle(ddi_dma_handle_t); ! void aac_fm_ereport(struct aac_softstate *, char *); - /* - * Auto enumeration functions - */ - static dev_info_t *aac_find_child(struct aac_softstate *, uint16_t, uint8_t); static int aac_tran_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t, void *, dev_info_t **); ! static int aac_handle_dr(struct aac_softstate *, int, int, int); ! extern pri_t minclsyspri; ! ! #ifdef DEBUG /* * UART debug output support */ #define AAC_PRINT_BUFFER_SIZE 512 --- 377,393 ---- static void aac_fm_init(struct aac_softstate *); static void aac_fm_fini(struct aac_softstate *); static int aac_fm_error_cb(dev_info_t *, ddi_fm_error_t *, const void *); int aac_check_acc_handle(ddi_acc_handle_t); int aac_check_dma_handle(ddi_dma_handle_t); ! void aac_fm_ereport(struct aac_softstate *, char *, int); static int aac_tran_bus_config(dev_info_t *, uint_t, ddi_bus_config_op_t, void *, dev_info_t **); ! static int aac_dr_event(struct aac_softstate *, int, int, int); ! #ifdef AAC_DEBUG /* * UART debug output support */ #define AAC_PRINT_BUFFER_SIZE 512
*** 388,399 **** #define AAC_FW_DBG_STRLEN_OFFSET 0x00 #define AAC_FW_DBG_FLAGS_OFFSET 0x04 #define AAC_FW_DBG_BLED_OFFSET 0x08 static int aac_get_fw_debug_buffer(struct aac_softstate *); - static void aac_print_scmd(struct aac_softstate *, struct aac_cmd *); - static void aac_print_aif(struct aac_softstate *, struct aac_aif_command *); static char aac_prt_buf[AAC_PRINT_BUFFER_SIZE]; static char aac_fmt[] = " %s"; static char aac_fmt_header[] = " %s.%d: %s"; static kmutex_t aac_prt_mutex; --- 396,405 ----
*** 402,430 **** * Debug flags to be put into the softstate flags field * when initialized */ uint32_t aac_debug_flags = /* AACDB_FLAGS_KERNEL_PRINT | */ ! /* AACDB_FLAGS_FW_PRINT | */ ! /* AACDB_FLAGS_MISC | */ /* AACDB_FLAGS_FUNC1 | */ /* AACDB_FLAGS_FUNC2 | */ /* AACDB_FLAGS_SCMD | */ /* AACDB_FLAGS_AIF | */ /* AACDB_FLAGS_FIB | */ /* AACDB_FLAGS_IOCTL | */ 0; ! uint32_t aac_debug_fib_flags = ! /* AACDB_FLAGS_FIB_RW | */ ! /* AACDB_FLAGS_FIB_IOCTL | */ ! /* AACDB_FLAGS_FIB_SRB | */ ! /* AACDB_FLAGS_FIB_SYNC | */ ! /* AACDB_FLAGS_FIB_HEADER | */ ! /* AACDB_FLAGS_FIB_TIMEOUT | */ ! 0; ! #endif /* DEBUG */ static struct cb_ops aac_cb_ops = { aac_open, /* open */ aac_close, /* close */ nodev, /* strategy */ --- 408,442 ---- * Debug flags to be put into the softstate flags field * when initialized */ uint32_t aac_debug_flags = /* AACDB_FLAGS_KERNEL_PRINT | */ ! AACDB_FLAGS_FW_PRINT | ! AACDB_FLAGS_MISC | /* AACDB_FLAGS_FUNC1 | */ /* AACDB_FLAGS_FUNC2 | */ /* AACDB_FLAGS_SCMD | */ /* AACDB_FLAGS_AIF | */ /* AACDB_FLAGS_FIB | */ /* AACDB_FLAGS_IOCTL | */ 0; ! #endif /* AAC_DEBUG */ ! #ifdef AAC_DEBUG_ALL ! #ifndef GETG0COUNT ! #define GETG0COUNT(cdb) (cdb)->g0_count0 ! #endif ! #ifndef GETG1COUNT ! #define GETG1COUNT(cdb) (((cdb)->g1_count1 << 8) + ((cdb)->g1_count0)) ! #endif ! #ifndef GETG4COUNT ! #define GETG4COUNT(cdb) (((cdb)->g4_count3 << 24) + \ ! ((cdb)->g4_count2 << 16) + ((cdb)->g4_count1 << 8) + ((cdb)->g4_count0)) ! #endif ! static void aac_print_scmd(struct aac_softstate *, struct aac_cmd *); ! static void aac_print_aif(struct aac_softstate *, struct aac_aif_command *); ! #endif /* AAC_DEBUG_ALL */ static struct cb_ops aac_cb_ops = { aac_open, /* open */ aac_close, /* close */ nodev, /* strategy */
*** 446,465 **** }; static struct dev_ops aac_dev_ops = { DEVO_REV, 0, ! aac_getinfo, nulldev, nulldev, aac_attach, aac_detach, aac_reset, &aac_cb_ops, NULL, ! NULL, ! aac_quiesce, }; static struct modldrv aac_modldrv = { &mod_driverops, "AAC Driver " AAC_DRIVER_VERSION, --- 458,476 ---- }; static struct dev_ops aac_dev_ops = { DEVO_REV, 0, ! nodev, nulldev, nulldev, aac_attach, aac_detach, aac_reset, &aac_cb_ops, NULL, ! NULL }; static struct modldrv aac_modldrv = { &mod_driverops, "AAC Driver " AAC_DRIVER_VERSION,
*** 609,634 **** /* * Hardware access functions for i960 based cards */ static struct aac_interface aac_rx_interface = { aac_rx_get_fwstatus, aac_rx_get_mailbox, ! aac_rx_set_mailbox }; /* * Hardware access functions for Rocket based cards */ static struct aac_interface aac_rkt_interface = { aac_rkt_get_fwstatus, aac_rkt_get_mailbox, ! aac_rkt_set_mailbox }; ddi_device_acc_attr_t aac_acc_attr = { ! DDI_DEVICE_ATTR_V1, DDI_STRUCTURE_LE_ACC, DDI_STRICTORDER_ACC, DDI_DEFAULT_ACC }; --- 620,683 ---- /* * Hardware access functions for i960 based cards */ static struct aac_interface aac_rx_interface = { + aac_rx_set_intr, + aac_rx_status_clr, + aac_rx_status_get, + aac_rx_notify, aac_rx_get_fwstatus, aac_rx_get_mailbox, ! aac_rx_set_mailbox, ! aac_rx_send_command }; /* * Hardware access functions for Rocket based cards */ static struct aac_interface aac_rkt_interface = { + aac_rx_set_intr, + aac_rx_status_clr, + aac_rx_status_get, + aac_rx_notify, aac_rkt_get_fwstatus, aac_rkt_get_mailbox, ! aac_rkt_set_mailbox, ! aac_rx_send_command }; + /* + * Hardware access functions for PMC SRC based cards + */ + static struct aac_interface aac_src_interface = { + aac_src_set_intr, + aac_src_status_clr, + aac_src_status_get, + aac_src_notify, + aac_src_get_fwstatus, + aac_src_get_mailbox, + aac_src_set_mailbox, + aac_src_send_command + }; + + /* + * Hardware access functions for PMC SRCv based cards + */ + static struct aac_interface aac_srcv_interface = { + aac_src_set_intr, + aac_src_status_clr, + aac_src_status_get, + aac_src_notify, + aac_src_get_fwstatus, + aac_srcv_get_mailbox, + aac_srcv_set_mailbox, + aac_src_send_command + }; + ddi_device_acc_attr_t aac_acc_attr = { ! DDI_DEVICE_ATTR_V0, DDI_STRUCTURE_LE_ACC, DDI_STRICTORDER_ACC, DDI_DEFAULT_ACC };
*** 662,673 **** --- 711,731 ---- 1, /* s/g list length */ AAC_BLK_SIZE, /* granularity of device */ 0 /* DMA transfer flags */ }; + struct aac_drinfo { + struct aac_softstate *softs; + int tgt; + int lun; + int event; + }; + static int aac_tick = AAC_DEFAULT_TICK; /* tick for the internal timer */ static uint32_t aac_timebase = 0; /* internal timer in seconds */ + static uint32_t aac_sync_time = 0; /* next time to sync. with firmware */ + static int aac_fm_valid = 0; /* FMA support */ /* * Warlock directives * * Different variables with the same types have to be protected by the
*** 685,702 **** _NOTE(SCHEME_PROTECTS_DATA("unique per aac_fib", aac_blockread aac_blockwrite \ aac_blockread64 aac_raw_io aac_sg_entry aac_sg_entry64 aac_sg_entryraw \ aac_sg_table aac_srb)) _NOTE(SCHEME_PROTECTS_DATA("unique to sync fib and cdb", scsi_inquiry)) _NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_device scsi_address)) _NOTE(SCHEME_PROTECTS_DATA("unique to scsi_transport", buf)) int _init(void) { int rval = 0; ! #ifdef DEBUG mutex_init(&aac_prt_mutex, NULL, MUTEX_DRIVER, NULL); #endif DBCALLED(NULL, 1); if ((rval = ddi_soft_state_init((void *)&aac_softstatep, --- 743,761 ---- _NOTE(SCHEME_PROTECTS_DATA("unique per aac_fib", aac_blockread aac_blockwrite \ aac_blockread64 aac_raw_io aac_sg_entry aac_sg_entry64 aac_sg_entryraw \ aac_sg_table aac_srb)) _NOTE(SCHEME_PROTECTS_DATA("unique to sync fib and cdb", scsi_inquiry)) _NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_device scsi_address)) + _NOTE(SCHEME_PROTECTS_DATA("unique to dr event", aac_drinfo)) _NOTE(SCHEME_PROTECTS_DATA("unique to scsi_transport", buf)) int _init(void) { int rval = 0; ! #ifdef AAC_DEBUG mutex_init(&aac_prt_mutex, NULL, MUTEX_DRIVER, NULL); #endif DBCALLED(NULL, 1); if ((rval = ddi_soft_state_init((void *)&aac_softstatep,
*** 715,725 **** } return (rval); error: AACDB_PRINT(NULL, CE_WARN, "Mod init error!"); ! #ifdef DEBUG mutex_destroy(&aac_prt_mutex); #endif return (rval); } --- 774,784 ---- } return (rval); error: AACDB_PRINT(NULL, CE_WARN, "Mod init error!"); ! #ifdef AAC_DEBUG mutex_destroy(&aac_prt_mutex); #endif return (rval); }
*** 744,754 **** if ((rval = mod_remove(&aac_modlinkage)) != 0) goto error; scsi_hba_fini(&aac_modlinkage); ddi_soft_state_fini((void *)&aac_softstatep); ! #ifdef DEBUG mutex_destroy(&aac_prt_mutex); #endif return (0); error: --- 803,813 ---- if ((rval = mod_remove(&aac_modlinkage)) != 0) goto error; scsi_hba_fini(&aac_modlinkage); ddi_soft_state_fini((void *)&aac_softstatep); ! #ifdef AAC_DEBUG mutex_destroy(&aac_prt_mutex); #endif return (0); error:
*** 757,767 **** } static int aac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { ! int instance, i; struct aac_softstate *softs = NULL; int attach_state = 0; char *data; DBCALLED(NULL, 1); --- 816,826 ---- } static int aac_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { ! int instance, i, major, minor; struct aac_softstate *softs = NULL; int attach_state = 0; char *data; DBCALLED(NULL, 1);
*** 787,894 **** softs->instance = instance; softs->devinfo_p = dip; softs->buf_dma_attr = softs->addr_dma_attr = aac_dma_attr; softs->addr_dma_attr.dma_attr_granular = 1; - softs->acc_attr = aac_acc_attr; - softs->reg_attr = aac_acc_attr; softs->card = AAC_UNKNOWN_CARD; ! #ifdef DEBUG softs->debug_flags = aac_debug_flags; - softs->debug_fib_flags = aac_debug_fib_flags; #endif - /* Initialize FMA */ - aac_fm_init(softs); - /* Check the card type */ if (aac_check_card_type(softs) == AACERR) { AACDB_PRINT(softs, CE_WARN, "Card not supported"); goto error; } /* We have found the right card and everything is OK */ attach_state |= AAC_ATTACH_CARD_DETECTED; /* Map PCI mem space */ if (ddi_regs_map_setup(dip, 1, ! (caddr_t *)&softs->pci_mem_base_vaddr, 0, ! softs->map_size_min, &softs->reg_attr, ! &softs->pci_mem_handle) != DDI_SUCCESS) goto error; softs->map_size = softs->map_size_min; attach_state |= AAC_ATTACH_PCI_MEM_MAPPED; ! AAC_DISABLE_INTR(softs); ! /* Init mutexes and condvars */ ! mutex_init(&softs->io_lock, NULL, MUTEX_DRIVER, ! DDI_INTR_PRI(softs->intr_pri)); ! mutex_init(&softs->q_comp_mutex, NULL, MUTEX_DRIVER, ! DDI_INTR_PRI(softs->intr_pri)); ! mutex_init(&softs->time_mutex, NULL, MUTEX_DRIVER, ! DDI_INTR_PRI(softs->intr_pri)); ! mutex_init(&softs->ev_lock, NULL, MUTEX_DRIVER, ! DDI_INTR_PRI(softs->intr_pri)); ! mutex_init(&softs->aifq_mutex, NULL, ! MUTEX_DRIVER, DDI_INTR_PRI(softs->intr_pri)); cv_init(&softs->event, NULL, CV_DRIVER, NULL); ! cv_init(&softs->sync_fib_cv, NULL, CV_DRIVER, NULL); cv_init(&softs->drain_cv, NULL, CV_DRIVER, NULL); ! cv_init(&softs->event_wait_cv, NULL, CV_DRIVER, NULL); ! cv_init(&softs->event_disp_cv, NULL, CV_DRIVER, NULL); ! cv_init(&softs->aifq_cv, NULL, CV_DRIVER, NULL); attach_state |= AAC_ATTACH_KMUTEX_INITED; - /* Init the cmd queues */ - for (i = 0; i < AAC_CMDQ_NUM; i++) - aac_cmd_initq(&softs->q_wait[i]); - aac_cmd_initq(&softs->q_busy); - aac_cmd_initq(&softs->q_comp); - /* Check for legacy device naming support */ - softs->legacy = 1; /* default to use legacy name */ if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0, "legacy-name-enable", &data) == DDI_SUCCESS)) { ! if (strcmp(data, "no") == 0) { ! AACDB_PRINT(softs, CE_NOTE, "legacy-name disabled"); ! softs->legacy = 0; } ddi_prop_free(data); } ! ! /* ! * Everything has been set up till now, ! * we will do some common attach. ! */ ! mutex_enter(&softs->io_lock); ! if (aac_common_attach(softs) == AACERR) { ! mutex_exit(&softs->io_lock); ! goto error; } ! mutex_exit(&softs->io_lock); ! attach_state |= AAC_ATTACH_COMM_SPACE_SETUP; ! ! /* Check for buf breakup support */ if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0, ! "breakup-enable", &data) == DDI_SUCCESS)) { if (strcmp(data, "yes") == 0) { ! AACDB_PRINT(softs, CE_NOTE, "buf breakup enabled"); ! softs->flags |= AAC_FLAGS_BRKUP; } ddi_prop_free(data); } ! softs->dma_max = softs->buf_dma_attr.dma_attr_maxxfer; ! if (softs->flags & AAC_FLAGS_BRKUP) { ! softs->dma_max = ddi_prop_get_int(DDI_DEV_T_ANY, dip, ! DDI_PROP_DONTPASS, "dma-max", softs->dma_max); } if (aac_hba_setup(softs) != AACOK) goto error; attach_state |= AAC_ATTACH_SCSI_TRAN_SETUP; /* Create devctl/scsi nodes for cfgadm */ if (ddi_create_minor_node(dip, "devctl", S_IFCHR, INST2DEVCTL(instance), DDI_NT_SCSI_NEXUS, 0) != DDI_SUCCESS) { AACDB_PRINT(softs, CE_WARN, "failed to create devctl node"); goto error; --- 846,1021 ---- softs->instance = instance; softs->devinfo_p = dip; softs->buf_dma_attr = softs->addr_dma_attr = aac_dma_attr; softs->addr_dma_attr.dma_attr_granular = 1; softs->card = AAC_UNKNOWN_CARD; ! #ifdef AAC_DEBUG softs->debug_flags = aac_debug_flags; #endif /* Check the card type */ if (aac_check_card_type(softs) == AACERR) { AACDB_PRINT(softs, CE_WARN, "Card not supported"); goto error; } /* We have found the right card and everything is OK */ attach_state |= AAC_ATTACH_CARD_DETECTED; + /* + * Initialize FMA + */ + #ifdef FORCE_FM_SUPPORT + aac_fm_valid = 1; + #else + aac_fm_valid = 0; + /* check OS version */ + data = (char *)utsname.release; + major = aac_atoi(&data); + if (*data == '.') { + data++; + minor = aac_atoi(&data); + /* enable FMA support in Solaris 11 first */ + if (major >= 5 && minor >= 11) + aac_fm_valid = 1; + } + #endif + aac_fm_init(softs); + /* Map PCI mem space */ if (ddi_regs_map_setup(dip, 1, ! (caddr_t *)&softs->pci_mem_base_vaddr[0], 0, ! softs->map_size_min, &aac_acc_attr, ! &softs->pci_mem_handle[0]) != DDI_SUCCESS) goto error; + if (softs->hwif == AAC_HWIF_SRC) { + /* + * Map whole space because map_size_min is not enough + * for NEMER/ARK family with APRE + */ + if (ddi_regs_map_setup(dip, 2, + (caddr_t *)&softs->pci_mem_base_vaddr[1], 0, + softs->hwif == AAC_HWIF_SRC ? AAC_MAP_SIZE_MIN_SRC_BAR1 : AAC_MAP_SIZE_MIN_SRCV_BAR1, + &aac_acc_attr, + &softs->pci_mem_handle[1]) != DDI_SUCCESS) { + ddi_regs_map_free(&softs->pci_mem_handle[0]); + goto error; + } + } else { + /* Setup BAR1 related values */ + softs->pci_mem_handle[1] = softs->pci_mem_handle[0]; + softs->pci_mem_base_vaddr[1] = softs->pci_mem_base_vaddr[0]; + } softs->map_size = softs->map_size_min; attach_state |= AAC_ATTACH_PCI_MEM_MAPPED; ! AAC_SET_INTR(softs, 0); ! if (ddi_intr_hilevel(dip, 0)) { ! AACDB_PRINT(softs, CE_WARN, ! "High level interrupt is not supported!"); ! goto error; ! } ! ! /* Init mutexes */ ! if (ddi_get_iblock_cookie(dip, 0, &softs->iblock_cookie) != ! DDI_SUCCESS) { ! AACDB_PRINT(softs, CE_WARN, ! "Can not get interrupt block cookie!"); ! goto error; ! } ! mutex_init(&softs->q_comp_mutex, NULL, ! MUTEX_DRIVER, (void *)softs->iblock_cookie); cv_init(&softs->event, NULL, CV_DRIVER, NULL); ! mutex_init(&softs->aifq_mutex, NULL, ! MUTEX_DRIVER, (void *)softs->iblock_cookie); ! cv_init(&softs->aifv, NULL, CV_DRIVER, NULL); cv_init(&softs->drain_cv, NULL, CV_DRIVER, NULL); ! mutex_init(&softs->io_lock, NULL, MUTEX_DRIVER, ! (void *)softs->iblock_cookie); attach_state |= AAC_ATTACH_KMUTEX_INITED; /* Check for legacy device naming support */ if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0, "legacy-name-enable", &data) == DDI_SUCCESS)) { ! if (strcmp(data, "yes") == 0) { ! AACDB_PRINT(softs, CE_NOTE, "aac-legacy-name enabled"); ! softs->legacy = 1; } ddi_prop_free(data); } ! /* Check for sync. transfer mode */ ! if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0, ! "enforce-sync-mode", &data) == DDI_SUCCESS)) { ! if (strcmp(data, "yes") == 0) { ! AACDB_PRINT(softs, CE_NOTE, "enforce-sync-mode set"); ! softs->sync_mode = 1; } ! ddi_prop_free(data); ! } ! /* Convert S/G table (NEW_COMM_TYPE2) */ if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0, ! "disable-sgl-conversion", &data) == DDI_SUCCESS)) { if (strcmp(data, "yes") == 0) { ! AACDB_PRINT(softs, CE_NOTE, "disable-sgl-conversion set"); ! softs->no_sgl_conv = 1; } ddi_prop_free(data); } ! ! /* Create a taskq for dealing with dr events, suspend taskq */ ! if ((softs->taskq = ddi_taskq_create(dip, "aac_dr_taskq", 1, ! TASKQ_DEFAULTPRI, 0)) == NULL) { ! AACDB_PRINT(softs, CE_WARN, "ddi_taskq_create failed"); ! goto error; } + ddi_taskq_suspend(softs->taskq); + /* + * Everything has been set up till now (especially taskq and hba_tran + * for auto-enumeration), we will do some common attach. + */ + if (aac_common_attach(softs) == AACERR) + goto error; + attach_state |= AAC_ATTACH_COMM_SPACE_SETUP; + + /* Init the cmd queues */ + for (i = 0; i < AAC_CMDQ_NUM; i++) + aac_cmd_initq(&softs->q_wait[i]); + aac_cmd_initq(&softs->q_busy); + aac_cmd_initq(&softs->q_comp); + + /* allocate and fill the scsi_hba_tran_t structure */ if (aac_hba_setup(softs) != AACOK) goto error; attach_state |= AAC_ATTACH_SCSI_TRAN_SETUP; + /* scsi_hba_tran is now initialized, resume taskq */ + ddi_taskq_resume(softs->taskq); + + /* Connect interrupt handlers */ + if (ddi_add_softintr(dip, DDI_SOFTINT_LOW, &softs->softint_id, + NULL, NULL, aac_softintr, (caddr_t)softs) != DDI_SUCCESS) { + AACDB_PRINT(softs, CE_WARN, + "Can not setup soft interrupt handler!"); + goto error; + } + attach_state |= AAC_ATTACH_SOFT_INTR_SETUP; + + /* Solaris 11 Express: avoid tran_start calls before aac_unhold_bus() */ + mutex_enter(&softs->io_lock); + + if (ddi_add_intr(dip, 0, &softs->iblock_cookie, + (ddi_idevice_cookie_t *)0, + (softs->flags & AAC_FLAGS_NEW_COMM) ? + aac_intr_new : aac_intr_old, (caddr_t)softs) != DDI_SUCCESS) { + AACDB_PRINT(softs, CE_WARN, "Can not setup interrupt handler!"); + goto error; + } + attach_state |= AAC_ATTACH_HARD_INTR_SETUP; + /* Create devctl/scsi nodes for cfgadm */ if (ddi_create_minor_node(dip, "devctl", S_IFCHR, INST2DEVCTL(instance), DDI_NT_SCSI_NEXUS, 0) != DDI_SUCCESS) { AACDB_PRINT(softs, CE_WARN, "failed to create devctl node"); goto error;
*** 907,940 **** DDI_PSEUDO, 0) != DDI_SUCCESS) { AACDB_PRINT(softs, CE_WARN, "failed to create aac node"); goto error; } - /* Common attach is OK, so we are attached! */ - softs->state |= AAC_STATE_RUN; - - /* Create event thread */ - softs->fibctx_p = &softs->aifctx; - if ((softs->event_thread = thread_create(NULL, 0, aac_event_thread, - softs, 0, &p0, TS_RUN, minclsyspri)) == NULL) { - AACDB_PRINT(softs, CE_WARN, "aif thread create failed"); - softs->state &= ~AAC_STATE_RUN; - goto error; - } - aac_unhold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC); /* Create a thread for command timeout */ ! softs->timeout_id = timeout(aac_timer, (void *)softs, ! (aac_tick * drv_usectohz(1000000))); /* Common attach is OK, so we are attached! */ ddi_report_dev(dip); AACDB_PRINT(softs, CE_NOTE, "aac attached ok"); return (DDI_SUCCESS); error: if (attach_state & AAC_ATTACH_CREATE_SCSI) ddi_remove_minor_node(dip, "scsi"); if (attach_state & AAC_ATTACH_CREATE_DEVCTL) ddi_remove_minor_node(dip, "devctl"); if (attach_state & AAC_ATTACH_COMM_SPACE_SETUP) --- 1034,1060 ---- DDI_PSEUDO, 0) != DDI_SUCCESS) { AACDB_PRINT(softs, CE_WARN, "failed to create aac node"); goto error; } aac_unhold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC); + softs->state = AAC_STATE_RUN; + mutex_exit(&softs->io_lock); /* Create a thread for command timeout */ ! softs->timeout_id = timeout(aac_daemon, (void *)softs, ! (60 * drv_usectohz(1000000))); /* Common attach is OK, so we are attached! */ + AAC_SET_INTR(softs, 1); ddi_report_dev(dip); AACDB_PRINT(softs, CE_NOTE, "aac attached ok"); return (DDI_SUCCESS); error: + if (softs && softs->taskq) + ddi_taskq_destroy(softs->taskq); if (attach_state & AAC_ATTACH_CREATE_SCSI) ddi_remove_minor_node(dip, "scsi"); if (attach_state & AAC_ATTACH_CREATE_DEVCTL) ddi_remove_minor_node(dip, "devctl"); if (attach_state & AAC_ATTACH_COMM_SPACE_SETUP)
*** 941,965 **** aac_common_detach(softs); if (attach_state & AAC_ATTACH_SCSI_TRAN_SETUP) { (void) scsi_hba_detach(dip); scsi_hba_tran_free(AAC_DIP2TRAN(dip)); } if (attach_state & AAC_ATTACH_KMUTEX_INITED) { - mutex_destroy(&softs->io_lock); mutex_destroy(&softs->q_comp_mutex); - mutex_destroy(&softs->time_mutex); - mutex_destroy(&softs->ev_lock); - mutex_destroy(&softs->aifq_mutex); cv_destroy(&softs->event); ! cv_destroy(&softs->sync_fib_cv); cv_destroy(&softs->drain_cv); ! cv_destroy(&softs->event_wait_cv); ! cv_destroy(&softs->event_disp_cv); ! cv_destroy(&softs->aifq_cv); } ! if (attach_state & AAC_ATTACH_PCI_MEM_MAPPED) ! ddi_regs_map_free(&softs->pci_mem_handle); aac_fm_fini(softs); if (attach_state & AAC_ATTACH_CARD_DETECTED) softs->card = AACERR; if (attach_state & AAC_ATTACH_SOFTSTATE_ALLOCED) ddi_soft_state_free(aac_softstatep, instance); --- 1061,1087 ---- aac_common_detach(softs); if (attach_state & AAC_ATTACH_SCSI_TRAN_SETUP) { (void) scsi_hba_detach(dip); scsi_hba_tran_free(AAC_DIP2TRAN(dip)); } + if (attach_state & AAC_ATTACH_HARD_INTR_SETUP) + ddi_remove_intr(dip, 0, softs->iblock_cookie); + if (attach_state & AAC_ATTACH_SOFT_INTR_SETUP) + ddi_remove_softintr(softs->softint_id); if (attach_state & AAC_ATTACH_KMUTEX_INITED) { mutex_destroy(&softs->q_comp_mutex); cv_destroy(&softs->event); ! mutex_destroy(&softs->aifq_mutex); ! cv_destroy(&softs->aifv); cv_destroy(&softs->drain_cv); ! mutex_destroy(&softs->io_lock); } ! if (attach_state & AAC_ATTACH_PCI_MEM_MAPPED) { ! ddi_regs_map_free(&softs->pci_mem_handle[0]); ! if (softs->hwif == AAC_HWIF_SRC) ! ddi_regs_map_free(&softs->pci_mem_handle[1]); ! } aac_fm_fini(softs); if (attach_state & AAC_ATTACH_CARD_DETECTED) softs->card = AACERR; if (attach_state & AAC_ATTACH_SOFTSTATE_ALLOCED) ddi_soft_state_free(aac_softstatep, instance);
*** 982,1037 **** default: return (DDI_FAILURE); } mutex_enter(&softs->io_lock); ! AAC_DISABLE_INTR(softs); softs->state = AAC_STATE_STOPPED; ddi_remove_minor_node(dip, "aac"); ddi_remove_minor_node(dip, "scsi"); ddi_remove_minor_node(dip, "devctl"); mutex_exit(&softs->io_lock); aac_common_detach(softs); - mutex_enter(&softs->io_lock); (void) scsi_hba_detach(dip); scsi_hba_tran_free(tran); - mutex_exit(&softs->io_lock); ! /* Stop timer */ ! mutex_enter(&softs->time_mutex); ! if (softs->timeout_id) { ! timeout_id_t tid = softs->timeout_id; ! softs->timeout_id = 0; ! ! mutex_exit(&softs->time_mutex); ! (void) untimeout(tid); ! mutex_enter(&softs->time_mutex); ! } ! mutex_exit(&softs->time_mutex); ! ! /* Destroy event thread */ ! mutex_enter(&softs->ev_lock); ! cv_signal(&softs->event_disp_cv); ! cv_wait(&softs->event_wait_cv, &softs->ev_lock); ! mutex_exit(&softs->ev_lock); ! ! cv_destroy(&softs->aifq_cv); ! cv_destroy(&softs->event_disp_cv); ! cv_destroy(&softs->event_wait_cv); ! cv_destroy(&softs->drain_cv); ! cv_destroy(&softs->sync_fib_cv); cv_destroy(&softs->event); mutex_destroy(&softs->aifq_mutex); ! mutex_destroy(&softs->ev_lock); ! mutex_destroy(&softs->time_mutex); ! mutex_destroy(&softs->q_comp_mutex); mutex_destroy(&softs->io_lock); ! ddi_regs_map_free(&softs->pci_mem_handle); aac_fm_fini(softs); softs->hwif = AAC_HWIF_UNKNOWN; softs->card = AAC_UNKNOWN_CARD; ddi_soft_state_free(aac_softstatep, ddi_get_instance(dip)); --- 1104,1146 ---- default: return (DDI_FAILURE); } mutex_enter(&softs->io_lock); ! AAC_SET_INTR(softs, 0); softs->state = AAC_STATE_STOPPED; + mutex_exit(&softs->io_lock); + (void) untimeout(softs->timeout_id); + mutex_enter(&softs->io_lock); + softs->timeout_id = 0; + + ddi_taskq_destroy(softs->taskq); + ddi_remove_minor_node(dip, "aac"); ddi_remove_minor_node(dip, "scsi"); ddi_remove_minor_node(dip, "devctl"); + mutex_exit(&softs->io_lock); + ddi_remove_intr(dip, 0, softs->iblock_cookie); + ddi_remove_softintr(softs->softint_id); aac_common_detach(softs); (void) scsi_hba_detach(dip); scsi_hba_tran_free(tran); ! mutex_destroy(&softs->q_comp_mutex); cv_destroy(&softs->event); mutex_destroy(&softs->aifq_mutex); ! cv_destroy(&softs->aifv); ! cv_destroy(&softs->drain_cv); mutex_destroy(&softs->io_lock); ! ddi_regs_map_free(&softs->pci_mem_handle[0]); ! if (softs->hwif == AAC_HWIF_SRC) ! ddi_regs_map_free(&softs->pci_mem_handle[1]); aac_fm_fini(softs); softs->hwif = AAC_HWIF_UNKNOWN; softs->card = AAC_UNKNOWN_CARD; ddi_soft_state_free(aac_softstatep, ddi_get_instance(dip));
*** 1045,1166 **** struct aac_softstate *softs = AAC_DIP2SOFTS(dip); DBCALLED(softs, 1); mutex_enter(&softs->io_lock); - AAC_DISABLE_INTR(softs); (void) aac_shutdown(softs); mutex_exit(&softs->io_lock); return (DDI_SUCCESS); } /* - * quiesce(9E) entry point. - * - * This function is called when the system is single-threaded at high - * PIL with preemption disabled. Therefore, this function must not be - * blocked. - * - * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. - * DDI_FAILURE indicates an error condition and should almost never happen. - */ - static int - aac_quiesce(dev_info_t *dip) - { - struct aac_softstate *softs = AAC_DIP2SOFTS(dip); - - if (softs == NULL) - return (DDI_FAILURE); - - _NOTE(ASSUMING_PROTECTED(softs->state)) - AAC_DISABLE_INTR(softs); - - return (DDI_SUCCESS); - } - - /* ARGSUSED */ - static int - aac_getinfo(dev_info_t *self, ddi_info_cmd_t infocmd, void *arg, - void **result) - { - int error = DDI_SUCCESS; - - switch (infocmd) { - case DDI_INFO_DEVT2INSTANCE: - *result = (void *)(intptr_t)(MINOR2INST(getminor((dev_t)arg))); - break; - default: - error = DDI_FAILURE; - } - return (error); - } - - /* * Bring the controller down to a dormant state and detach all child devices. * This function is called before detach or system shutdown. * Note: we can assume that the q_wait on the controller is empty, as we * won't allow shutdown if any device is open. */ static int aac_shutdown(struct aac_softstate *softs) { ! ddi_acc_handle_t acc; ! struct aac_close_command *cc; int rval; - (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac); - acc = softs->sync_ac.slotp->fib_acc_handle; - - cc = (struct aac_close_command *)&softs->sync_ac.slotp->fibp->data[0]; - ddi_put32(acc, &cc->Command, VM_CloseAll); ddi_put32(acc, &cc->ContainerId, 0xfffffffful); /* Flush all caches, set FW to write through mode */ rval = aac_sync_fib(softs, ContainerCommand, AAC_FIB_SIZEOF(struct aac_close_command)); - aac_sync_fib_slot_release(softs, &softs->sync_ac); AACDB_PRINT(softs, CE_NOTE, "shutting down aac %s", (rval == AACOK) ? "ok" : "fail"); return (rval); } static uint_t aac_softintr(caddr_t arg) { ! struct aac_softstate *softs = (void *)arg; if (!AAC_IS_Q_EMPTY(&softs->q_comp)) { aac_drain_comp_q(softs); - } return (DDI_INTR_CLAIMED); } /* * Setup auto sense data for pkt */ ! static void ! aac_set_arq_data(struct scsi_pkt *pkt, uchar_t key, ! uchar_t add_code, uchar_t qual_code, uint64_t info) { ! struct scsi_arq_status *arqstat = (void *)(pkt->pkt_scbp); ! *pkt->pkt_scbp = STATUS_CHECK; /* CHECK CONDITION */ ! pkt->pkt_state |= STATE_ARQ_DONE; ! *(uint8_t *)&arqstat->sts_rqpkt_status = STATUS_GOOD; arqstat->sts_rqpkt_reason = CMD_CMPLT; arqstat->sts_rqpkt_resid = 0; arqstat->sts_rqpkt_state = STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD | STATE_XFERRED_DATA; arqstat->sts_rqpkt_statistics = 0; if (info <= 0xfffffffful) { arqstat->sts_sensedata.es_valid = 1; arqstat->sts_sensedata.es_class = CLASS_EXTENDED_SENSE; arqstat->sts_sensedata.es_code = CODE_FMT_FIXED_CURRENT; arqstat->sts_sensedata.es_key = key; --- 1154,1255 ---- struct aac_softstate *softs = AAC_DIP2SOFTS(dip); DBCALLED(softs, 1); mutex_enter(&softs->io_lock); (void) aac_shutdown(softs); mutex_exit(&softs->io_lock); return (DDI_SUCCESS); } /* * Bring the controller down to a dormant state and detach all child devices. * This function is called before detach or system shutdown. * Note: we can assume that the q_wait on the controller is empty, as we * won't allow shutdown if any device is open. */ static int aac_shutdown(struct aac_softstate *softs) { ! ddi_acc_handle_t acc = softs->sync_slot->fib_acc_handle; ! struct aac_close_command *cc = (struct aac_close_command *) \ ! &softs->sync_slot->fibp->data[0]; int rval; ddi_put32(acc, &cc->Command, VM_CloseAll); ddi_put32(acc, &cc->ContainerId, 0xfffffffful); /* Flush all caches, set FW to write through mode */ rval = aac_sync_fib(softs, ContainerCommand, AAC_FIB_SIZEOF(struct aac_close_command)); AACDB_PRINT(softs, CE_NOTE, "shutting down aac %s", (rval == AACOK) ? "ok" : "fail"); return (rval); } static uint_t aac_softintr(caddr_t arg) { ! struct aac_softstate *softs = (struct aac_softstate *)arg; if (!AAC_IS_Q_EMPTY(&softs->q_comp)) { aac_drain_comp_q(softs); return (DDI_INTR_CLAIMED); + } else { + return (DDI_INTR_UNCLAIMED); + } } /* * Setup auto sense data for pkt */ ! static struct scsi_arq_status * ! aac_set_arq_common(struct scsi_pkt *pkt) { ! struct scsi_arq_status *arqstat; ! pkt->pkt_state |= STATE_GOT_STATUS | STATE_ARQ_DONE; ! arqstat = (struct scsi_arq_status *)(pkt->pkt_scbp); ! arqstat->sts_status.sts_chk = 1; /* CHECK CONDITION */ arqstat->sts_rqpkt_reason = CMD_CMPLT; arqstat->sts_rqpkt_resid = 0; arqstat->sts_rqpkt_state = STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD | STATE_XFERRED_DATA; arqstat->sts_rqpkt_statistics = 0; + return (arqstat); + } + + static void + aac_copy_arq_data(struct scsi_pkt *pkt, uint8_t *sense_data, int32_t sense_len, + ddi_acc_handle_t acc) + { + struct scsi_arq_status *arqstat; + + arqstat = aac_set_arq_common(pkt); + + if (sense_len > sizeof (struct scsi_extended_sense)) + sense_len = sizeof (struct scsi_extended_sense); + + ddi_rep_get8(acc, (uint8_t *)&arqstat->sts_sensedata, + (uint8_t *)sense_data, sense_len, DDI_DEV_AUTOINCR); + } + + static void + aac_set_arq_data(struct scsi_pkt *pkt, uchar_t key, + uchar_t add_code, uchar_t qual_code, uint64_t info) + { + struct scsi_arq_status *arqstat; + + arqstat = aac_set_arq_common(pkt); + if (info <= 0xfffffffful) { arqstat->sts_sensedata.es_valid = 1; arqstat->sts_sensedata.es_class = CLASS_EXTENDED_SENSE; arqstat->sts_sensedata.es_code = CODE_FMT_FIXED_CURRENT; arqstat->sts_sensedata.es_key = key;
*** 1205,1317 **** aac_set_arq_data_hwerr(struct aac_cmd *acp) { union scsi_cdb *cdbp; uint64_t err_blkno; ! cdbp = (void *)acp->pkt->pkt_cdbp; err_blkno = AAC_GETGXADDR(acp->cmdlen, cdbp); aac_set_arq_data(acp->pkt, KEY_HARDWARE_ERROR, 0x00, 0x00, err_blkno); } /* ! * Send a command to the adapter in New Comm. interface */ ! static int ! aac_send_command(struct aac_softstate *softs, struct aac_slot *slotp) { ! uint32_t index, device; ! index = PCI_MEM_GET32(softs, AAC_IQUE); ! if (index == 0xffffffffUL) { ! index = PCI_MEM_GET32(softs, AAC_IQUE); ! if (index == 0xffffffffUL) ! return (AACERR); ! } ! device = index; ! PCI_MEM_PUT32(softs, device, ! (uint32_t)(slotp->fib_phyaddr & 0xfffffffful)); ! device += 4; ! PCI_MEM_PUT32(softs, device, (uint32_t)(slotp->fib_phyaddr >> 32)); ! device += 4; ! PCI_MEM_PUT32(softs, device, slotp->acp->fib_size); ! PCI_MEM_PUT32(softs, AAC_IQUE, index); ! return (AACOK); } static void aac_end_io(struct aac_softstate *softs, struct aac_cmd *acp) { struct aac_device *dvp = acp->dvp; int q = AAC_CMDQ(acp); if (acp->slotp) { /* outstanding cmd */ - if (!(acp->flags & AAC_CMD_IN_SYNC_SLOT)) { aac_release_slot(softs, acp->slotp); acp->slotp = NULL; - } if (dvp) { dvp->ncmds[q]--; if (dvp->throttle[q] == AAC_THROTTLE_DRAIN && dvp->ncmds[q] == 0 && q == AAC_CMDQ_ASYNC) aac_set_throttle(softs, dvp, q, softs->total_slots); - /* - * Setup auto sense data for UNIT ATTENTION - * Each lun should generate a unit attention - * condition when reset. - * Phys. drives are treated as logical ones - * during error recovery. - */ - if (dvp->type == AAC_DEV_LD) { - struct aac_container *ctp = - (struct aac_container *)dvp; - if (ctp->reset == 0) - goto noreset; - - AACDB_PRINT(softs, CE_NOTE, - "Unit attention: reset"); - ctp->reset = 0; - aac_set_arq_data(acp->pkt, KEY_UNIT_ATTENTION, - 0x29, 0x02, 0); } - } - noreset: softs->bus_ncmds[q]--; ! aac_cmd_delete(&softs->q_busy, acp); } else { /* cmd in waiting queue */ aac_cmd_delete(&softs->q_wait[q], acp); } ! if (!(acp->flags & (AAC_CMD_NO_CB | AAC_CMD_NO_INTR))) { /* async IO */ mutex_enter(&softs->q_comp_mutex); aac_cmd_enqueue(&softs->q_comp, acp); mutex_exit(&softs->q_comp_mutex); } else if (acp->flags & AAC_CMD_NO_CB) { /* sync IO */ cv_broadcast(&softs->event); } } static void ! aac_handle_io(struct aac_softstate *softs, int index) { - struct aac_slot *slotp; struct aac_cmd *acp; - uint32_t fast; - fast = index & AAC_SENDERADDR_MASK_FAST_RESPONSE; - index >>= 2; - /* Make sure firmware reported index is valid */ - ASSERT(index >= 0 && index < softs->total_slots); - slotp = &softs->io_slot[index]; - ASSERT(slotp->index == index); acp = slotp->acp; - if (acp == NULL || acp->slotp != slotp) { ! cmn_err(CE_WARN, ! "Firmware error: invalid slot index received from FW"); return; } acp->flags |= AAC_CMD_CMPLT; (void) ddi_dma_sync(slotp->fib_dma_handle, 0, 0, DDI_DMA_SYNC_FORCPU); --- 1294,1375 ---- aac_set_arq_data_hwerr(struct aac_cmd *acp) { union scsi_cdb *cdbp; uint64_t err_blkno; ! cdbp = (union scsi_cdb *)acp->pkt->pkt_cdbp; err_blkno = AAC_GETGXADDR(acp->cmdlen, cdbp); aac_set_arq_data(acp->pkt, KEY_HARDWARE_ERROR, 0x00, 0x00, err_blkno); } /* ! * Setup auto sense data for UNIT ATTENTION */ ! /*ARGSUSED*/ ! static void ! aac_set_arq_data_reset(struct aac_softstate *softs, struct aac_cmd *acp) { ! struct aac_container *dvp = (struct aac_container *)acp->dvp; ! ASSERT(dvp->dev.type == AAC_DEV_LD); ! if (dvp->reset) { ! dvp->reset = 0; ! aac_set_arq_data(acp->pkt, KEY_UNIT_ATTENTION, 0x29, 0x02, 0); ! } } static void aac_end_io(struct aac_softstate *softs, struct aac_cmd *acp) { struct aac_device *dvp = acp->dvp; int q = AAC_CMDQ(acp); if (acp->slotp) { /* outstanding cmd */ aac_release_slot(softs, acp->slotp); acp->slotp = NULL; if (dvp) { dvp->ncmds[q]--; if (dvp->throttle[q] == AAC_THROTTLE_DRAIN && dvp->ncmds[q] == 0 && q == AAC_CMDQ_ASYNC) aac_set_throttle(softs, dvp, q, softs->total_slots); } softs->bus_ncmds[q]--; ! (void) aac_cmd_delete(&softs->q_busy, acp); } else { /* cmd in waiting queue */ aac_cmd_delete(&softs->q_wait[q], acp); } ! acp->cur_segment++; ! if (acp->cur_segment >= acp->segment_cnt) { ! if (!(acp->flags & (AAC_CMD_NO_CB | AAC_CMD_NO_INTR | AAC_CMD_AIF))) { /* async IO */ mutex_enter(&softs->q_comp_mutex); aac_cmd_enqueue(&softs->q_comp, acp); mutex_exit(&softs->q_comp_mutex); } else if (acp->flags & AAC_CMD_NO_CB) { /* sync IO */ cv_broadcast(&softs->event); } + } else { + acp->flags &= AAC_CMD_CONSISTENT | AAC_CMD_DMA_PARTIAL | \ + AAC_CMD_BUF_READ | AAC_CMD_BUF_WRITE | AAC_CMD_DMA_VALID; + acp->timeout = acp->pkt->pkt_time; + if (acp->pkt->pkt_flags & FLAG_NOINTR) + acp->flags |= AAC_CMD_NO_INTR; + aac_do_io(softs, acp); + } } static void ! aac_handle_io(struct aac_softstate *softs, struct aac_slot *slotp, int fast) { struct aac_cmd *acp; /* Make sure firmware reported index is valid */ acp = slotp->acp; if (acp == NULL || acp->slotp != slotp) { ! AACDB_PRINT(softs, CE_NOTE, "Command already freed, discarding"); return; } acp->flags |= AAC_CMD_CMPLT; (void) ddi_dma_sync(slotp->fib_dma_handle, 0, 0, DDI_DMA_SYNC_FORCPU);
*** 1333,1398 **** */ ddi_put32(slotp->fib_acc_handle, &slotp->fibp->Header.XferState, state | AAC_FIBSTATE_DONEADAP); ddi_put32(slotp->fib_acc_handle, ! (void *)&slotp->fibp->data[0], ST_OK); } /* Handle completed ac */ acp->ac_comp(softs, acp); } else { ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); acp->flags |= AAC_CMD_ERR; if (acp->pkt) { acp->pkt->pkt_reason = CMD_TRAN_ERR; acp->pkt->pkt_statistics = 0; } } aac_end_io(softs, acp); } /* * Interrupt handler for New Comm. interface * New Comm. interface use a different mechanism for interrupt. No explict * message queues, and driver need only accesses the mapped PCI mem space to * find the completed FIB or AIF. */ static int aac_process_intr_new(struct aac_softstate *softs) { uint32_t index; index = AAC_OUTB_GET(softs); if (index == 0xfffffffful) index = AAC_OUTB_GET(softs); ! if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) { ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); ! return (0); } if (index != 0xfffffffful) { do { if ((index & AAC_SENDERADDR_MASK_AIF) == 0) { ! aac_handle_io(softs, index); } else if (index != 0xfffffffeul) { struct aac_fib *fibp; /* FIB in AIF queue */ ! uint16_t fib_size; /* * 0xfffffffe means that the controller wants * more work, ignore it for now. Otherwise, * AIF received. */ index &= ~2; ! fibp = (struct aac_fib *)(softs-> \ ! pci_mem_base_vaddr + index); ! fib_size = PCI_MEM_GET16(softs, index + \ offsetof(struct aac_fib, Header.Size)); ! aac_save_aif(softs, softs->pci_mem_handle, ! fibp, fib_size); /* * AIF memory is owned by the adapter, so let it * know that we are done with it. */ --- 1391,1554 ---- */ ddi_put32(slotp->fib_acc_handle, &slotp->fibp->Header.XferState, state | AAC_FIBSTATE_DONEADAP); ddi_put32(slotp->fib_acc_handle, ! (uint32_t *)&slotp->fibp->data[0], ST_OK); ! acp->flags |= AAC_CMD_FASTRESP; } /* Handle completed ac */ + if (acp->cur_segment + 1 >= acp->segment_cnt) acp->ac_comp(softs, acp); } else { ! aac_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); acp->flags |= AAC_CMD_ERR; if (acp->pkt) { acp->pkt->pkt_reason = CMD_TRAN_ERR; acp->pkt->pkt_statistics = 0; } + acp->cur_segment = acp->segment_cnt - 1; } aac_end_io(softs, acp); } /* + * Interrupt handler for New Comm. Type1 interface + */ + static int + aac_process_intr_new_type1(struct aac_softstate *softs) + { + struct aac_cmd *acp; + uint32_t bellbits, bellbits_shifted, index, handle; + int isFastResponse; + int our_interrupt = 0; + + bellbits = PCI_MEM_GET32(softs, 0, AAC_SRC_ODBR_R); + if (bellbits & AAC_DB_RESPONSE_SENT_NS) { + bellbits = AAC_DB_RESPONSE_SENT_NS; + /* handle async. status */ + our_interrupt = 1; + index = softs->aac_host_rrq_idx; + for (;;) { + isFastResponse = 0; + /* remove toggle bit (31) */ + handle = (softs->comm_space->aac_host_rrq[index] & 0x7fffffff); + /* check fast response bit (30) */ + if (handle & 0x40000000) + isFastResponse = 1; + + handle &= 0x0000ffff; + if (handle == 0) + break; + + acp = softs->io_slot[handle-1].acp; + ASSERT((handle-1) >= 0 && (handle-1) < softs->total_slots); + aac_handle_io(softs, &softs->io_slot[handle-1], isFastResponse); + + softs->comm_space->aac_host_rrq[index++] = 0; + if (index == softs->aac_max_fibs) + index = 0; + softs->aac_host_rrq_idx = index; + + if (acp && (acp->flags & AAC_CMD_AIF)) { + if (acp->flags & AAC_CMD_AIF_NOMORE) { + kmem_free(acp, sizeof(struct aac_cmd)); + } else { + acp->timeout = AAC_AIF_TIMEOUT; + acp->aac_cmd_fib = aac_cmd_aif_request; + acp->ac_comp = aac_aifreq_complete; + aac_do_io(softs, acp); + } + } + } + } else { + bellbits_shifted = (bellbits >> AAC_SRC_ODR_SHIFT); + if (bellbits_shifted & AAC_DB_AIF_PENDING) { + our_interrupt = 1; + /* handle AIF */ + if ((acp = kmem_zalloc(sizeof(struct aac_cmd), KM_NOSLEEP)) != NULL) { + acp->timeout = AAC_AIF_TIMEOUT; + acp->aac_cmd_fib = aac_cmd_aif_request; + acp->ac_comp = aac_aifreq_complete; + aac_do_io(softs, acp); + } + } else if (bellbits_shifted & AAC_DB_SYNC_COMMAND) { + if (softs->sync_mode_slot) { + our_interrupt = 1; + aac_handle_io(softs, softs->sync_mode_slot, isFastResponse); + softs->sync_slot_busy = 0; + } + } + } + if (our_interrupt) + PCI_MEM_PUT32(softs, 0, AAC_SRC_ODBR_C, bellbits); + + /* + * Process waiting cmds before start new ones to + * ensure first IOs are serviced first. + */ + aac_start_waiting_io(softs); + return (our_interrupt ? AAC_DB_COMMAND_READY:0); + } + + /* * Interrupt handler for New Comm. interface * New Comm. interface use a different mechanism for interrupt. No explict * message queues, and driver need only accesses the mapped PCI mem space to * find the completed FIB or AIF. */ static int aac_process_intr_new(struct aac_softstate *softs) { uint32_t index; + int fast; index = AAC_OUTB_GET(softs); if (index == 0xfffffffful) index = AAC_OUTB_GET(softs); ! if (aac_check_acc_handle(softs->pci_mem_handle[0]) != DDI_SUCCESS) { ! aac_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); ! return (DDI_INTR_UNCLAIMED); } if (index != 0xfffffffful) { do { if ((index & AAC_SENDERADDR_MASK_AIF) == 0) { ! fast= index & AAC_SENDERADDR_MASK_FAST_RESPONSE; ! index >>= 2; ! ASSERT(index >= 0 && index < softs->total_slots); ! aac_handle_io(softs, &softs->io_slot[index], fast); } else if (index != 0xfffffffeul) { struct aac_fib *fibp; /* FIB in AIF queue */ ! uint16_t fib_size, fib_size0; /* * 0xfffffffe means that the controller wants * more work, ignore it for now. Otherwise, * AIF received. */ index &= ~2; ! mutex_enter(&softs->aifq_mutex); ! /* ! * Copy AIF from adapter to the empty AIF slot ! */ ! fibp = &softs->aifq[softs->aifq_idx].d; ! fib_size0 = PCI_MEM_GET16(softs, 0, index + \ offsetof(struct aac_fib, Header.Size)); + fib_size = (fib_size0 > AAC_FIB_SIZE) ? + AAC_FIB_SIZE : fib_size0; + PCI_MEM_REP_GET8(softs, 0, index, fibp, + fib_size); ! if (aac_check_acc_handle(softs-> \ ! pci_mem_handle[0]) == DDI_SUCCESS) ! (void) aac_handle_aif(softs, fibp); ! else ! aac_fm_service_impact(softs->devinfo_p, ! DDI_SERVICE_UNAFFECTED); ! mutex_exit(&softs->aifq_mutex); /* * AIF memory is owned by the adapter, so let it * know that we are done with it. */
*** 1415,1429 **** } static uint_t aac_intr_new(caddr_t arg) { ! struct aac_softstate *softs = (void *)arg; uint_t rval; mutex_enter(&softs->io_lock); ! if (aac_process_intr_new(softs)) rval = DDI_INTR_CLAIMED; else rval = DDI_INTR_UNCLAIMED; mutex_exit(&softs->io_lock); --- 1571,1592 ---- } static uint_t aac_intr_new(caddr_t arg) { ! struct aac_softstate *softs = (struct aac_softstate *)arg; ! int status; uint_t rval; mutex_enter(&softs->io_lock); ! if ((softs->flags & AAC_FLAGS_NEW_COMM_TYPE1) || ! (softs->flags & AAC_FLAGS_NEW_COMM_TYPE2) || ! (softs->flags & AAC_FLAGS_NEW_COMM_TYPE34)) ! status = aac_process_intr_new_type1(softs); ! else ! status = aac_process_intr_new(softs); ! if (status) rval = DDI_INTR_CLAIMED; else rval = DDI_INTR_UNCLAIMED; mutex_exit(&softs->io_lock);
*** 1441,1463 **** aac_process_intr_old(struct aac_softstate *softs) { uint16_t status; status = AAC_STATUS_GET(softs); ! if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) { ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); return (DDI_INTR_UNCLAIMED); } if (status & AAC_DB_RESPONSE_READY) { ! int slot_idx; /* ACK the intr */ AAC_STATUS_CLR(softs, AAC_DB_RESPONSE_READY); (void) AAC_STATUS_GET(softs); while (aac_fib_dequeue(softs, AAC_HOST_NORM_RESP_Q, ! &slot_idx) == AACOK) ! aac_handle_io(softs, slot_idx); /* * Process waiting cmds before start new ones to * ensure first IOs are serviced first. */ --- 1604,1630 ---- aac_process_intr_old(struct aac_softstate *softs) { uint16_t status; status = AAC_STATUS_GET(softs); ! if (aac_check_acc_handle(softs->pci_mem_handle[0]) != DDI_SUCCESS) { ! aac_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); return (DDI_INTR_UNCLAIMED); } if (status & AAC_DB_RESPONSE_READY) { ! int slot_idx, fast; /* ACK the intr */ AAC_STATUS_CLR(softs, AAC_DB_RESPONSE_READY); (void) AAC_STATUS_GET(softs); while (aac_fib_dequeue(softs, AAC_HOST_NORM_RESP_Q, ! &slot_idx) == AACOK) { ! fast = slot_idx & AAC_SENDERADDR_MASK_FAST_RESPONSE; ! slot_idx >>= 2; ! ASSERT(slot_idx >= 0 && slot_idx < softs->total_slots); ! aac_handle_io(softs, &softs->io_slot[slot_idx], fast); ! } /* * Process waiting cmds before start new ones to * ensure first IOs are serviced first. */
*** 1469,1480 **** AAC_STATUS_CLR(softs, AAC_DB_COMMAND_READY); (void) AAC_STATUS_GET(softs); if (aac_fib_dequeue(softs, AAC_HOST_NORM_CMD_Q, &aif_idx) == AACOK) { ddi_acc_handle_t acc = softs->comm_space_acc_handle; ! struct aac_fib *fibp; /* FIB in communication space */ ! uint16_t fib_size; uint32_t fib_xfer_state; uint32_t addr, size; ASSERT((aif_idx >= 0) && (aif_idx < AAC_ADAPTER_FIBS)); --- 1636,1648 ---- AAC_STATUS_CLR(softs, AAC_DB_COMMAND_READY); (void) AAC_STATUS_GET(softs); if (aac_fib_dequeue(softs, AAC_HOST_NORM_CMD_Q, &aif_idx) == AACOK) { ddi_acc_handle_t acc = softs->comm_space_acc_handle; ! struct aac_fib *fibp; /* FIB in AIF queue */ ! struct aac_fib *fibp0; /* FIB in communication space */ ! uint16_t fib_size, fib_size0; uint32_t fib_xfer_state; uint32_t addr, size; ASSERT((aif_idx >= 0) && (aif_idx < AAC_ADAPTER_FIBS));
*** 1482,1506 **** { (void) ddi_dma_sync((softs)->comm_space_dma_handle, \ offsetof(struct aac_comm_space, \ adapter_fibs[(aif_idx)]), AAC_FIB_SIZE, \ (type)); } /* Copy AIF from adapter to the empty AIF slot */ AAC_SYNC_AIF(softs, aif_idx, DDI_DMA_SYNC_FORCPU); ! fibp = &softs->comm_space->adapter_fibs[aif_idx]; ! fib_size = ddi_get16(acc, &fibp->Header.Size); ! aac_save_aif(softs, acc, fibp, fib_size); /* Complete AIF back to adapter with good status */ fib_xfer_state = LE_32(fibp->Header.XferState); if (fib_xfer_state & AAC_FIBSTATE_FROMADAP) { ! ddi_put32(acc, &fibp->Header.XferState, fib_xfer_state | AAC_FIBSTATE_DONEHOST); ! ddi_put32(acc, (void *)&fibp->data[0], ST_OK); ! if (fib_size > AAC_FIB_SIZE) ! ddi_put16(acc, &fibp->Header.Size, AAC_FIB_SIZE); AAC_SYNC_AIF(softs, aif_idx, DDI_DMA_SYNC_FORDEV); } --- 1650,1682 ---- { (void) ddi_dma_sync((softs)->comm_space_dma_handle, \ offsetof(struct aac_comm_space, \ adapter_fibs[(aif_idx)]), AAC_FIB_SIZE, \ (type)); } + mutex_enter(&softs->aifq_mutex); /* Copy AIF from adapter to the empty AIF slot */ + fibp = &softs->aifq[softs->aifq_idx].d; AAC_SYNC_AIF(softs, aif_idx, DDI_DMA_SYNC_FORCPU); ! fibp0 = &softs->comm_space->adapter_fibs[aif_idx]; ! fib_size0 = ddi_get16(acc, &fibp0->Header.Size); ! fib_size = (fib_size0 > AAC_FIB_SIZE) ? ! AAC_FIB_SIZE : fib_size0; ! ddi_rep_get8(acc, (uint8_t *)fibp, (uint8_t *)fibp0, ! fib_size, DDI_DEV_AUTOINCR); ! (void) aac_handle_aif(softs, fibp); ! mutex_exit(&softs->aifq_mutex); /* Complete AIF back to adapter with good status */ fib_xfer_state = LE_32(fibp->Header.XferState); if (fib_xfer_state & AAC_FIBSTATE_FROMADAP) { ! ddi_put32(acc, &fibp0->Header.XferState, fib_xfer_state | AAC_FIBSTATE_DONEHOST); ! ddi_put32(acc, (uint32_t *)&fibp0->data[0], ! ST_OK); ! if (fib_size0 > AAC_FIB_SIZE) ! ddi_put16(acc, &fibp0->Header.Size, AAC_FIB_SIZE); AAC_SYNC_AIF(softs, aif_idx, DDI_DMA_SYNC_FORDEV); }
*** 1511,1521 **** size = (uint32_t)ddi_get16(acc, &softs->comm_space->adapter_fibs[aif_idx]. \ Header.Size); ddi_put32(acc, &softs->comm_space->adapter_fibs[aif_idx]. \ ! Header.ReceiverFibAddress, addr); if (aac_fib_enqueue(softs, AAC_ADAP_NORM_RESP_Q, addr, size) == AACERR) cmn_err(CE_NOTE, "!AIF ack failed"); } return (AAC_DB_COMMAND_READY); --- 1687,1697 ---- size = (uint32_t)ddi_get16(acc, &softs->comm_space->adapter_fibs[aif_idx]. \ Header.Size); ddi_put32(acc, &softs->comm_space->adapter_fibs[aif_idx]. \ ! Header.a.ReceiverFibAddress, addr); if (aac_fib_enqueue(softs, AAC_ADAP_NORM_RESP_Q, addr, size) == AACERR) cmn_err(CE_NOTE, "!AIF ack failed"); } return (AAC_DB_COMMAND_READY);
*** 1529,1539 **** if (aac_check_dma_handle(softs->comm_space_dma_handle) == DDI_SUCCESS) cmn_err(CE_NOTE, "MSG From Adapter: %s", softs->comm_space->adapter_print_buf); else ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); AAC_NOTIFY(softs, AAC_DB_PRINTF_READY); return (AAC_DB_PRINTF_READY); } else if (status & AAC_DB_COMMAND_NOT_FULL) { /* --- 1705,1715 ---- if (aac_check_dma_handle(softs->comm_space_dma_handle) == DDI_SUCCESS) cmn_err(CE_NOTE, "MSG From Adapter: %s", softs->comm_space->adapter_print_buf); else ! aac_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); AAC_NOTIFY(softs, AAC_DB_PRINTF_READY); return (AAC_DB_PRINTF_READY); } else if (status & AAC_DB_COMMAND_NOT_FULL) { /*
*** 1554,1564 **** } static uint_t aac_intr_old(caddr_t arg) { ! struct aac_softstate *softs = (void *)arg; int rval; mutex_enter(&softs->io_lock); if (aac_process_intr_old(softs)) rval = DDI_INTR_CLAIMED; --- 1730,1740 ---- } static uint_t aac_intr_old(caddr_t arg) { ! struct aac_softstate *softs = (struct aac_softstate *)arg; int rval; mutex_enter(&softs->io_lock); if (aac_process_intr_old(softs)) rval = DDI_INTR_CLAIMED;
*** 1569,1777 **** aac_drain_comp_q(softs); return (rval); } /* - * Query FIXED or MSI interrupts - */ - static int - aac_query_intrs(struct aac_softstate *softs, int intr_type) - { - dev_info_t *dip = softs->devinfo_p; - int avail, actual, count; - int i, flag, ret; - - AACDB_PRINT(softs, CE_NOTE, - "aac_query_intrs:interrupt type 0x%x", intr_type); - - /* Get number of interrupts */ - ret = ddi_intr_get_nintrs(dip, intr_type, &count); - if ((ret != DDI_SUCCESS) || (count == 0)) { - AACDB_PRINT(softs, CE_WARN, - "ddi_intr_get_nintrs() failed, ret %d count %d", - ret, count); - return (DDI_FAILURE); - } - - /* Get number of available interrupts */ - ret = ddi_intr_get_navail(dip, intr_type, &avail); - if ((ret != DDI_SUCCESS) || (avail == 0)) { - AACDB_PRINT(softs, CE_WARN, - "ddi_intr_get_navail() failed, ret %d avail %d", - ret, avail); - return (DDI_FAILURE); - } - - AACDB_PRINT(softs, CE_NOTE, - "ddi_intr_get_nvail returned %d, navail() returned %d", - count, avail); - - /* Allocate an array of interrupt handles */ - softs->intr_size = count * sizeof (ddi_intr_handle_t); - softs->htable = kmem_alloc(softs->intr_size, KM_SLEEP); - - if (intr_type == DDI_INTR_TYPE_MSI) { - count = 1; /* only one vector needed by now */ - flag = DDI_INTR_ALLOC_STRICT; - } else { /* must be DDI_INTR_TYPE_FIXED */ - flag = DDI_INTR_ALLOC_NORMAL; - } - - /* Call ddi_intr_alloc() */ - ret = ddi_intr_alloc(dip, softs->htable, intr_type, 0, - count, &actual, flag); - - if ((ret != DDI_SUCCESS) || (actual == 0)) { - AACDB_PRINT(softs, CE_WARN, - "ddi_intr_alloc() failed, ret = %d", ret); - actual = 0; - goto error; - } - - if (actual < count) { - AACDB_PRINT(softs, CE_NOTE, - "Requested: %d, Received: %d", count, actual); - goto error; - } - - softs->intr_cnt = actual; - - /* Get priority for first msi, assume remaining are all the same */ - if ((ret = ddi_intr_get_pri(softs->htable[0], - &softs->intr_pri)) != DDI_SUCCESS) { - AACDB_PRINT(softs, CE_WARN, - "ddi_intr_get_pri() failed, ret = %d", ret); - goto error; - } - - /* Test for high level mutex */ - if (softs->intr_pri >= ddi_intr_get_hilevel_pri()) { - AACDB_PRINT(softs, CE_WARN, - "aac_query_intrs: Hi level interrupt not supported"); - goto error; - } - - return (DDI_SUCCESS); - - error: - /* Free already allocated intr */ - for (i = 0; i < actual; i++) - (void) ddi_intr_free(softs->htable[i]); - - kmem_free(softs->htable, softs->intr_size); - return (DDI_FAILURE); - } - - - /* - * Register FIXED or MSI interrupts, and enable them - */ - static int - aac_add_intrs(struct aac_softstate *softs) - { - int i, ret; - int actual; - ddi_intr_handler_t *aac_intr; - - actual = softs->intr_cnt; - aac_intr = (ddi_intr_handler_t *)((softs->flags & AAC_FLAGS_NEW_COMM) ? - aac_intr_new : aac_intr_old); - - /* Call ddi_intr_add_handler() */ - for (i = 0; i < actual; i++) { - if ((ret = ddi_intr_add_handler(softs->htable[i], - aac_intr, (caddr_t)softs, NULL)) != DDI_SUCCESS) { - cmn_err(CE_WARN, - "ddi_intr_add_handler() failed ret = %d", ret); - - /* Free already allocated intr */ - for (i = 0; i < actual; i++) - (void) ddi_intr_free(softs->htable[i]); - - kmem_free(softs->htable, softs->intr_size); - return (DDI_FAILURE); - } - } - - if ((ret = ddi_intr_get_cap(softs->htable[0], &softs->intr_cap)) - != DDI_SUCCESS) { - cmn_err(CE_WARN, "ddi_intr_get_cap() failed, ret = %d", ret); - - /* Free already allocated intr */ - for (i = 0; i < actual; i++) - (void) ddi_intr_free(softs->htable[i]); - - kmem_free(softs->htable, softs->intr_size); - return (DDI_FAILURE); - } - - return (DDI_SUCCESS); - } - - /* - * Unregister FIXED or MSI interrupts - */ - static void - aac_remove_intrs(struct aac_softstate *softs) - { - int i; - - /* Disable all interrupts */ - (void) aac_disable_intrs(softs); - /* Call ddi_intr_remove_handler() */ - for (i = 0; i < softs->intr_cnt; i++) { - (void) ddi_intr_remove_handler(softs->htable[i]); - (void) ddi_intr_free(softs->htable[i]); - } - - kmem_free(softs->htable, softs->intr_size); - } - - static int - aac_enable_intrs(struct aac_softstate *softs) - { - int rval = AACOK; - - if (softs->intr_cap & DDI_INTR_FLAG_BLOCK) { - /* for MSI block enable */ - if (ddi_intr_block_enable(softs->htable, softs->intr_cnt) != - DDI_SUCCESS) - rval = AACERR; - } else { - int i; - - /* Call ddi_intr_enable() for legacy/MSI non block enable */ - for (i = 0; i < softs->intr_cnt; i++) { - if (ddi_intr_enable(softs->htable[i]) != DDI_SUCCESS) - rval = AACERR; - } - } - return (rval); - } - - static int - aac_disable_intrs(struct aac_softstate *softs) - { - int rval = AACOK; - - if (softs->intr_cap & DDI_INTR_FLAG_BLOCK) { - /* Call ddi_intr_block_disable() */ - if (ddi_intr_block_disable(softs->htable, softs->intr_cnt) != - DDI_SUCCESS) - rval = AACERR; - } else { - int i; - - for (i = 0; i < softs->intr_cnt; i++) { - if (ddi_intr_disable(softs->htable[i]) != DDI_SUCCESS) - rval = AACERR; - } - } - return (rval); - } - - /* * Set pkt_reason and OR in pkt_statistics flag */ static void aac_set_pkt_reason(struct aac_softstate *softs, struct aac_cmd *acp, uchar_t reason, uint_t stat) --- 1745,1754 ----
*** 1793,1803 **** ASSERT(acp->pkt); acp->flags |= AAC_CMD_CMPLT; acp->pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | \ ! STATE_SENT_CMD | STATE_GOT_STATUS; if (acp->pkt->pkt_state & STATE_XFERRED_DATA) acp->pkt->pkt_resid = 0; /* AAC_CMD_NO_INTR means no complete callback */ if (!(acp->flags & AAC_CMD_NO_INTR)) { --- 1770,1780 ---- ASSERT(acp->pkt); acp->flags |= AAC_CMD_CMPLT; acp->pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | \ ! STATE_SENT_CMD; if (acp->pkt->pkt_state & STATE_XFERRED_DATA) acp->pkt->pkt_resid = 0; /* AAC_CMD_NO_INTR means no complete callback */ if (!(acp->flags & AAC_CMD_NO_INTR)) {
*** 1824,1844 **** uint32_t status; ASSERT(!(acp->flags & AAC_CMD_SYNC)); ASSERT(!(acp->flags & AAC_CMD_NO_CB)); - acp->pkt->pkt_state |= STATE_GOT_STATUS; - /* * block_read/write has a similar response header, use blockread * response for both. */ resp = (struct aac_blockread_response *)&slotp->fibp->data[0]; status = ddi_get32(slotp->fib_acc_handle, &resp->Status); if (status == ST_OK) { acp->pkt->pkt_resid = 0; acp->pkt->pkt_state |= STATE_XFERRED_DATA; } else { aac_set_arq_data_hwerr(acp); } } --- 1801,1821 ---- uint32_t status; ASSERT(!(acp->flags & AAC_CMD_SYNC)); ASSERT(!(acp->flags & AAC_CMD_NO_CB)); /* * block_read/write has a similar response header, use blockread * response for both. */ resp = (struct aac_blockread_response *)&slotp->fibp->data[0]; status = ddi_get32(slotp->fib_acc_handle, &resp->Status); if (status == ST_OK) { acp->pkt->pkt_resid = 0; acp->pkt->pkt_state |= STATE_XFERRED_DATA; + } else if (status == ST_NOT_READY) { + aac_set_pkt_reason(softs, acp, CMD_TIMEOUT, STAT_TIMEOUT); } else { aac_set_arq_data_hwerr(acp); } }
*** 1850,2023 **** { ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; struct aac_fib *fibp = acp->slotp->fibp; struct scsi_pkt *pkt = acp->pkt; struct aac_srb_reply *resp; ! uint32_t resp_status; ASSERT(!(acp->flags & AAC_CMD_SYNC)); ASSERT(!(acp->flags & AAC_CMD_NO_CB)); resp = (struct aac_srb_reply *)&fibp->data[0]; resp_status = ddi_get32(acc, &resp->status); /* First check FIB status */ if (resp_status == ST_OK) { ! uint32_t scsi_status; ! uint32_t srb_status; ! uint32_t data_xfer_length; - scsi_status = ddi_get32(acc, &resp->scsi_status); - srb_status = ddi_get32(acc, &resp->srb_status); - data_xfer_length = ddi_get32(acc, &resp->data_xfer_length); - - *pkt->pkt_scbp = (uint8_t)scsi_status; - pkt->pkt_state |= STATE_GOT_STATUS; - if (scsi_status == STATUS_GOOD) { - uchar_t cmd = ((union scsi_cdb *)(void *) - (pkt->pkt_cdbp))->scc_cmd; - /* Next check SRB status */ switch (srb_status & 0x3f) { - case SRB_STATUS_DATA_OVERRUN: - AACDB_PRINT(softs, CE_NOTE, "DATA_OVERRUN: " \ - "scmd=%d, xfer=%d, buflen=%d", - (uint32_t)cmd, data_xfer_length, - acp->bcount); - - switch (cmd) { - case SCMD_READ: - case SCMD_WRITE: - case SCMD_READ_G1: - case SCMD_WRITE_G1: - case SCMD_READ_G4: - case SCMD_WRITE_G4: - case SCMD_READ_G5: - case SCMD_WRITE_G5: - aac_set_pkt_reason(softs, acp, - CMD_DATA_OVR, 0); - break; - } - /*FALLTHRU*/ case SRB_STATUS_ERROR_RECOVERY: case SRB_STATUS_PENDING: case SRB_STATUS_SUCCESS: - /* - * pkt_resid should only be calculated if the - * status is ERROR_RECOVERY/PENDING/SUCCESS/ - * OVERRUN/UNDERRUN - */ - if (data_xfer_length) { - pkt->pkt_state |= STATE_XFERRED_DATA; - pkt->pkt_resid = acp->bcount - \ - data_xfer_length; - ASSERT(pkt->pkt_resid >= 0); - } break; case SRB_STATUS_ABORTED: - AACDB_PRINT(softs, CE_NOTE, - "SRB_STATUS_ABORTED, xfer=%d, resid=%d", - data_xfer_length, pkt->pkt_resid); aac_set_pkt_reason(softs, acp, CMD_ABORTED, STAT_ABORTED); break; case SRB_STATUS_ABORT_FAILED: ! AACDB_PRINT(softs, CE_NOTE, ! "SRB_STATUS_ABORT_FAILED, xfer=%d, " \ ! "resid=%d", data_xfer_length, ! pkt->pkt_resid); ! aac_set_pkt_reason(softs, acp, CMD_ABORT_FAIL, ! 0); break; ! case SRB_STATUS_PARITY_ERROR: ! AACDB_PRINT(softs, CE_NOTE, ! "SRB_STATUS_PARITY_ERROR, xfer=%d, " \ ! "resid=%d", data_xfer_length, ! pkt->pkt_resid); ! aac_set_pkt_reason(softs, acp, CMD_PER_FAIL, 0); break; - case SRB_STATUS_NO_DEVICE: - case SRB_STATUS_INVALID_PATH_ID: - case SRB_STATUS_INVALID_TARGET_ID: - case SRB_STATUS_INVALID_LUN: - case SRB_STATUS_SELECTION_TIMEOUT: - #ifdef DEBUG - if (AAC_DEV_IS_VALID(acp->dvp)) { - AACDB_PRINT(softs, CE_NOTE, - "SRB_STATUS_NO_DEVICE(%d), " \ - "xfer=%d, resid=%d ", - srb_status & 0x3f, - data_xfer_length, pkt->pkt_resid); } - #endif - aac_set_pkt_reason(softs, acp, CMD_DEV_GONE, 0); break; case SRB_STATUS_COMMAND_TIMEOUT: case SRB_STATUS_TIMEOUT: - AACDB_PRINT(softs, CE_NOTE, - "SRB_STATUS_COMMAND_TIMEOUT, xfer=%d, " \ - "resid=%d", data_xfer_length, - pkt->pkt_resid); aac_set_pkt_reason(softs, acp, CMD_TIMEOUT, STAT_TIMEOUT); break; case SRB_STATUS_BUS_RESET: - AACDB_PRINT(softs, CE_NOTE, - "SRB_STATUS_BUS_RESET, xfer=%d, " \ - "resid=%d", data_xfer_length, - pkt->pkt_resid); aac_set_pkt_reason(softs, acp, CMD_RESET, STAT_BUS_RESET); break; default: - AACDB_PRINT(softs, CE_NOTE, "srb_status=%d, " \ - "xfer=%d, resid=%d", srb_status & 0x3f, - data_xfer_length, pkt->pkt_resid); aac_set_pkt_reason(softs, acp, CMD_TRAN_ERR, 0); break; } ! } else if (scsi_status == STATUS_CHECK) { ! /* CHECK CONDITION */ ! struct scsi_arq_status *arqstat = ! (void *)(pkt->pkt_scbp); ! uint32_t sense_data_size; ! ! pkt->pkt_state |= STATE_ARQ_DONE; ! ! *(uint8_t *)&arqstat->sts_rqpkt_status = STATUS_GOOD; ! arqstat->sts_rqpkt_reason = CMD_CMPLT; ! arqstat->sts_rqpkt_resid = 0; ! arqstat->sts_rqpkt_state = ! STATE_GOT_BUS | ! STATE_GOT_TARGET | ! STATE_SENT_CMD | ! STATE_XFERRED_DATA; ! arqstat->sts_rqpkt_statistics = 0; ! ! sense_data_size = ddi_get32(acc, ! &resp->sense_data_size); ! ASSERT(sense_data_size <= AAC_SENSE_BUFFERSIZE); ! AACDB_PRINT(softs, CE_NOTE, ! "CHECK CONDITION: sense len=%d, xfer len=%d", ! sense_data_size, data_xfer_length); ! ! if (sense_data_size > SENSE_LENGTH) ! sense_data_size = SENSE_LENGTH; ! ddi_rep_get8(acc, (uint8_t *)&arqstat->sts_sensedata, ! (uint8_t *)resp->sense_data, sense_data_size, ! DDI_DEV_AUTOINCR); } else { - AACDB_PRINT(softs, CE_WARN, "invaild scsi status: " \ - "scsi_status=%d, srb_status=%d", - scsi_status, srb_status); - aac_set_pkt_reason(softs, acp, CMD_TRAN_ERR, 0); - } - } else { AACDB_PRINT(softs, CE_NOTE, "SRB failed: fib status %d", resp_status); - aac_set_pkt_reason(softs, acp, CMD_TRAN_ERR, 0); } } /* * Handle completed IOCTL command */ --- 1827,1918 ---- { ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; struct aac_fib *fibp = acp->slotp->fibp; struct scsi_pkt *pkt = acp->pkt; struct aac_srb_reply *resp; ! uint32_t resp_status, scsi_status; ! uint32_t srb_status, data_xfer_length; ! uint32_t sense_data_size; ASSERT(!(acp->flags & AAC_CMD_SYNC)); ASSERT(!(acp->flags & AAC_CMD_NO_CB)); resp = (struct aac_srb_reply *)&fibp->data[0]; + if (acp->flags & AAC_CMD_FASTRESP) { + resp_status = ST_OK; + sense_data_size = 0; + srb_status = SRB_STATUS_SUCCESS; + data_xfer_length = 0; + scsi_status = 0; + } else { resp_status = ddi_get32(acc, &resp->status); + sense_data_size = ddi_get32(acc, &resp->sense_data_size); + srb_status = ddi_get32(acc, &resp->srb_status); + data_xfer_length = ddi_get32(acc, &resp->data_xfer_length); + scsi_status = ddi_get32(acc, &resp->scsi_status); + } /* First check FIB status */ if (resp_status == ST_OK) { ! if (data_xfer_length) { ! /* When the cmd failed, data_xfer_length is 0 */ ! pkt->pkt_state |= STATE_XFERRED_DATA; ! pkt->pkt_resid = acp->bcount - data_xfer_length; ! } /* Next check SRB status */ switch (srb_status & 0x3f) { case SRB_STATUS_ERROR_RECOVERY: case SRB_STATUS_PENDING: case SRB_STATUS_SUCCESS: break; case SRB_STATUS_ABORTED: aac_set_pkt_reason(softs, acp, CMD_ABORTED, STAT_ABORTED); break; case SRB_STATUS_ABORT_FAILED: ! aac_set_pkt_reason(softs, acp, CMD_ABORT_FAIL, 0); break; ! case SRB_STATUS_DATA_OVERRUN: ! switch (((union scsi_cdb *)(pkt->pkt_cdbp))->scc_cmd) { ! case SCMD_READ: ! case SCMD_WRITE: ! case SCMD_READ_G1: ! case SCMD_WRITE_G1: ! case SCMD_READ_G4: ! case SCMD_WRITE_G4: ! aac_set_pkt_reason(softs, acp, CMD_DATA_OVR, 0); break; } break; case SRB_STATUS_COMMAND_TIMEOUT: case SRB_STATUS_TIMEOUT: aac_set_pkt_reason(softs, acp, CMD_TIMEOUT, STAT_TIMEOUT); break; case SRB_STATUS_BUS_RESET: aac_set_pkt_reason(softs, acp, CMD_RESET, STAT_BUS_RESET); break; default: aac_set_pkt_reason(softs, acp, CMD_TRAN_ERR, 0); break; } ! } else if (resp_status == ST_NOT_READY) { ! aac_set_pkt_reason(softs, acp, CMD_TIMEOUT, STAT_TIMEOUT); } else { AACDB_PRINT(softs, CE_NOTE, "SRB failed: fib status %d", resp_status); } + + /* Finally SCSI status */ + if (scsi_status == 2) { + AACDB_PRINT(softs, CE_NOTE, "CHECK CONDITION: len=%d", + sense_data_size); + ASSERT(sense_data_size <= AAC_SENSE_BUFFERSIZE); + aac_copy_arq_data(pkt, resp->sense_data, sense_data_size, acc); + } } /* * Handle completed IOCTL command */
*** 2043,2061 **** ddi_rep_get8(slotp->fib_acc_handle, (uint8_t *)acp->fibp, (uint8_t *)slotp->fibp, acp->fib_size, DDI_DEV_AUTOINCR); } /* - * Handle completed sync fib command - */ - /*ARGSUSED*/ - void - aac_sync_complete(struct aac_softstate *softs, struct aac_cmd *acp) - { - } - - /* * Handle completed Flush command */ /*ARGSUSED*/ static void aac_synccache_complete(struct aac_softstate *softs, struct aac_cmd *acp) --- 1938,1947 ----
*** 2065,2100 **** struct aac_synchronize_reply *resp; uint32_t status; ASSERT(!(acp->flags & AAC_CMD_SYNC)); - acp->pkt->pkt_state |= STATE_GOT_STATUS; - resp = (struct aac_synchronize_reply *)&slotp->fibp->data[0]; status = ddi_get32(acc, &resp->Status); if (status != CT_OK) aac_set_arq_data_hwerr(acp); } /*ARGSUSED*/ static void ! aac_startstop_complete(struct aac_softstate *softs, struct aac_cmd *acp) { struct aac_slot *slotp = acp->slotp; ddi_acc_handle_t acc = slotp->fib_acc_handle; - struct aac_Container_resp *resp; uint32_t status; ASSERT(!(acp->flags & AAC_CMD_SYNC)); ! acp->pkt->pkt_state |= STATE_GOT_STATUS; ! resp = (struct aac_Container_resp *)&slotp->fibp->data[0]; ! status = ddi_get32(acc, &resp->Status); ! if (status != 0) { ! AACDB_PRINT(softs, CE_WARN, "Cannot start/stop a unit"); ! aac_set_arq_data_hwerr(acp); } } /* * Access PCI space to see if the driver can support the card --- 1951,2004 ---- struct aac_synchronize_reply *resp; uint32_t status; ASSERT(!(acp->flags & AAC_CMD_SYNC)); resp = (struct aac_synchronize_reply *)&slotp->fibp->data[0]; status = ddi_get32(acc, &resp->Status); if (status != CT_OK) aac_set_arq_data_hwerr(acp); } + /* + * Handle completed AIF request command + */ /*ARGSUSED*/ static void ! aac_aifreq_complete(struct aac_softstate *softs, struct aac_cmd *acp) { struct aac_slot *slotp = acp->slotp; ddi_acc_handle_t acc = slotp->fib_acc_handle; uint32_t status; + struct aac_fib *fibp; /* FIB in AIF queue */ + uint16_t fib_size, fib_size0; ASSERT(!(acp->flags & AAC_CMD_SYNC)); ! acp->flags |= AAC_CMD_AIF; ! status = ddi_get32(acc, &slotp->fibp->Header.XferState); ! if (status & AAC_FIBSTATE_NOMOREAIF) { ! acp->flags |= AAC_CMD_AIF_NOMORE; ! } else { ! mutex_enter(&softs->aifq_mutex); ! /* ! * Copy AIF from adapter to the empty AIF slot ! */ ! fibp = &softs->aifq[softs->aifq_idx].d; ! fib_size0 = ddi_get16(acc, &slotp->fibp->Header.Size); ! fib_size = (fib_size0 > AAC_FIB_SIZE) ? ! AAC_FIB_SIZE : fib_size0; ! ddi_rep_get8(acc, (uint8_t *)fibp, (uint8_t *)slotp->fibp, ! fib_size, DDI_DEV_AUTOINCR); ! if (aac_check_acc_handle(softs-> \ ! pci_mem_handle[0]) == DDI_SUCCESS) ! (void) aac_handle_aif(softs, fibp); ! else ! aac_fm_service_impact(softs->devinfo_p, ! DDI_SERVICE_UNAFFECTED); ! mutex_exit(&softs->aifq_mutex); } } /* * Access PCI space to see if the driver can support the card
*** 2150,2159 **** --- 2054,2071 ---- softs->hwif = AAC_HWIF_I960RX; break; case 0x286: softs->hwif = AAC_HWIF_RKT; break; + case 0x28b: + softs->hwif = AAC_HWIF_SRC; + break; + case 0x28c: + case 0x28d: + case 0x28f: + softs->hwif = AAC_HWIF_SRCV; + break; default: AACDB_PRINT(softs, CE_WARN, "Unknown device \"pci9005,%x\"", softs->devid); goto error; }
*** 2167,2176 **** --- 2079,2096 ---- break; case AAC_HWIF_RKT: softs->aac_if = aac_rkt_interface; softs->map_size_min = AAC_MAP_SIZE_MIN_RKT; break; + case AAC_HWIF_SRC: + softs->aac_if = aac_src_interface; + softs->map_size_min = AAC_MAP_SIZE_MIN_SRC_BAR0; + break; + case AAC_HWIF_SRCV: + softs->aac_if = aac_srcv_interface; + softs->map_size_min = AAC_MAP_SIZE_MIN_SRCV_BAR0; + break; default: AACDB_PRINT(softs, CE_WARN, "Unknown hardware interface %d", softs->hwif); goto error; }
*** 2195,2206 **** goto error; } } /* Set memory base to map */ ! softs->pci_mem_base_paddr = 0xfffffff0UL & \ pci_config_get32(pci_config_handle, PCI_CONF_BASE0); pci_config_teardown(&pci_config_handle); return (AACOK); /* card type detected */ error: --- 2115,2132 ---- goto error; } } /* Set memory base to map */ ! softs->pci_mem_base_paddr[0] = 0xfffffff0UL & \ pci_config_get32(pci_config_handle, PCI_CONF_BASE0); + if (softs->hwif == AAC_HWIF_SRC) { + softs->pci_mem_base_paddr[1] = 0xfffffff0UL & \ + pci_config_get32(pci_config_handle, PCI_CONF_BASE2); + } else { + softs->pci_mem_base_paddr[1] = softs->pci_mem_base_paddr[0]; + } pci_config_teardown(&pci_config_handle); return (AACOK); /* card type detected */ error:
*** 2207,2306 **** pci_config_teardown(&pci_config_handle); return (AACERR); /* no matched card found */ } /* - * Do the usual interrupt handler setup stuff. - */ - static int - aac_register_intrs(struct aac_softstate *softs) - { - dev_info_t *dip; - int intr_types; - - ASSERT(softs->devinfo_p); - dip = softs->devinfo_p; - - /* Get the type of device intrrupts */ - if (ddi_intr_get_supported_types(dip, &intr_types) != DDI_SUCCESS) { - AACDB_PRINT(softs, CE_WARN, - "ddi_intr_get_supported_types() failed"); - return (AACERR); - } - AACDB_PRINT(softs, CE_NOTE, - "ddi_intr_get_supported_types() ret: 0x%x", intr_types); - - /* Query interrupt, and alloc/init all needed struct */ - if (intr_types & DDI_INTR_TYPE_MSI) { - if (aac_query_intrs(softs, DDI_INTR_TYPE_MSI) - != DDI_SUCCESS) { - AACDB_PRINT(softs, CE_WARN, - "MSI interrupt query failed"); - return (AACERR); - } - softs->intr_type = DDI_INTR_TYPE_MSI; - } else if (intr_types & DDI_INTR_TYPE_FIXED) { - if (aac_query_intrs(softs, DDI_INTR_TYPE_FIXED) - != DDI_SUCCESS) { - AACDB_PRINT(softs, CE_WARN, - "FIXED interrupt query failed"); - return (AACERR); - } - softs->intr_type = DDI_INTR_TYPE_FIXED; - } else { - AACDB_PRINT(softs, CE_WARN, - "Device cannot suppport both FIXED and MSI interrupts"); - return (AACERR); - } - - /* Connect interrupt handlers */ - if (aac_add_intrs(softs) != DDI_SUCCESS) { - AACDB_PRINT(softs, CE_WARN, - "Interrupt registration failed, intr type: %s", - softs->intr_type == DDI_INTR_TYPE_MSI ? "MSI" : "FIXED"); - return (AACERR); - } - (void) aac_enable_intrs(softs); - - if (ddi_add_softintr(dip, DDI_SOFTINT_LOW, &softs->softint_id, - NULL, NULL, aac_softintr, (caddr_t)softs) != DDI_SUCCESS) { - AACDB_PRINT(softs, CE_WARN, - "Can not setup soft interrupt handler!"); - aac_remove_intrs(softs); - return (AACERR); - } - - return (AACOK); - } - - static void - aac_unregister_intrs(struct aac_softstate *softs) - { - aac_remove_intrs(softs); - ddi_remove_softintr(softs->softint_id); - } - - /* * Check the firmware to determine the features to support and the FIB * parameters to use. */ static int aac_check_firmware(struct aac_softstate *softs) { uint32_t options; uint32_t atu_size; ddi_acc_handle_t pci_handle; ! uint8_t *data; ! uint32_t max_fibs; uint32_t max_fib_size; uint32_t sg_tablesize; uint32_t max_sectors; uint32_t status; /* Get supported options */ if ((aac_sync_mbcommand(softs, AAC_MONKER_GETINFO, 0, 0, 0, 0, ! &status)) != AACOK) { if (status != SRB_STATUS_INVALID_REQUEST) { cmn_err(CE_CONT, "?Fatal error: request adapter info error"); return (AACERR); } --- 2133,2162 ---- pci_config_teardown(&pci_config_handle); return (AACERR); /* no matched card found */ } /* * Check the firmware to determine the features to support and the FIB * parameters to use. */ static int aac_check_firmware(struct aac_softstate *softs) { uint32_t options; uint32_t atu_size; ddi_acc_handle_t pci_handle; ! char *pci_mbr; ! uint32_t max_fibs, max_aif; uint32_t max_fib_size; uint32_t sg_tablesize; uint32_t max_sectors; uint32_t status; /* Get supported options */ + softs->sync_slot_busy = 1; if ((aac_sync_mbcommand(softs, AAC_MONKER_GETINFO, 0, 0, 0, 0, ! &status, NULL)) != AACOK) { if (status != SRB_STATUS_INVALID_REQUEST) { cmn_err(CE_CONT, "?Fatal error: request adapter info error"); return (AACERR); }
*** 2355,2414 **** softs->flags |= AAC_FLAGS_ARRAY_64BIT; AACDB_PRINT(softs, CE_NOTE, "!Enable 64-bit array size"); } if (options & AAC_SUPPORTED_NONDASD) { - if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, softs->devinfo_p, 0, - "nondasd-enable", (char **)&data) == DDI_SUCCESS)) { - if (strcmp((char *)data, "yes") == 0) { - AACDB_PRINT(softs, CE_NOTE, - "!Enable Non-DASD access"); softs->flags |= AAC_FLAGS_NONDASD; } ! ddi_prop_free(data); } } /* Read preferred settings */ max_fib_size = 0; if ((aac_sync_mbcommand(softs, AAC_MONKER_GETCOMMPREF, ! 0, 0, 0, 0, NULL)) == AACOK) { options = AAC_MAILBOX_GET(softs, 1); max_fib_size = (options & 0xffff); max_sectors = (options >> 16) << 1; options = AAC_MAILBOX_GET(softs, 2); sg_tablesize = (options >> 16); options = AAC_MAILBOX_GET(softs, 3); max_fibs = (options & 0xffff); } /* Enable new comm. and rawio at the same time */ ! if ((softs->support_opt & AAC_SUPPORTED_NEW_COMM) && (max_fib_size != 0)) { - /* read out and save PCI MBR */ if ((atu_size > softs->map_size) && (ddi_regs_map_setup(softs->devinfo_p, 1, ! (caddr_t *)&data, 0, atu_size, &softs->reg_attr, &pci_handle) == DDI_SUCCESS)) { ! ddi_regs_map_free(&softs->pci_mem_handle); ! softs->pci_mem_handle = pci_handle; ! softs->pci_mem_base_vaddr = data; softs->map_size = atu_size; } - if (atu_size == softs->map_size) { - softs->flags |= AAC_FLAGS_NEW_COMM; - AACDB_PRINT(softs, CE_NOTE, - "!Enable New Comm. interface"); } } /* Set FIB parameters */ if (softs->flags & AAC_FLAGS_NEW_COMM) { softs->aac_max_fibs = max_fibs; softs->aac_max_fib_size = max_fib_size; softs->aac_max_sectors = max_sectors; softs->aac_sg_tablesize = sg_tablesize; softs->flags |= AAC_FLAGS_RAW_IO; AACDB_PRINT(softs, CE_NOTE, "!Enable RawIO"); } else { softs->aac_max_fibs = --- 2211,2293 ---- softs->flags |= AAC_FLAGS_ARRAY_64BIT; AACDB_PRINT(softs, CE_NOTE, "!Enable 64-bit array size"); } if (options & AAC_SUPPORTED_NONDASD) { softs->flags |= AAC_FLAGS_NONDASD; + AACDB_PRINT(softs, CE_NOTE, "!Enable Non-DASD access"); } ! ! if ((options & AAC_SUPPORTED_NEW_COMM_TYPE3) || ! (options & AAC_SUPPORTED_NEW_COMM_TYPE4)) { ! softs->flags |= AAC_FLAGS_NEW_COMM | AAC_FLAGS_NEW_COMM_TYPE34; ! } else if (options & AAC_SUPPORTED_NEW_COMM_TYPE2) { ! softs->flags |= AAC_FLAGS_NEW_COMM | AAC_FLAGS_NEW_COMM_TYPE2; ! AACDB_PRINT(softs, CE_NOTE, "!Enable New Comm. Type2 interface"); ! } else if (options & AAC_SUPPORTED_NEW_COMM_TYPE1) { ! softs->flags |= AAC_FLAGS_NEW_COMM | AAC_FLAGS_NEW_COMM_TYPE1; ! AACDB_PRINT(softs, CE_NOTE, "!Enable New Comm. Type1 interface"); ! } else if (options & AAC_SUPPORTED_NEW_COMM) { ! softs->flags |= AAC_FLAGS_NEW_COMM; ! AACDB_PRINT(softs, CE_NOTE, "!Enable New Comm. interface"); } + + if (softs->sync_mode && + ((softs->flags & AAC_FLAGS_NEW_COMM_TYPE1) || + (softs->flags & AAC_FLAGS_NEW_COMM_TYPE2) || + (softs->flags & AAC_FLAGS_NEW_COMM_TYPE34))) { + cmn_err(CE_NOTE, "aac: Sync. mode enforced by driver parameter. This will cause a significant performance decrease!"); + softs->flags |= AAC_FLAGS_SYNC_MODE; + } else if (softs->flags & AAC_FLAGS_NEW_COMM_TYPE34) { + cmn_err(CE_NOTE, "aac: Async. mode not supported by current driver, sync. mode enforced."); + cmn_err(CE_NOTE, "aac: Please update driver to get full performance."); + softs->flags |= AAC_FLAGS_SYNC_MODE; } /* Read preferred settings */ max_fib_size = 0; + softs->sync_slot_busy = 1; if ((aac_sync_mbcommand(softs, AAC_MONKER_GETCOMMPREF, ! 0, 0, 0, 0, NULL, NULL)) == AACOK) { options = AAC_MAILBOX_GET(softs, 1); max_fib_size = (options & 0xffff); max_sectors = (options >> 16) << 1; options = AAC_MAILBOX_GET(softs, 2); sg_tablesize = (options >> 16); options = AAC_MAILBOX_GET(softs, 3); max_fibs = (options & 0xffff); + options = AAC_MAILBOX_GET(softs, 4); + max_aif = (options & 0xffff); } /* Enable new comm. and rawio at the same time */ ! if ((softs->flags & AAC_FLAGS_NEW_COMM) && (max_fib_size != 0)) { if ((atu_size > softs->map_size) && (ddi_regs_map_setup(softs->devinfo_p, 1, ! (caddr_t *)&pci_mbr, 0, atu_size, &aac_acc_attr, &pci_handle) == DDI_SUCCESS)) { ! ddi_regs_map_free(&softs->pci_mem_handle[0]); ! softs->pci_mem_handle[0] = pci_handle; ! softs->pci_mem_base_vaddr[0] = pci_mbr; softs->map_size = atu_size; + if (softs->hwif != AAC_HWIF_SRC) { + softs->pci_mem_handle[1] = + softs->pci_mem_handle[0]; + softs->pci_mem_base_vaddr[1] = + softs->pci_mem_base_vaddr[0]; } } } /* Set FIB parameters */ if (softs->flags & AAC_FLAGS_NEW_COMM) { softs->aac_max_fibs = max_fibs; softs->aac_max_fib_size = max_fib_size; softs->aac_max_sectors = max_sectors; softs->aac_sg_tablesize = sg_tablesize; + softs->aac_max_aif = max_aif; softs->flags |= AAC_FLAGS_RAW_IO; AACDB_PRINT(softs, CE_NOTE, "!Enable RawIO"); } else { softs->aac_max_fibs =
*** 2450,2460 **** */ softs->buf_dma_attr.dma_attr_count_max = softs->buf_dma_attr.dma_attr_maxxfer - 1; /* Setup FIB operations */ ! if (softs->flags & AAC_FLAGS_RAW_IO) softs->aac_cmd_fib = aac_cmd_fib_rawio; else if (softs->flags & AAC_FLAGS_SG_64BIT) softs->aac_cmd_fib = aac_cmd_fib_brw64; else softs->aac_cmd_fib = aac_cmd_fib_brw; --- 2329,2341 ---- */ softs->buf_dma_attr.dma_attr_count_max = softs->buf_dma_attr.dma_attr_maxxfer - 1; /* Setup FIB operations */ ! if (softs->flags & AAC_FLAGS_NEW_COMM_TYPE2) ! softs->aac_cmd_fib = aac_cmd_fib_rawio2; ! else if (softs->flags & AAC_FLAGS_RAW_IO) softs->aac_cmd_fib = aac_cmd_fib_rawio; else if (softs->flags & AAC_FLAGS_SG_64BIT) softs->aac_cmd_fib = aac_cmd_fib_brw64; else softs->aac_cmd_fib = aac_cmd_fib_brw;
*** 2477,2487 **** static void aac_fsa_rev(struct aac_softstate *softs, struct FsaRev *fsarev0, struct FsaRev *fsarev1) { ! ddi_acc_handle_t acc = softs->sync_ac.slotp->fib_acc_handle; AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.dash); AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.type); AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.minor); AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.major); --- 2358,2368 ---- static void aac_fsa_rev(struct aac_softstate *softs, struct FsaRev *fsarev0, struct FsaRev *fsarev1) { ! ddi_acc_handle_t acc = softs->comm_space_acc_handle; AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.dash); AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.type); AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.minor); AAC_GET_FIELD8(acc, fsarev1, fsarev0, external.comp.major);
*** 2495,2521 **** */ static int aac_get_adapter_info(struct aac_softstate *softs, struct aac_adapter_info *ainfr, struct aac_supplement_adapter_info *sinfr) { ! struct aac_cmd *acp = &softs->sync_ac; ! ddi_acc_handle_t acc; ! struct aac_fib *fibp; struct aac_adapter_info *ainfp; struct aac_supplement_adapter_info *sinfp; - int rval; - (void) aac_sync_fib_slot_bind(softs, acp); - acc = acp->slotp->fib_acc_handle; - fibp = acp->slotp->fibp; - ddi_put8(acc, &fibp->data[0], 0); if (aac_sync_fib(softs, RequestAdapterInfo, AAC_FIB_SIZEOF(struct aac_adapter_info)) != AACOK) { AACDB_PRINT(softs, CE_WARN, "RequestAdapterInfo failed"); ! rval = AACERR; ! goto finish; } ainfp = (struct aac_adapter_info *)fibp->data; if (ainfr) { AAC_GET_FIELD32(acc, ainfr, ainfp, SupportedOptions); AAC_GET_FIELD32(acc, ainfr, ainfp, PlatformBase); --- 2376,2395 ---- */ static int aac_get_adapter_info(struct aac_softstate *softs, struct aac_adapter_info *ainfr, struct aac_supplement_adapter_info *sinfr) { ! ddi_acc_handle_t acc = softs->sync_slot->fib_acc_handle; ! struct aac_fib *fibp = softs->sync_slot->fibp; struct aac_adapter_info *ainfp; struct aac_supplement_adapter_info *sinfp; ddi_put8(acc, &fibp->data[0], 0); if (aac_sync_fib(softs, RequestAdapterInfo, AAC_FIB_SIZEOF(struct aac_adapter_info)) != AACOK) { AACDB_PRINT(softs, CE_WARN, "RequestAdapterInfo failed"); ! return (AACERR); } ainfp = (struct aac_adapter_info *)fibp->data; if (ainfr) { AAC_GET_FIELD32(acc, ainfr, ainfp, SupportedOptions); AAC_GET_FIELD32(acc, ainfr, ainfp, PlatformBase);
*** 2543,2563 **** if (sinfr) { if (!(softs->support_opt & AAC_SUPPORTED_SUPPLEMENT_ADAPTER_INFO)) { AACDB_PRINT(softs, CE_WARN, "SupplementAdapterInfo not supported"); ! rval = AACERR; ! goto finish; } ddi_put8(acc, &fibp->data[0], 0); if (aac_sync_fib(softs, RequestSupplementAdapterInfo, ! AAC_FIB_SIZEOF(struct aac_supplement_adapter_info)) ! != AACOK) { AACDB_PRINT(softs, CE_WARN, "RequestSupplementAdapterInfo failed"); ! rval = AACERR; ! goto finish; } sinfp = (struct aac_supplement_adapter_info *)fibp->data; AAC_REP_GET_FIELD8(acc, sinfr, sinfp, AdapterTypeText[0], 17+1); AAC_REP_GET_FIELD8(acc, sinfr, sinfp, Pad[0], 2); AAC_GET_FIELD32(acc, sinfr, sinfp, FlashMemoryByteSize); --- 2417,2434 ---- if (sinfr) { if (!(softs->support_opt & AAC_SUPPORTED_SUPPLEMENT_ADAPTER_INFO)) { AACDB_PRINT(softs, CE_WARN, "SupplementAdapterInfo not supported"); ! return (AACERR); } ddi_put8(acc, &fibp->data[0], 0); if (aac_sync_fib(softs, RequestSupplementAdapterInfo, ! AAC_FIB_SIZEOF(struct aac_supplement_adapter_info)) != AACOK) { AACDB_PRINT(softs, CE_WARN, "RequestSupplementAdapterInfo failed"); ! return (AACERR); } sinfp = (struct aac_supplement_adapter_info *)fibp->data; AAC_REP_GET_FIELD8(acc, sinfr, sinfp, AdapterTypeText[0], 17+1); AAC_REP_GET_FIELD8(acc, sinfr, sinfp, Pad[0], 2); AAC_GET_FIELD32(acc, sinfr, sinfp, FlashMemoryByteSize);
*** 2582,2621 **** MFG_WWN_WIDTH); AAC_GET_FIELD32(acc, sinfr, sinfp, SupportedOptions2); AAC_GET_FIELD32(acc, sinfr, sinfp, ExpansionFlag); if (sinfr->ExpansionFlag == 1) { AAC_GET_FIELD32(acc, sinfr, sinfp, FeatureBits3); ! AAC_GET_FIELD32(acc, sinfr, sinfp, ! SupportedPerformanceMode); ! AAC_REP_GET_FIELD32(acc, sinfr, sinfp, ! ReservedGrowth[0], 80); } } ! rval = AACOK; ! finish: ! aac_sync_fib_slot_release(softs, acp); ! return (rval); } static int aac_get_bus_info(struct aac_softstate *softs, uint32_t *bus_max, uint32_t *tgt_max) { ! struct aac_cmd *acp = &softs->sync_ac; ! ddi_acc_handle_t acc; ! struct aac_fib *fibp; struct aac_ctcfg *c_cmd; struct aac_ctcfg_resp *c_resp; uint32_t scsi_method_id; struct aac_bus_info *cmd; struct aac_bus_info_response *resp; int rval; - (void) aac_sync_fib_slot_bind(softs, acp); - acc = acp->slotp->fib_acc_handle; - fibp = acp->slotp->fibp; - /* Detect MethodId */ c_cmd = (struct aac_ctcfg *)&fibp->data[0]; ddi_put32(acc, &c_cmd->Command, VM_ContainerConfig); ddi_put32(acc, &c_cmd->cmd, CT_GET_SCSI_METHOD); ddi_put32(acc, &c_cmd->param, 0); --- 2453,2482 ---- MFG_WWN_WIDTH); AAC_GET_FIELD32(acc, sinfr, sinfp, SupportedOptions2); AAC_GET_FIELD32(acc, sinfr, sinfp, ExpansionFlag); if (sinfr->ExpansionFlag == 1) { AAC_GET_FIELD32(acc, sinfr, sinfp, FeatureBits3); ! AAC_GET_FIELD32(acc, sinfr, sinfp, SupportedPerformanceMode); ! AAC_REP_GET_FIELD32(acc, sinfr, sinfp, ReservedGrowth[0], 80); } } ! return (AACOK); } static int aac_get_bus_info(struct aac_softstate *softs, uint32_t *bus_max, uint32_t *tgt_max) { ! ddi_acc_handle_t acc = softs->sync_slot->fib_acc_handle; ! struct aac_fib *fibp = softs->sync_slot->fibp; struct aac_ctcfg *c_cmd; struct aac_ctcfg_resp *c_resp; uint32_t scsi_method_id; struct aac_bus_info *cmd; struct aac_bus_info_response *resp; int rval; /* Detect MethodId */ c_cmd = (struct aac_ctcfg *)&fibp->data[0]; ddi_put32(acc, &c_cmd->Command, VM_ContainerConfig); ddi_put32(acc, &c_cmd->cmd, CT_GET_SCSI_METHOD); ddi_put32(acc, &c_cmd->param, 0);
*** 2623,2634 **** AAC_FIB_SIZEOF(struct aac_ctcfg)); c_resp = (struct aac_ctcfg_resp *)&fibp->data[0]; if (rval != AACOK || ddi_get32(acc, &c_resp->Status) != 0) { AACDB_PRINT(softs, CE_WARN, "VM_ContainerConfig command fail"); ! rval = AACERR; ! goto finish; } scsi_method_id = ddi_get32(acc, &c_resp->param); /* Detect phys. bus count and max. target id first */ cmd = (struct aac_bus_info *)&fibp->data[0]; --- 2484,2494 ---- AAC_FIB_SIZEOF(struct aac_ctcfg)); c_resp = (struct aac_ctcfg_resp *)&fibp->data[0]; if (rval != AACOK || ddi_get32(acc, &c_resp->Status) != 0) { AACDB_PRINT(softs, CE_WARN, "VM_ContainerConfig command fail"); ! return (AACERR); } scsi_method_id = ddi_get32(acc, &c_resp->param); /* Detect phys. bus count and max. target id first */ cmd = (struct aac_bus_info *)&fibp->data[0];
*** 2648,2665 **** resp = (struct aac_bus_info_response *)cmd; /* Scan all coordinates with INQUIRY */ if ((rval != AACOK) || (ddi_get32(acc, &resp->Status) != 0)) { AACDB_PRINT(softs, CE_WARN, "GetBusInfo command fail"); ! rval = AACERR; ! goto finish; } *bus_max = ddi_get32(acc, &resp->BusCount); *tgt_max = ddi_get32(acc, &resp->TargetsPerBus); - - finish: - aac_sync_fib_slot_release(softs, acp); return (AACOK); } /* * The following function comes from Adaptec: --- 2508,2521 ---- resp = (struct aac_bus_info_response *)cmd; /* Scan all coordinates with INQUIRY */ if ((rval != AACOK) || (ddi_get32(acc, &resp->Status) != 0)) { AACDB_PRINT(softs, CE_WARN, "GetBusInfo command fail"); ! return (AACERR); } *bus_max = ddi_get32(acc, &resp->BusCount); *tgt_max = ddi_get32(acc, &resp->TargetsPerBus); return (AACOK); } /* * The following function comes from Adaptec:
*** 2700,2724 **** * there is no harm in doing this when it's already been done. */ static int aac_handle_adapter_config_issues(struct aac_softstate *softs) { ! struct aac_cmd *acp = &softs->sync_ac; ! ddi_acc_handle_t acc; ! struct aac_fib *fibp; struct aac_Container *cmd; struct aac_Container_resp *resp; struct aac_cf_status_header *cfg_sts_hdr; uint32_t resp_status; uint32_t ct_status; uint32_t cfg_stat_action; int rval; - (void) aac_sync_fib_slot_bind(softs, acp); - acc = acp->slotp->fib_acc_handle; - fibp = acp->slotp->fibp; - /* Get adapter config status */ cmd = (struct aac_Container *)&fibp->data[0]; bzero(cmd, sizeof (*cmd) - CT_PACKET_SIZE); ddi_put32(acc, &cmd->Command, VM_ContainerConfig); --- 2556,2575 ---- * there is no harm in doing this when it's already been done. */ static int aac_handle_adapter_config_issues(struct aac_softstate *softs) { ! ddi_acc_handle_t acc = softs->sync_slot->fib_acc_handle; ! struct aac_fib *fibp = softs->sync_slot->fibp; struct aac_Container *cmd; struct aac_Container_resp *resp; struct aac_cf_status_header *cfg_sts_hdr; uint32_t resp_status; uint32_t ct_status; uint32_t cfg_stat_action; int rval; /* Get adapter config status */ cmd = (struct aac_Container *)&fibp->data[0]; bzero(cmd, sizeof (*cmd) - CT_PACKET_SIZE); ddi_put32(acc, &cmd->Command, VM_ContainerConfig);
*** 2762,2773 **** } } else { cmn_err(CE_WARN, "!Configuration issue, auto-commit aborted"); rval = AACMPE_CONFIG_STATUS; } - - aac_sync_fib_slot_release(softs, acp); return (rval); } /* * Hardware initialization and resource allocation --- 2613,2622 ----
*** 2775,2784 **** --- 2624,2634 ---- static int aac_common_attach(struct aac_softstate *softs) { uint32_t status; int i; + char version_string[160]; struct aac_supplement_adapter_info sinf; DBCALLED(softs, 1); /*
*** 2786,2797 **** --- 2636,2649 ---- * FIBs in the message queue. At this point there should not be and * if there are they are probably left over from another instance of * the driver like when the system crashes and the crash dump driver * gets loaded. */ + if (softs->hwif != AAC_HWIF_SRC && softs->hwif != AAC_HWIF_SRCV) { while (AAC_OUTB_GET(softs) != 0xfffffffful) ; + } /* * Wait the card to complete booting up before do anything that * attempts to communicate with it. */
*** 2800,2845 **** goto error; i = AAC_FWUP_TIMEOUT * 1000; /* set timeout */ AAC_BUSYWAIT(AAC_FWSTATUS_GET(softs) & AAC_KERNEL_UP_AND_RUNNING, i); if (i == 0) { cmn_err(CE_CONT, "?Fatal error: controller not ready"); ! aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE); ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); goto error; } /* Read and set card supported options and settings */ if (aac_check_firmware(softs) == AACERR) { ! aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE); ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); goto error; } ! /* Add interrupt handlers */ ! if (aac_register_intrs(softs) == AACERR) { ! cmn_err(CE_CONT, ! "?Fatal error: interrupts register failed"); ! goto error; ! } ! /* Setup communication space with the card */ if (softs->comm_space_dma_handle == NULL) { if (aac_alloc_comm_space(softs) != AACOK) goto error; } - if (aac_setup_comm_space(softs) != AACOK) { - cmn_err(CE_CONT, "?Setup communication space failed"); - aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE); - ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); - goto error; - } - #ifdef DEBUG - if (aac_get_fw_debug_buffer(softs) != AACOK) - cmn_err(CE_CONT, "?firmware UART trace not supported"); - #endif - /* Allocate slots */ if ((softs->total_slots == 0) && (aac_create_slots(softs) != AACOK)) { cmn_err(CE_CONT, "?Fatal error: slots allocate failed"); goto error; } --- 2652,2680 ---- goto error; i = AAC_FWUP_TIMEOUT * 1000; /* set timeout */ AAC_BUSYWAIT(AAC_FWSTATUS_GET(softs) & AAC_KERNEL_UP_AND_RUNNING, i); if (i == 0) { cmn_err(CE_CONT, "?Fatal error: controller not ready"); ! aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE, DDI_SERVICE_LOST); goto error; } /* Read and set card supported options and settings */ if (aac_check_firmware(softs) == AACERR) { ! aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE, DDI_SERVICE_LOST); goto error; } ! /* Clear out all interrupts */ ! AAC_STATUS_CLR(softs, ~0); ! /* Allocate communication space with the card */ if (softs->comm_space_dma_handle == NULL) { if (aac_alloc_comm_space(softs) != AACOK) goto error; } /* Allocate slots */ if ((softs->total_slots == 0) && (aac_create_slots(softs) != AACOK)) { cmn_err(CE_CONT, "?Fatal error: slots allocate failed"); goto error; }
*** 2852,2868 **** goto error; AACDB_PRINT(softs, CE_NOTE, "%d fibs allocated", softs->total_fibs); } ! AAC_STATUS_CLR(softs, ~0); /* Clear out all interrupts */ ! AAC_ENABLE_INTR(softs); /* Enable the interrupts we can handle */ - if (aac_get_adapter_info(softs, NULL, &sinf) == AACOK) { - softs->feature_bits = sinf.FeatureBits; - softs->support_opt2 = sinf.SupportedOptions2; - /* Get adapter names */ if (CARD_IS_UNKNOWN(softs->card)) { char *p, *p0, *p1; /* --- 2687,2702 ---- goto error; AACDB_PRINT(softs, CE_NOTE, "%d fibs allocated", softs->total_fibs); } ! if (aac_get_adapter_info(softs, NULL, &sinf) != AACOK) { ! cmn_err(CE_CONT, "?Query adapter information failed"); ! } else { ! softs->aac_feature_bits = sinf.FeatureBits; ! softs->aac_support_opt2 = sinf.SupportedOptions2; /* Get adapter names */ if (CARD_IS_UNKNOWN(softs->card)) { char *p, *p0, *p1; /*
*** 2899,2954 **** if (*p0) (void *)strncpy(softs->product_name, p0, AAC_PRODUCT_LEN); } } - } else { - cmn_err(CE_CONT, "?Query adapter information failed"); } ! cmn_err(CE_NOTE, "!aac driver %d.%02d.%02d-%d, found card: " \ "%s %s(pci0x%x.%x.%x.%x) at 0x%x", AAC_DRIVER_MAJOR_VERSION, AAC_DRIVER_MINOR_VERSION, AAC_DRIVER_BUGFIX_LEVEL, AAC_DRIVER_BUILD, softs->vendor_name, softs->product_name, softs->vendid, softs->devid, softs->subvendid, softs->subsysid, ! softs->pci_mem_base_paddr); /* Perform acceptance of adapter-detected config changes if possible */ if (aac_handle_adapter_config_issues(softs) != AACMPE_OK) { cmn_err(CE_CONT, "?Handle adapter config issues failed"); ! aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE); ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); goto error; } /* Setup containers (logical devices) */ if (aac_probe_containers(softs) != AACOK) { cmn_err(CE_CONT, "?Fatal error: get container info error"); goto error; } - /* Check for JBOD support. Default disable */ - char *data; - if (softs->feature_bits & AAC_FEATURE_SUPPORTED_JBOD) { - if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, softs->devinfo_p, - 0, "jbod-enable", &data) == DDI_SUCCESS)) { - if (strcmp(data, "yes") == 0) { - AACDB_PRINT(softs, CE_NOTE, - "Enable JBOD access"); - softs->flags |= AAC_FLAGS_JBOD; - } - ddi_prop_free(data); - } - } - /* Setup phys. devices */ ! if (softs->flags & (AAC_FLAGS_NONDASD | AAC_FLAGS_JBOD)) { uint32_t bus_max, tgt_max; uint32_t bus, tgt; int index; if (aac_get_bus_info(softs, &bus_max, &tgt_max) != AACOK) { --- 2733,2786 ---- if (*p0) (void *)strncpy(softs->product_name, p0, AAC_PRODUCT_LEN); } } } + if (!(softs->flags & AAC_FLAGS_SYNC_MODE)) { + /* Setup communication space with the card */ + if (aac_setup_comm_space(softs) != AACOK) { + cmn_err(CE_CONT, "?Setup communication space failed"); + aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE, DDI_SERVICE_LOST); + goto error; + } + } ! #ifdef AAC_DEBUG ! if (aac_get_fw_debug_buffer(softs) != AACOK) ! cmn_err(CE_CONT, "?firmware UART trace not supported"); ! #endif ! ! sprintf(version_string, "!aac driver %d.%02d.%02d-%d, found card: " \ "%s %s(pci0x%x.%x.%x.%x) at 0x%x", AAC_DRIVER_MAJOR_VERSION, AAC_DRIVER_MINOR_VERSION, AAC_DRIVER_BUGFIX_LEVEL, AAC_DRIVER_BUILD, softs->vendor_name, softs->product_name, softs->vendid, softs->devid, softs->subvendid, softs->subsysid, ! softs->pci_mem_base_paddr[0]); ! cmn_err(CE_NOTE, version_string); ! AACDB_PRINT(softs, CE_NOTE, version_string); /* Perform acceptance of adapter-detected config changes if possible */ if (aac_handle_adapter_config_issues(softs) != AACMPE_OK) { cmn_err(CE_CONT, "?Handle adapter config issues failed"); ! aac_fm_ereport(softs, DDI_FM_DEVICE_NO_RESPONSE, DDI_SERVICE_LOST); goto error; } /* Setup containers (logical devices) */ if (aac_probe_containers(softs) != AACOK) { cmn_err(CE_CONT, "?Fatal error: get container info error"); goto error; } /* Setup phys. devices */ ! if (softs->flags & AAC_FLAGS_NONDASD) { uint32_t bus_max, tgt_max; uint32_t bus, tgt; int index; if (aac_get_bus_info(softs, &bus_max, &tgt_max) != AACOK) {
*** 2985,3007 **** } } /* Check dma & acc handles allocated in attach */ if (aac_check_dma_handle(softs->comm_space_dma_handle) != DDI_SUCCESS) { ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); goto error; } ! if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) { ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); goto error; } for (i = 0; i < softs->total_slots; i++) { if (aac_check_dma_handle(softs->io_slot[i].fib_dma_handle) != DDI_SUCCESS) { ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); goto error; } } --- 2817,2839 ---- } } /* Check dma & acc handles allocated in attach */ if (aac_check_dma_handle(softs->comm_space_dma_handle) != DDI_SUCCESS) { ! aac_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); goto error; } ! if (aac_check_acc_handle(softs->pci_mem_handle[0]) != DDI_SUCCESS) { ! aac_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); goto error; } for (i = 0; i < softs->total_slots; i++) { if (aac_check_dma_handle(softs->io_slot[i].fib_dma_handle) != DDI_SUCCESS) { ! aac_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); goto error; } }
*** 3029,3041 **** static void aac_common_detach(struct aac_softstate *softs) { DBCALLED(softs, 1); - aac_unregister_intrs(softs); - - mutex_enter(&softs->io_lock); (void) aac_shutdown(softs); if (softs->nondasds) { kmem_free(softs->nondasds, AAC_MAX_PD(softs) * \ sizeof (struct aac_nondasd)); --- 2861,2870 ----
*** 3042,3085 **** softs->nondasds = NULL; } aac_destroy_fibs(softs); aac_destroy_slots(softs); aac_free_comm_space(softs); - mutex_exit(&softs->io_lock); } /* * Send a synchronous command to the controller and wait for a result. * Indicate if the controller completed the command with an error status. */ int aac_sync_mbcommand(struct aac_softstate *softs, uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3, ! uint32_t *statusp) { int timeout; uint32_t status; - if (statusp != NULL) - *statusp = SRB_STATUS_SUCCESS; - /* Fill in mailbox */ AAC_MAILBOX_SET(softs, cmd, arg0, arg1, arg2, arg3); /* Ensure the sync command doorbell flag is cleared */ AAC_STATUS_CLR(softs, AAC_DB_SYNC_COMMAND); /* Then set it to signal the adapter */ AAC_NOTIFY(softs, AAC_DB_SYNC_COMMAND); /* Spin waiting for the command to complete */ timeout = AAC_IMMEDIATE_TIMEOUT * 1000; AAC_BUSYWAIT(AAC_STATUS_GET(softs) & AAC_DB_SYNC_COMMAND, timeout); if (!timeout) { AACDB_PRINT(softs, CE_WARN, ! "Sync command timed out after %d seconds (0x%x)!", ! AAC_IMMEDIATE_TIMEOUT, AAC_FWSTATUS_GET(softs)); return (AACERR); } /* Clear the completion flag */ AAC_STATUS_CLR(softs, AAC_DB_SYNC_COMMAND); --- 2871,2914 ---- softs->nondasds = NULL; } aac_destroy_fibs(softs); aac_destroy_slots(softs); aac_free_comm_space(softs); } /* * Send a synchronous command to the controller and wait for a result. * Indicate if the controller completed the command with an error status. */ int aac_sync_mbcommand(struct aac_softstate *softs, uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3, ! uint32_t *statusp, uint32_t *r1) { int timeout; uint32_t status; /* Fill in mailbox */ AAC_MAILBOX_SET(softs, cmd, arg0, arg1, arg2, arg3); /* Ensure the sync command doorbell flag is cleared */ AAC_STATUS_CLR(softs, AAC_DB_SYNC_COMMAND); /* Then set it to signal the adapter */ AAC_NOTIFY(softs, AAC_DB_SYNC_COMMAND); + if ((cmd != AAC_MONKER_SYNCFIB) || (statusp == NULL) || (*statusp != 0)) { + if (statusp != NULL) + *statusp = SRB_STATUS_SUCCESS; /* Spin waiting for the command to complete */ timeout = AAC_IMMEDIATE_TIMEOUT * 1000; AAC_BUSYWAIT(AAC_STATUS_GET(softs) & AAC_DB_SYNC_COMMAND, timeout); if (!timeout) { AACDB_PRINT(softs, CE_WARN, ! "Sync command %d timed out after %d seconds (0x%x)!", ! cmd, AAC_IMMEDIATE_TIMEOUT, AAC_FWSTATUS_GET(softs)); ! softs->sync_slot_busy = 0; return (AACERR); } /* Clear the completion flag */ AAC_STATUS_CLR(softs, AAC_DB_SYNC_COMMAND);
*** 3088,3100 **** status = AAC_MAILBOX_GET(softs, 0); if (statusp != NULL) *statusp = status; if (status != SRB_STATUS_SUCCESS) { AACDB_PRINT(softs, CE_WARN, ! "Sync command fail: status = 0x%x", status); return (AACERR); } return (AACOK); } /* --- 2917,2934 ---- status = AAC_MAILBOX_GET(softs, 0); if (statusp != NULL) *statusp = status; if (status != SRB_STATUS_SUCCESS) { AACDB_PRINT(softs, CE_WARN, ! "Sync command %d failed: status = 0x%x", cmd, status); ! softs->sync_slot_busy = 0; return (AACERR); } + if (r1 != NULL) + *r1 = AAC_MAILBOX_GET(softs, 1); + softs->sync_slot_busy = 0; + } return (AACOK); } /*
*** 3101,3137 **** * Send a synchronous FIB to the adapter and wait for its completion */ static int aac_sync_fib(struct aac_softstate *softs, uint16_t cmd, uint16_t fibsize) { ! struct aac_cmd *acp = &softs->sync_ac; ! acp->flags = AAC_CMD_SYNC | AAC_CMD_IN_SYNC_SLOT; ! if (softs->state & AAC_STATE_INTR) ! acp->flags |= AAC_CMD_NO_CB; ! else ! acp->flags |= AAC_CMD_NO_INTR; - acp->ac_comp = aac_sync_complete; - acp->timeout = AAC_SYNC_TIMEOUT; - acp->fib_size = fibsize; - /* ! * Only need to setup sync fib header, caller should have init ! * fib data */ ! aac_cmd_fib_header(softs, acp, cmd); ! (void) ddi_dma_sync(acp->slotp->fib_dma_handle, 0, fibsize, ! DDI_DMA_SYNC_FORDEV); ! aac_start_io(softs, acp); ! if (softs->state & AAC_STATE_INTR) ! return (aac_do_sync_io(softs, acp)); ! else ! return (aac_do_poll_io(softs, acp)); } static void aac_cmd_initq(struct aac_cmd_queue *q) { --- 2935,2982 ---- * Send a synchronous FIB to the adapter and wait for its completion */ static int aac_sync_fib(struct aac_softstate *softs, uint16_t cmd, uint16_t fibsize) { ! struct aac_slot *slotp = softs->sync_slot; ! ddi_dma_handle_t dma = slotp->fib_dma_handle; ! uint32_t status = 1; ! int rval; ! /* Sync fib only supports 512 bytes */ ! if (fibsize > AAC_FIB_SIZE) ! return (AACERR); /* ! * Setup sync fib ! * Need not reinitialize FIB header if it's already been filled ! * by others like aac_cmd_fib_scsi as aac_cmd. */ ! if (slotp->acp == NULL) ! aac_cmd_fib_header(softs, slotp, cmd, fibsize); ! (void) ddi_dma_sync(dma, 0, fibsize, DDI_DMA_SYNC_FORDEV); ! /* Give the FIB to the controller, wait for a response. */ ! softs->sync_slot_busy = 1; ! rval = aac_sync_mbcommand(softs, AAC_MONKER_SYNCFIB, ! slotp->fib_phyaddr, 0, 0, 0, &status, NULL); ! if (rval == AACERR) { ! AACDB_PRINT(softs, CE_WARN, ! "Send sync fib to controller failed"); ! return (AACERR); ! } ! (void) ddi_dma_sync(dma, 0, AAC_FIB_SIZE, DDI_DMA_SYNC_FORCPU); ! ! if ((aac_check_acc_handle(softs->pci_mem_handle[0]) != DDI_SUCCESS) || ! (aac_check_dma_handle(dma) != DDI_SUCCESS)) { ! aac_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); ! return (AACERR); ! } ! ! return (AACOK); } static void aac_cmd_initq(struct aac_cmd_queue *q) {
*** 3209,3223 **** DBCALLED(softs, 2); ASSERT(queue == AAC_ADAP_NORM_CMD_Q || queue == AAC_ADAP_NORM_RESP_Q); /* Get the producer/consumer indices */ ! (void) ddi_dma_sync(dma, (uintptr_t)softs->qtablep->qt_qindex[queue] - \ ! (uintptr_t)softs->comm_space, sizeof (uint32_t) * 2, DDI_DMA_SYNC_FORCPU); if (aac_check_dma_handle(dma) != DDI_SUCCESS) { ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); return (AACERR); } pi = ddi_get32(acc, &softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX]); --- 3054,3068 ---- DBCALLED(softs, 2); ASSERT(queue == AAC_ADAP_NORM_CMD_Q || queue == AAC_ADAP_NORM_RESP_Q); /* Get the producer/consumer indices */ ! (void) ddi_dma_sync(dma, (uint8_t *)softs->qtablep->qt_qindex[queue] - \ ! (uint8_t *)softs->comm_space, sizeof (uint32_t) * 2, DDI_DMA_SYNC_FORCPU); if (aac_check_dma_handle(dma) != DDI_SUCCESS) { ! aac_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); return (AACERR); } pi = ddi_get32(acc, &softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX]);
*** 3236,3255 **** return (AACERR); /* Fill in queue entry */ ddi_put32(acc, &((softs->qentries[queue] + pi)->aq_fib_size), fib_size); ddi_put32(acc, &((softs->qentries[queue] + pi)->aq_fib_addr), fib_addr); ! (void) ddi_dma_sync(dma, (uintptr_t)(softs->qentries[queue] + pi) - \ ! (uintptr_t)softs->comm_space, sizeof (struct aac_queue_entry), DDI_DMA_SYNC_FORDEV); /* Update producer index */ ddi_put32(acc, &softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX], pi + 1); (void) ddi_dma_sync(dma, ! (uintptr_t)&softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX] - \ ! (uintptr_t)softs->comm_space, sizeof (uint32_t), DDI_DMA_SYNC_FORDEV); if (aac_qinfo[queue].notify != 0) AAC_NOTIFY(softs, aac_qinfo[queue].notify); return (AACOK); --- 3081,3100 ---- return (AACERR); /* Fill in queue entry */ ddi_put32(acc, &((softs->qentries[queue] + pi)->aq_fib_size), fib_size); ddi_put32(acc, &((softs->qentries[queue] + pi)->aq_fib_addr), fib_addr); ! (void) ddi_dma_sync(dma, (uint8_t *)(softs->qentries[queue] + pi) - \ ! (uint8_t *)softs->comm_space, sizeof (struct aac_queue_entry), DDI_DMA_SYNC_FORDEV); /* Update producer index */ ddi_put32(acc, &softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX], pi + 1); (void) ddi_dma_sync(dma, ! (uint8_t *)&softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX] - \ ! (uint8_t *)softs->comm_space, sizeof (uint32_t), DDI_DMA_SYNC_FORDEV); if (aac_qinfo[queue].notify != 0) AAC_NOTIFY(softs, aac_qinfo[queue].notify); return (AACOK);
*** 3270,3281 **** DBCALLED(softs, 2); ASSERT(idxp); /* Get the producer/consumer indices */ ! (void) ddi_dma_sync(dma, (uintptr_t)softs->qtablep->qt_qindex[queue] - \ ! (uintptr_t)softs->comm_space, sizeof (uint32_t) * 2, DDI_DMA_SYNC_FORCPU); pi = ddi_get32(acc, &softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX]); ci = ddi_get32(acc, &softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX]); --- 3115,3126 ---- DBCALLED(softs, 2); ASSERT(idxp); /* Get the producer/consumer indices */ ! (void) ddi_dma_sync(dma, (uint8_t *)softs->qtablep->qt_qindex[queue] - \ ! (uint8_t *)softs->comm_space, sizeof (uint32_t) * 2, DDI_DMA_SYNC_FORCPU); pi = ddi_get32(acc, &softs->qtablep->qt_qindex[queue][AAC_PRODUCER_INDEX]); ci = ddi_get32(acc, &softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX]);
*** 3297,3311 **** */ if (ci >= aac_qinfo[queue].size) ci = 0; /* Fetch the entry */ ! (void) ddi_dma_sync(dma, (uintptr_t)(softs->qentries[queue] + pi) - \ ! (uintptr_t)softs->comm_space, sizeof (struct aac_queue_entry), DDI_DMA_SYNC_FORCPU); if (aac_check_dma_handle(dma) != DDI_SUCCESS) { ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); return (AACERR); } switch (queue) { case AAC_HOST_NORM_RESP_Q: --- 3142,3156 ---- */ if (ci >= aac_qinfo[queue].size) ci = 0; /* Fetch the entry */ ! (void) ddi_dma_sync(dma, (uint8_t *)(softs->qentries[queue] + pi) - \ ! (uint8_t *)softs->comm_space, sizeof (struct aac_queue_entry), DDI_DMA_SYNC_FORCPU); if (aac_check_dma_handle(dma) != DDI_SUCCESS) { ! aac_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); return (AACERR); } switch (queue) { case AAC_HOST_NORM_RESP_Q:
*** 3327,3350 **** /* Update consumer index */ ddi_put32(acc, &softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX], ci + 1); (void) ddi_dma_sync(dma, ! (uintptr_t)&softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX] - \ ! (uintptr_t)softs->comm_space, sizeof (uint32_t), DDI_DMA_SYNC_FORDEV); if (unfull && aac_qinfo[queue].notify != 0) AAC_NOTIFY(softs, aac_qinfo[queue].notify); return (AACOK); } static struct aac_mntinforesp * ! aac_get_mntinfo(struct aac_softstate *softs, int cid) { ! ddi_acc_handle_t acc = softs->sync_ac.slotp->fib_acc_handle; ! struct aac_fib *fibp = softs->sync_ac.slotp->fibp; struct aac_mntinfo *mi = (struct aac_mntinfo *)&fibp->data[0]; struct aac_mntinforesp *mir; ddi_put32(acc, &mi->Command, /* Use 64-bit LBA if enabled */ (softs->flags & AAC_FLAGS_LBA_64BIT) ? --- 3172,3198 ---- /* Update consumer index */ ddi_put32(acc, &softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX], ci + 1); (void) ddi_dma_sync(dma, ! (uint8_t *)&softs->qtablep->qt_qindex[queue][AAC_CONSUMER_INDEX] - \ ! (uint8_t *)softs->comm_space, sizeof (uint32_t), DDI_DMA_SYNC_FORDEV); if (unfull && aac_qinfo[queue].notify != 0) AAC_NOTIFY(softs, aac_qinfo[queue].notify); return (AACOK); } + /* + * Request information of the container cid + */ static struct aac_mntinforesp * ! aac_get_container_info(struct aac_softstate *softs, int cid) { ! ddi_acc_handle_t acc = softs->sync_slot->fib_acc_handle; ! struct aac_fib *fibp = softs->sync_slot->fibp; struct aac_mntinfo *mi = (struct aac_mntinfo *)&fibp->data[0]; struct aac_mntinforesp *mir; ddi_put32(acc, &mi->Command, /* Use 64-bit LBA if enabled */ (softs->flags & AAC_FLAGS_LBA_64BIT) ?
*** 3365,3405 **** } static int aac_get_container_count(struct aac_softstate *softs, int *count) { ! ddi_acc_handle_t acc; struct aac_mntinforesp *mir; - int rval; ! (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac); ! acc = softs->sync_ac.slotp->fib_acc_handle; ! ! if ((mir = aac_get_mntinfo(softs, 0)) == NULL) { ! rval = AACERR; ! goto finish; ! } *count = ddi_get32(acc, &mir->MntRespCount); if (*count > AAC_MAX_LD) { AACDB_PRINT(softs, CE_CONT, "container count(%d) > AAC_MAX_LD", *count); ! rval = AACERR; ! goto finish; } ! rval = AACOK; ! ! finish: ! aac_sync_fib_slot_release(softs, &softs->sync_ac); ! return (rval); } static int aac_get_container_uid(struct aac_softstate *softs, uint32_t cid, uint32_t *uid) { ! ddi_acc_handle_t acc = softs->sync_ac.slotp->fib_acc_handle; struct aac_Container *ct = (struct aac_Container *) \ ! &softs->sync_ac.slotp->fibp->data[0]; bzero(ct, sizeof (*ct) - CT_PACKET_SIZE); ddi_put32(acc, &ct->Command, VM_ContainerConfig); ddi_put32(acc, &ct->CTCommand.command, CT_CID_TO_32BITS_UID); ddi_put32(acc, &ct->CTCommand.param[0], cid); --- 3213,3242 ---- } static int aac_get_container_count(struct aac_softstate *softs, int *count) { ! ddi_acc_handle_t acc = softs->sync_slot->fib_acc_handle; struct aac_mntinforesp *mir; ! if ((mir = aac_get_container_info(softs, 0)) == NULL) ! return (AACERR); *count = ddi_get32(acc, &mir->MntRespCount); if (*count > AAC_MAX_LD) { AACDB_PRINT(softs, CE_CONT, "container count(%d) > AAC_MAX_LD", *count); ! return (AACERR); } ! return (AACOK); } static int aac_get_container_uid(struct aac_softstate *softs, uint32_t cid, uint32_t *uid) { ! ddi_acc_handle_t acc = softs->sync_slot->fib_acc_handle; struct aac_Container *ct = (struct aac_Container *) \ ! &softs->sync_slot->fibp->data[0]; bzero(ct, sizeof (*ct) - CT_PACKET_SIZE); ddi_put32(acc, &ct->Command, VM_ContainerConfig); ddi_put32(acc, &ct->CTCommand.command, CT_CID_TO_32BITS_UID); ddi_put32(acc, &ct->CTCommand.param[0], cid);
*** 3412,3500 **** *uid = ddi_get32(acc, &ct->CTCommand.param[1]); return (AACOK); } ! /* ! * Request information of the container cid ! */ ! static struct aac_mntinforesp * ! aac_get_container_info(struct aac_softstate *softs, int cid) ! { ! ddi_acc_handle_t acc = softs->sync_ac.slotp->fib_acc_handle; ! struct aac_mntinforesp *mir; ! int rval_uid; ! uint32_t uid; ! ! /* Get container UID first so that it will not overwrite mntinfo */ ! rval_uid = aac_get_container_uid(softs, cid, &uid); ! ! /* Get container basic info */ ! if ((mir = aac_get_mntinfo(softs, cid)) == NULL) { ! AACDB_PRINT(softs, CE_CONT, ! "query container %d info failed", cid); ! return (NULL); ! } ! if (ddi_get32(acc, &mir->MntObj.VolType) == CT_NONE) ! return (mir); ! if (rval_uid != AACOK) { ! AACDB_PRINT(softs, CE_CONT, ! "query container %d uid failed", cid); ! return (NULL); ! } ! ! ddi_put32(acc, &mir->Status, uid); ! return (mir); ! } ! ! static enum aac_cfg_event aac_probe_container(struct aac_softstate *softs, uint32_t cid) { - enum aac_cfg_event event = AAC_CFG_NULL_NOEXIST; struct aac_container *dvp = &softs->containers[cid]; struct aac_mntinforesp *mir; ! ddi_acc_handle_t acc; - (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac); - acc = softs->sync_ac.slotp->fib_acc_handle; - /* Get container basic info */ ! if ((mir = aac_get_container_info(softs, cid)) == NULL) { ! /* AAC_CFG_NULL_NOEXIST */ ! goto finish; ! } if (ddi_get32(acc, &mir->MntObj.VolType) == CT_NONE) { ! if (AAC_DEV_IS_VALID(&dvp->dev)) { AACDB_PRINT(softs, CE_NOTE, ">>> Container %d deleted", cid); ! dvp->dev.flags &= ~AAC_DFLAG_VALID; ! event = AAC_CFG_DELETE; } - /* AAC_CFG_NULL_NOEXIST */ } else { ! uint64_t size; ! uint32_t uid; ! event = AAC_CFG_NULL_EXIST; ! size = AAC_MIR_SIZE(softs, acc, mir); ! uid = ddi_get32(acc, &mir->Status); ! if (AAC_DEV_IS_VALID(&dvp->dev)) { if (dvp->uid != uid) { AACDB_PRINT(softs, CE_WARN, ">>> Container %u uid changed to %d", cid, uid); dvp->uid = uid; - event = AAC_CFG_CHANGE; } if (dvp->size != size) { AACDB_PRINT(softs, CE_NOTE, ">>> Container %u size changed to %"PRIu64, cid, size); dvp->size = size; - event = AAC_CFG_CHANGE; } } else { /* Init new container */ AACDB_PRINT(softs, CE_NOTE, ">>> Container %d added: " \ "size=0x%x.%08x, type=%d, name=%s", --- 3249,3302 ---- *uid = ddi_get32(acc, &ct->CTCommand.param[1]); return (AACOK); } ! static int aac_probe_container(struct aac_softstate *softs, uint32_t cid) { struct aac_container *dvp = &softs->containers[cid]; + ddi_acc_handle_t acc = softs->sync_slot->fib_acc_handle; struct aac_mntinforesp *mir; ! uint64_t size; ! uint32_t uid; /* Get container basic info */ ! if ((mir = aac_get_container_info(softs, cid)) == NULL) ! return (AACERR); if (ddi_get32(acc, &mir->MntObj.VolType) == CT_NONE) { ! if (dvp->dev.valid) { AACDB_PRINT(softs, CE_NOTE, ">>> Container %d deleted", cid); ! dvp->dev.valid = 0; ! (void) aac_dr_event(softs, dvp->cid, -1, ! AAC_DEV_OFFLINE); } } else { ! size = AAC_MIR_SIZE(softs, acc, mir); ! /* Get container UID */ ! if (aac_get_container_uid(softs, cid, &uid) == AACERR) { ! AACDB_PRINT(softs, CE_CONT, ! "query container %d uid failed", cid); ! return (AACERR); ! } ! AACDB_PRINT(softs, CE_CONT, "uid=0x%08x", uid); ! if (dvp->dev.valid) { if (dvp->uid != uid) { AACDB_PRINT(softs, CE_WARN, ">>> Container %u uid changed to %d", cid, uid); dvp->uid = uid; } if (dvp->size != size) { AACDB_PRINT(softs, CE_NOTE, ">>> Container %u size changed to %"PRIu64, cid, size); dvp->size = size; } } else { /* Init new container */ AACDB_PRINT(softs, CE_NOTE, ">>> Container %d added: " \ "size=0x%x.%08x, type=%d, name=%s",
*** 3501,3526 **** cid, ddi_get32(acc, &mir->MntObj.CapacityHigh), ddi_get32(acc, &mir->MntObj.Capacity), ddi_get32(acc, &mir->MntObj.VolType), mir->MntObj.FileSystemName); ! dvp->dev.flags |= AAC_DFLAG_VALID; dvp->dev.type = AAC_DEV_LD; dvp->cid = cid; dvp->uid = uid; dvp->size = size; dvp->locked = 0; dvp->deleted = 0; ! ! event = AAC_CFG_ADD; } } ! ! finish: ! aac_sync_fib_slot_release(softs, &softs->sync_ac); ! return (event); } /* * Do a rescan of all the possible containers and update the container list * with newly online/offline containers, and prepare for autoconfiguration. --- 3303,3325 ---- cid, ddi_get32(acc, &mir->MntObj.CapacityHigh), ddi_get32(acc, &mir->MntObj.Capacity), ddi_get32(acc, &mir->MntObj.VolType), mir->MntObj.FileSystemName); ! dvp->dev.valid = 1; dvp->dev.type = AAC_DEV_LD; dvp->cid = cid; dvp->uid = uid; dvp->size = size; dvp->locked = 0; dvp->deleted = 0; ! (void) aac_dr_event(softs, dvp->cid, -1, ! AAC_DEV_ONLINE); } } ! return (AACOK); } /* * Do a rescan of all the possible containers and update the container list * with newly online/offline containers, and prepare for autoconfiguration.
*** 3532,3602 **** /* Loop over possible containers */ count = softs->container_count; if (aac_get_container_count(softs, &count) == AACERR) return (AACERR); - for (i = total = 0; i < count; i++) { ! enum aac_cfg_event event = aac_probe_container(softs, i); ! if ((event != AAC_CFG_NULL_NOEXIST) && ! (event != AAC_CFG_NULL_EXIST)) { ! (void) aac_handle_dr(softs, i, -1, event); total++; } - } - if (count < softs->container_count) { struct aac_container *dvp; for (dvp = &softs->containers[count]; dvp < &softs->containers[softs->container_count]; dvp++) { ! if (!AAC_DEV_IS_VALID(&dvp->dev)) continue; AACDB_PRINT(softs, CE_NOTE, ">>> Container %d deleted", dvp->cid); ! dvp->dev.flags &= ~AAC_DFLAG_VALID; ! (void) aac_handle_dr(softs, dvp->cid, -1, ! AAC_CFG_DELETE); } } - softs->container_count = count; ! AACDB_PRINT(softs, CE_CONT, "?Total %d container(s) found", total); return (AACOK); } static int - aac_probe_jbod(struct aac_softstate *softs, int tgt, int event) - { - ASSERT(AAC_MAX_LD <= tgt); - ASSERT(tgt < AAC_MAX_DEV(softs)); - struct aac_device *dvp; - dvp = AAC_DEV(softs, tgt); - - switch (event) { - case AAC_CFG_ADD: - AACDB_PRINT(softs, CE_NOTE, - ">>> Jbod %d added", tgt - AAC_MAX_LD); - dvp->flags |= AAC_DFLAG_VALID; - dvp->type = AAC_DEV_PD; - break; - case AAC_CFG_DELETE: - AACDB_PRINT(softs, CE_NOTE, - ">>> Jbod %d deleted", tgt - AAC_MAX_LD); - dvp->flags &= ~AAC_DFLAG_VALID; - break; - default: - return (AACERR); - } - (void) aac_handle_dr(softs, tgt, 0, event); - return (AACOK); - } - - static int aac_alloc_comm_space(struct aac_softstate *softs) { ! size_t rlen; ddi_dma_cookie_t cookie; uint_t cookien; /* Allocate DMA for comm. space */ if (ddi_dma_alloc_handle( --- 3331,3367 ---- /* Loop over possible containers */ count = softs->container_count; if (aac_get_container_count(softs, &count) == AACERR) return (AACERR); for (i = total = 0; i < count; i++) { ! if (aac_probe_container(softs, i) == AACOK) total++; } if (count < softs->container_count) { struct aac_container *dvp; for (dvp = &softs->containers[count]; dvp < &softs->containers[softs->container_count]; dvp++) { ! if (dvp->dev.valid == 0) continue; AACDB_PRINT(softs, CE_NOTE, ">>> Container %d deleted", dvp->cid); ! dvp->dev.valid = 0; ! (void) aac_dr_event(softs, dvp->cid, -1, ! AAC_DEV_OFFLINE); } } softs->container_count = count; ! AACDB_PRINT(softs, CE_CONT, "Total %d container(s) found", total); return (AACOK); } static int aac_alloc_comm_space(struct aac_softstate *softs) { ! size_t rlen, maxsize; ddi_dma_cookie_t cookie; uint_t cookien; /* Allocate DMA for comm. space */ if (ddi_dma_alloc_handle(
*** 3607,3620 **** &softs->comm_space_dma_handle) != DDI_SUCCESS) { AACDB_PRINT(softs, CE_WARN, "Cannot alloc dma handle for communication area"); goto error; } if (ddi_dma_mem_alloc( softs->comm_space_dma_handle, ! sizeof (struct aac_comm_space), ! &softs->acc_attr, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, (caddr_t *)&softs->comm_space, &rlen, --- 3372,3390 ---- &softs->comm_space_dma_handle) != DDI_SUCCESS) { AACDB_PRINT(softs, CE_WARN, "Cannot alloc dma handle for communication area"); goto error; } + + maxsize = sizeof(struct aac_comm_space); + if ((softs->flags & AAC_FLAGS_NEW_COMM_TYPE1) || + (softs->flags & AAC_FLAGS_NEW_COMM_TYPE2)) + maxsize += (softs->aac_max_fibs-1) * sizeof(uint32_t); if (ddi_dma_mem_alloc( softs->comm_space_dma_handle, ! maxsize, ! &aac_acc_attr, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, (caddr_t *)&softs->comm_space, &rlen,
*** 3625,3644 **** } if (ddi_dma_addr_bind_handle( softs->comm_space_dma_handle, NULL, (caddr_t)softs->comm_space, ! sizeof (struct aac_comm_space), DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &cookie, &cookien) != DDI_DMA_MAPPED) { AACDB_PRINT(softs, CE_WARN, "DMA bind failed for communication area"); goto error; } softs->comm_space_phyaddr = cookie.dmac_address; return (AACOK); error: if (softs->comm_space_acc_handle) { --- 3395,3416 ---- } if (ddi_dma_addr_bind_handle( softs->comm_space_dma_handle, NULL, (caddr_t)softs->comm_space, ! maxsize, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &cookie, &cookien) != DDI_DMA_MAPPED) { AACDB_PRINT(softs, CE_WARN, "DMA bind failed for communication area"); goto error; } + + bzero(softs->comm_space, maxsize); softs->comm_space_phyaddr = cookie.dmac_address; return (AACOK); error: if (softs->comm_space_acc_handle) {
*** 3653,3663 **** } static void aac_free_comm_space(struct aac_softstate *softs) { - (void) ddi_dma_unbind_handle(softs->comm_space_dma_handle); ddi_dma_mem_free(&softs->comm_space_acc_handle); softs->comm_space_acc_handle = NULL; ddi_dma_free_handle(&softs->comm_space_dma_handle); softs->comm_space_dma_handle = NULL; --- 3425,3434 ----
*** 3677,3711 **** struct aac_adapter_init *initp; int qoffset; comm_space_phyaddr = softs->comm_space_phyaddr; /* Setup adapter init struct */ initp = &softs->comm_space->init_data; - bzero(initp, sizeof (struct aac_adapter_init)); ddi_put32(acc, &initp->InitStructRevision, AAC_INIT_STRUCT_REVISION); ddi_put32(acc, &initp->HostElapsedSeconds, ddi_get_time()); /* Setup new/old comm. specific data */ ! if (softs->flags & AAC_FLAGS_RAW_IO) { uint32_t init_flags = 0; - if (softs->flags & AAC_FLAGS_NEW_COMM) init_flags |= AAC_INIT_FLAGS_NEW_COMM_SUPPORTED; ! /* AAC_SUPPORTED_POWER_MANAGEMENT */ init_flags |= AAC_INIT_FLAGS_DRIVER_SUPPORTS_PM; init_flags |= AAC_INIT_FLAGS_DRIVER_USES_UTC_TIME; - ddi_put32(acc, &initp->InitStructRevision, - AAC_INIT_STRUCT_REVISION_4); ddi_put32(acc, &initp->InitFlags, init_flags); /* Setup the preferred settings */ ddi_put32(acc, &initp->MaxIoCommands, softs->aac_max_fibs); ddi_put32(acc, &initp->MaxIoSize, (softs->aac_max_sectors << 9)); ddi_put32(acc, &initp->MaxFibSize, softs->aac_max_fib_size); } else { /* * Tells the adapter about the physical location of various * important shared data structures */ --- 3448,3501 ---- struct aac_adapter_init *initp; int qoffset; comm_space_phyaddr = softs->comm_space_phyaddr; + /* reset rrq index */ + softs->aac_host_rrq_idx = 0; + /* Setup adapter init struct */ initp = &softs->comm_space->init_data; ddi_put32(acc, &initp->InitStructRevision, AAC_INIT_STRUCT_REVISION); ddi_put32(acc, &initp->HostElapsedSeconds, ddi_get_time()); + ddi_put32(acc, &initp->MiniPortRevision,AAC_INIT_STRUCT_MINIPORT_REVISION); /* Setup new/old comm. specific data */ ! if (softs->flags & AAC_FLAGS_NEW_COMM) { uint32_t init_flags = 0; init_flags |= AAC_INIT_FLAGS_NEW_COMM_SUPPORTED; ! if (softs->flags & AAC_FLAGS_NEW_COMM_TYPE1) { ! init_flags |= (AAC_INITFLAGS_NEW_COMM_TYPE1_SUPPORTED | ! AAC_INITFLAGS_DRIVER_SUPPORTS_FAST_JBOD); ! ddi_put32(acc, &initp->InitStructRevision, ! AAC_INIT_STRUCT_REVISION_6); ! } else if (softs->flags & AAC_FLAGS_NEW_COMM_TYPE2) { ! init_flags |= (AAC_INITFLAGS_NEW_COMM_TYPE2_SUPPORTED | ! AAC_INITFLAGS_DRIVER_SUPPORTS_FAST_JBOD); ! ddi_put32(acc, &initp->InitStructRevision, ! AAC_INIT_STRUCT_REVISION_7); ! ddi_put32(acc, &initp->MiniPortRevision, 0L); ! } else { ! ddi_put32(acc, &initp->InitStructRevision, ! AAC_INIT_STRUCT_REVISION_4); ! } ! if (softs->aac_support_opt2 & AAC_SUPPORTED_POWER_MANAGEMENT) { init_flags |= AAC_INIT_FLAGS_DRIVER_SUPPORTS_PM; init_flags |= AAC_INIT_FLAGS_DRIVER_USES_UTC_TIME; + } ddi_put32(acc, &initp->InitFlags, init_flags); /* Setup the preferred settings */ ddi_put32(acc, &initp->MaxIoCommands, softs->aac_max_fibs); ddi_put32(acc, &initp->MaxIoSize, (softs->aac_max_sectors << 9)); ddi_put32(acc, &initp->MaxFibSize, softs->aac_max_fib_size); + ddi_put32(acc, &initp->MaxNumAif, softs->aac_max_aif); + ddi_put32(acc, &initp->HostRRQ_AddrLow, + comm_space_phyaddr + offsetof(struct aac_comm_space,aac_host_rrq)); } else { /* * Tells the adapter about the physical location of various * important shared data structures */
*** 3719,3730 **** ddi_put32(acc, &initp->PrintfBufferAddress, comm_space_phyaddr + \ offsetof(struct aac_comm_space, adapter_print_buf)); ddi_put32(acc, &initp->PrintfBufferSize, AAC_ADAPTER_PRINT_BUFSIZE); - ddi_put32(acc, &initp->MiniPortRevision, - AAC_INIT_STRUCT_MINIPORT_REVISION); ddi_put32(acc, &initp->HostPhysMemPages, AAC_MAX_PFN); qoffset = (comm_space_phyaddr + \ offsetof(struct aac_comm_space, qtable)) % \ AAC_QUEUE_ALIGN; --- 3509,3518 ----
*** 3804,3817 **** &softs->qtablep->qt_AdapHighRespQueue[0]; } (void) ddi_dma_sync(dma, 0, 0, DDI_DMA_SYNC_FORDEV); /* Send init structure to the card */ if (aac_sync_mbcommand(softs, AAC_MONKER_INITSTRUCT, comm_space_phyaddr + \ offsetof(struct aac_comm_space, init_data), ! 0, 0, 0, NULL) == AACERR) { AACDB_PRINT(softs, CE_WARN, "Cannot send init structure to adapter"); return (AACERR); } --- 3592,3606 ---- &softs->qtablep->qt_AdapHighRespQueue[0]; } (void) ddi_dma_sync(dma, 0, 0, DDI_DMA_SYNC_FORDEV); /* Send init structure to the card */ + softs->sync_slot_busy = 1; if (aac_sync_mbcommand(softs, AAC_MONKER_INITSTRUCT, comm_space_phyaddr + \ offsetof(struct aac_comm_space, init_data), ! 0, 0, 0, NULL, NULL) == AACERR) { AACDB_PRINT(softs, CE_WARN, "Cannot send init structure to adapter"); return (AACERR); }
*** 3915,3925 **** break; case 0x83: /* Device identification page */ if (vpdp == NULL || ! bp->b_bcount < (AAC_VPD_PAGE_DATA + 32)) return; bzero(vpdp, AAC_VPD_PAGE_LENGTH); vpdp[AAC_VPD_PAGE_CODE] = 0x83; idp = &vpdp[AAC_VPD_PAGE_DATA]; --- 3704,3714 ---- break; case 0x83: /* Device identification page */ if (vpdp == NULL || ! bp->b_bcount < (AAC_VPD_ID_DATA + 32)) return; bzero(vpdp, AAC_VPD_PAGE_LENGTH); vpdp[AAC_VPD_PAGE_CODE] = 0x83; idp = &vpdp[AAC_VPD_PAGE_DATA];
*** 3937,3951 **** */ sp = &idp[AAC_VPD_ID_DATA]; sp = aac_vendor_id(softs, sp); sp = aac_product_id(softs, sp); sp = aac_lun_serialno(softs, tgt, sp); ! idp[AAC_VPD_ID_LENGTH] = (uintptr_t)sp - \ ! (uintptr_t)&idp[AAC_VPD_ID_DATA]; ! vpdp[AAC_VPD_PAGE_LENGTH] = (uintptr_t)sp - \ ! (uintptr_t)&vpdp[AAC_VPD_PAGE_DATA]; pkt->pkt_state |= STATE_XFERRED_DATA; break; default: aac_set_arq_data(pkt, KEY_ILLEGAL_REQUEST, --- 3726,3739 ---- */ sp = &idp[AAC_VPD_ID_DATA]; sp = aac_vendor_id(softs, sp); sp = aac_product_id(softs, sp); sp = aac_lun_serialno(softs, tgt, sp); ! idp[AAC_VPD_ID_LENGTH] = sp - &idp[AAC_VPD_ID_DATA]; ! vpdp[AAC_VPD_PAGE_LENGTH] = ! sp - &vpdp[AAC_VPD_PAGE_DATA]; pkt->pkt_state |= STATE_XFERRED_DATA; break; default: aac_set_arq_data(pkt, KEY_ILLEGAL_REQUEST,
*** 3988,4127 **** static void aac_mode_sense(struct aac_softstate *softs, struct scsi_pkt *pkt, union scsi_cdb *cdbp, struct buf *bp, int capacity) { uchar_t pagecode; struct mode_header *headerp; - struct mode_header_g1 *g1_headerp; unsigned int ncyl; ! caddr_t sense_data; ! caddr_t next_page; ! size_t sdata_size; ! size_t pages_size; ! int unsupport_page = 0; - ASSERT(cdbp->scc_cmd == SCMD_MODE_SENSE || - cdbp->scc_cmd == SCMD_MODE_SENSE_G1); - if (!(bp && bp->b_un.b_addr && bp->b_bcount)) return; if (bp->b_flags & (B_PHYS | B_PAGEIO)) bp_mapin(bp); pkt->pkt_state |= STATE_XFERRED_DATA; ! pagecode = cdbp->cdb_un.sg.scsi[0] & 0x3F; - /* calculate the size of needed buffer */ - if (cdbp->scc_cmd == SCMD_MODE_SENSE) - sdata_size = MODE_HEADER_LENGTH; - else /* must be SCMD_MODE_SENSE_G1 */ - sdata_size = MODE_HEADER_LENGTH_G1; - - pages_size = 0; switch (pagecode) { - case SD_MODE_SENSE_PAGE3_CODE: - pages_size += sizeof (struct mode_format); - break; - - case SD_MODE_SENSE_PAGE4_CODE: - pages_size += sizeof (struct mode_geometry); - break; - - case MODEPAGE_CTRL_MODE: - if (softs->flags & AAC_FLAGS_LBA_64BIT) { - pages_size += sizeof (struct mode_control_scsi3); - } else { - unsupport_page = 1; - } - break; - - case MODEPAGE_ALLPAGES: - if (softs->flags & AAC_FLAGS_LBA_64BIT) { - pages_size += sizeof (struct mode_format) + - sizeof (struct mode_geometry) + - sizeof (struct mode_control_scsi3); - } else { - pages_size += sizeof (struct mode_format) + - sizeof (struct mode_geometry); - } - break; - - default: - /* unsupported pages */ - unsupport_page = 1; - } - - /* allocate buffer to fill the send data */ - sdata_size += pages_size; - sense_data = kmem_zalloc(sdata_size, KM_SLEEP); - - if (cdbp->scc_cmd == SCMD_MODE_SENSE) { - headerp = (struct mode_header *)sense_data; - headerp->length = MODE_HEADER_LENGTH + pages_size - - sizeof (headerp->length); - headerp->bdesc_length = 0; - next_page = sense_data + sizeof (struct mode_header); - } else { - g1_headerp = (void *)sense_data; - g1_headerp->length = BE_16(MODE_HEADER_LENGTH_G1 + pages_size - - sizeof (g1_headerp->length)); - g1_headerp->bdesc_length = 0; - next_page = sense_data + sizeof (struct mode_header_g1); - } - - if (unsupport_page) - goto finish; - - if (pagecode == SD_MODE_SENSE_PAGE3_CODE || - pagecode == MODEPAGE_ALLPAGES) { /* SBC-3 7.1.3.3 Format device page */ ! struct mode_format *page3p; ! ! page3p = (void *)next_page; page3p->mode_page.code = SD_MODE_SENSE_PAGE3_CODE; page3p->mode_page.length = sizeof (struct mode_format); page3p->data_bytes_sect = BE_16(AAC_SECTOR_SIZE); page3p->sect_track = BE_16(AAC_SECTORS_PER_TRACK); - next_page += sizeof (struct mode_format); - } - - if (pagecode == SD_MODE_SENSE_PAGE4_CODE || - pagecode == MODEPAGE_ALLPAGES) { /* SBC-3 7.1.3.8 Rigid disk device geometry page */ ! struct mode_geometry *page4p; ! ! page4p = (void *)next_page; page4p->mode_page.code = SD_MODE_SENSE_PAGE4_CODE; page4p->mode_page.length = sizeof (struct mode_geometry); page4p->heads = AAC_NUMBER_OF_HEADS; page4p->rpm = BE_16(AAC_ROTATION_SPEED); ncyl = capacity / (AAC_NUMBER_OF_HEADS * AAC_SECTORS_PER_TRACK); page4p->cyl_lb = ncyl & 0xff; page4p->cyl_mb = (ncyl >> 8) & 0xff; page4p->cyl_ub = (ncyl >> 16) & 0xff; ! next_page += sizeof (struct mode_geometry); ! } ! ! if ((pagecode == MODEPAGE_CTRL_MODE || pagecode == MODEPAGE_ALLPAGES) && ! softs->flags & AAC_FLAGS_LBA_64BIT) { ! /* 64-bit LBA need large sense data */ struct mode_control_scsi3 *mctl; ! mctl = (void *)next_page; mctl->mode_page.code = MODEPAGE_CTRL_MODE; mctl->mode_page.length = sizeof (struct mode_control_scsi3) - sizeof (struct mode_page); mctl->d_sense = 1; } ! finish: ! /* copyout the valid data. */ ! bcopy(sense_data, bp->b_un.b_addr, min(sdata_size, bp->b_bcount)); ! kmem_free(sense_data, sdata_size); } static int aac_name_node(dev_info_t *dip, char *name, int len) { --- 3776,3890 ---- static void aac_mode_sense(struct aac_softstate *softs, struct scsi_pkt *pkt, union scsi_cdb *cdbp, struct buf *bp, int capacity) { uchar_t pagecode; + struct mode_format *page3p; + struct mode_geometry *page4p; struct mode_header *headerp; unsigned int ncyl; ! union { ! struct mode_header header; ! struct { ! uchar_t header[MODE_HEADER_LENGTH + MODE_BLK_DESC_LENGTH]; ! struct mode_format page; ! } page3; ! struct { ! uchar_t header[MODE_HEADER_LENGTH + MODE_BLK_DESC_LENGTH]; ! struct mode_geometry page; ! } page4; ! struct { ! uchar_t header[MODE_HEADER_LENGTH + MODE_BLK_DESC_LENGTH]; ! struct mode_control_scsi3 page; ! } pageA; ! } mode; if (!(bp && bp->b_un.b_addr && bp->b_bcount)) return; if (bp->b_flags & (B_PHYS | B_PAGEIO)) bp_mapin(bp); pkt->pkt_state |= STATE_XFERRED_DATA; ! bzero(&mode, sizeof(mode)); ! bzero(bp->b_un.b_addr, bp->b_bcount); ! pagecode = cdbp->cdb_un.sg.scsi[0]; ! headerp = &mode.header; switch (pagecode) { /* SBC-3 7.1.3.3 Format device page */ ! case SD_MODE_SENSE_PAGE3_CODE: ! headerp->bdesc_length = MODE_BLK_DESC_LENGTH; ! page3p = &mode.page3.page; page3p->mode_page.code = SD_MODE_SENSE_PAGE3_CODE; page3p->mode_page.length = sizeof (struct mode_format); page3p->data_bytes_sect = BE_16(AAC_SECTOR_SIZE); page3p->sect_track = BE_16(AAC_SECTORS_PER_TRACK); + break; /* SBC-3 7.1.3.8 Rigid disk device geometry page */ ! case SD_MODE_SENSE_PAGE4_CODE: ! headerp->bdesc_length = MODE_BLK_DESC_LENGTH; ! page4p = &mode.page4.page; page4p->mode_page.code = SD_MODE_SENSE_PAGE4_CODE; page4p->mode_page.length = sizeof (struct mode_geometry); page4p->heads = AAC_NUMBER_OF_HEADS; page4p->rpm = BE_16(AAC_ROTATION_SPEED); ncyl = capacity / (AAC_NUMBER_OF_HEADS * AAC_SECTORS_PER_TRACK); page4p->cyl_lb = ncyl & 0xff; page4p->cyl_mb = (ncyl >> 8) & 0xff; page4p->cyl_ub = (ncyl >> 16) & 0xff; + break; ! case MODEPAGE_CTRL_MODE: /* 64-bit LBA need large sense data */ ! if (softs->flags & AAC_FLAGS_LBA_64BIT) { struct mode_control_scsi3 *mctl; ! headerp->bdesc_length = MODE_BLK_DESC_LENGTH; ! mctl = &mode.pageA.page; mctl->mode_page.code = MODEPAGE_CTRL_MODE; mctl->mode_page.length = sizeof (struct mode_control_scsi3) - sizeof (struct mode_page); mctl->d_sense = 1; } + break; + } + bcopy(&mode, bp->b_un.b_addr, + (bp->b_bcount < sizeof(mode)) ? bp->b_bcount : sizeof(mode)); + } ! /* ! * Start/Stop unit (Power Management) ! */ ! static void ! aac_startstop(struct aac_softstate *softs, union scsi_cdb *cdbp, uint32_t cid) ! { ! ddi_acc_handle_t acc = softs->sync_slot->fib_acc_handle; ! struct aac_fib *fibp = softs->sync_slot->fibp; ! struct aac_Container *cmd; ! struct aac_Container_resp *resp; ! uint32_t resp_status; ! int rval; ! ! /* Get adapter config status */ ! cmd = (struct aac_Container *)&fibp->data[0]; ! ! bzero(cmd, sizeof (*cmd) - CT_PACKET_SIZE); ! ddi_put32(acc, &cmd->Command, VM_ContainerConfig); ! ddi_put32(acc, &cmd->CTCommand.command, CT_PM_DRIVER_SUPPORT); ! ddi_put32(acc, &cmd->CTCommand.param[0], cdbp->cdb_opaque[4] & 1 ? ! AAC_PM_DRIVERSUP_START_UNIT : AAC_PM_DRIVERSUP_STOP_UNIT); ! ddi_put32(acc, &cmd->CTCommand.param[1], cid); ! ddi_put32(acc, &cmd->CTCommand.param[2], cdbp->cdb_opaque[1] & 1); ! ! rval = aac_sync_fib(softs, ContainerCommand, ! AAC_FIB_SIZEOF(struct aac_Container)); ! ! resp = (struct aac_Container_resp *)cmd; ! resp_status = ddi_get32(acc, &resp->Status); ! if (rval != AACOK || resp_status != 0) ! AACDB_PRINT(softs, CE_WARN, "Cannot start/stop a unit"); } static int aac_name_node(dev_info_t *dip, char *name, int len) {
*** 4144,4191 **** static int aac_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, scsi_hba_tran_t *tran, struct scsi_device *sd) { struct aac_softstate *softs = AAC_TRAN2SOFTS(tran); ! #if defined(DEBUG) || defined(__lock_lint) int ctl = ddi_get_instance(softs->devinfo_p); #endif ! uint16_t tgt = sd->sd_address.a_target; ! uint8_t lun = sd->sd_address.a_lun; struct aac_device *dvp; DBCALLED(softs, 2); if (ndi_dev_is_persistent_node(tgt_dip) == 0) { ! /* ! * If no persistent node exist, we don't allow .conf node ! * to be created. ! */ ! if (aac_find_child(softs, tgt, lun) != NULL) { ! if (ndi_merge_node(tgt_dip, aac_name_node) != ! DDI_SUCCESS) ! /* Create this .conf node */ ! return (DDI_SUCCESS); ! } return (DDI_FAILURE); } /* * Only support container/phys. device that has been * detected and valid */ mutex_enter(&softs->io_lock); ! if (tgt >= AAC_MAX_DEV(softs)) { AACDB_PRINT_TRAN(softs, "aac_tran_tgt_init: c%dt%dL%d out", ctl, tgt, lun); mutex_exit(&softs->io_lock); return (DDI_FAILURE); } if (tgt < AAC_MAX_LD) { ! dvp = (struct aac_device *)&softs->containers[tgt]; ! if (lun != 0 || !AAC_DEV_IS_VALID(dvp)) { AACDB_PRINT_TRAN(softs, "aac_tran_tgt_init: c%dt%dL%d", ctl, tgt, lun); mutex_exit(&softs->io_lock); return (DDI_FAILURE); } --- 3907,3946 ---- static int aac_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, scsi_hba_tran_t *tran, struct scsi_device *sd) { struct aac_softstate *softs = AAC_TRAN2SOFTS(tran); ! #if defined(AAC_DEBUG) || defined(__lock_lint) int ctl = ddi_get_instance(softs->devinfo_p); #endif ! int tgt = sd->sd_address.a_target; ! int lun = sd->sd_address.a_lun; struct aac_device *dvp; DBCALLED(softs, 2); if (ndi_dev_is_persistent_node(tgt_dip) == 0) { ! (void) ndi_merge_node(tgt_dip, aac_name_node); ! ddi_set_name_addr(tgt_dip, NULL); return (DDI_FAILURE); } /* * Only support container/phys. device that has been * detected and valid */ mutex_enter(&softs->io_lock); ! if (tgt < 0 || tgt >= AAC_MAX_DEV(softs)) { AACDB_PRINT_TRAN(softs, "aac_tran_tgt_init: c%dt%dL%d out", ctl, tgt, lun); mutex_exit(&softs->io_lock); return (DDI_FAILURE); } + dvp = AAC_DEV(softs, tgt); if (tgt < AAC_MAX_LD) { ! if (dvp == NULL || !(dvp->valid) || lun != 0) { AACDB_PRINT_TRAN(softs, "aac_tran_tgt_init: c%dt%dL%d", ctl, tgt, lun); mutex_exit(&softs->io_lock); return (DDI_FAILURE); }
*** 4195,4225 **** * tgt_free. */ if (softs->containers[tgt].dev.dip == NULL && strcmp(ddi_driver_name(sd->sd_dev), "sd") == 0) softs->containers[tgt].dev.dip = tgt_dip; - } else { - dvp = (struct aac_device *)&softs->nondasds[AAC_PD(tgt)]; - /* - * Save the tgt_dip for the given target if one doesn't exist - * already. Dip's for non-existance tgt's will be cleared in - * tgt_free. - */ - - if (softs->nondasds[AAC_PD(tgt)].dev.dip == NULL && - strcmp(ddi_driver_name(sd->sd_dev), "sd") == 0) - softs->nondasds[AAC_PD(tgt)].dev.dip = tgt_dip; } - if (softs->flags & AAC_FLAGS_BRKUP) { - if (ndi_prop_update_int(DDI_DEV_T_NONE, tgt_dip, - "buf_break", 1) != DDI_PROP_SUCCESS) { - cmn_err(CE_CONT, "unable to create " - "property for t%dL%d (buf_break)", tgt, lun); - } - } - AACDB_PRINT(softs, CE_NOTE, "aac_tran_tgt_init: c%dt%dL%d ok (%s)", ctl, tgt, lun, (dvp->type == AAC_DEV_PD) ? "pd" : "ld"); mutex_exit(&softs->io_lock); return (DDI_SUCCESS); --- 3950,3961 ----
*** 4235,4252 **** struct aac_softstate *softs = SD2AAC(sd); int tgt = sd->sd_address.a_target; mutex_enter(&softs->io_lock); ! if (tgt < AAC_MAX_LD) { ! if (softs->containers[tgt].dev.dip == tgt_dip) softs->containers[tgt].dev.dip = NULL; ! } else { ! if (softs->nondasds[AAC_PD(tgt)].dev.dip == tgt_dip) ! softs->nondasds[AAC_PD(tgt)].dev.dip = NULL; ! softs->nondasds[AAC_PD(tgt)].dev.flags &= ~AAC_DFLAG_VALID; ! } mutex_exit(&softs->io_lock); } /* * Check if the firmware is Up And Running. If it is in the Kernel Panic --- 3971,3984 ---- struct aac_softstate *softs = SD2AAC(sd); int tgt = sd->sd_address.a_target; mutex_enter(&softs->io_lock); ! if (tgt < AAC_MAX_LD) softs->containers[tgt].dev.dip = NULL; ! else ! softs->nondasds[AAC_PD(tgt)].dev.valid = 0; mutex_exit(&softs->io_lock); } /* * Check if the firmware is Up And Running. If it is in the Kernel Panic
*** 4258,4277 **** static int aac_check_adapter_health(struct aac_softstate *softs) { int rval; ! rval = PCI_MEM_GET32(softs, AAC_OMR0); if (rval & AAC_KERNEL_UP_AND_RUNNING) { rval = 0; } else if (rval & AAC_KERNEL_PANIC) { - cmn_err(CE_WARN, "firmware panic"); rval = ((rval >> 16) & 0xff) + 1; /* avoid 0 as return value */ } else { - cmn_err(CE_WARN, "firmware dead"); rval = -1; } return (rval); } static void --- 3990,4009 ---- static int aac_check_adapter_health(struct aac_softstate *softs) { int rval; ! rval = AAC_FWSTATUS_GET(softs); if (rval & AAC_KERNEL_UP_AND_RUNNING) { rval = 0; } else if (rval & AAC_KERNEL_PANIC) { rval = ((rval >> 16) & 0xff) + 1; /* avoid 0 as return value */ + cmn_err(CE_WARN, "!Adapter firmware crashed with BLED %d", rval - 1); } else { rval = -1; + cmn_err(CE_WARN, "!Adapter firmware dead"); } return (rval); } static void
*** 4279,4308 **** uchar_t reason) { acp->flags |= AAC_CMD_ABORT; if (acp->pkt) { ! if (acp->slotp) { /* outstanding cmd */ ! acp->pkt->pkt_state |= STATE_GOT_STATUS; ! } switch (reason) { case CMD_TIMEOUT: - AACDB_PRINT(softs, CE_NOTE, "CMD_TIMEOUT: acp=0x%p", - acp); aac_set_pkt_reason(softs, acp, CMD_TIMEOUT, STAT_TIMEOUT | STAT_BUS_RESET); break; case CMD_RESET: /* aac support only RESET_ALL */ - AACDB_PRINT(softs, CE_NOTE, "CMD_RESET: acp=0x%p", acp); aac_set_pkt_reason(softs, acp, CMD_RESET, STAT_BUS_RESET); break; case CMD_ABORTED: - AACDB_PRINT(softs, CE_NOTE, "CMD_ABORTED: acp=0x%p", - acp); aac_set_pkt_reason(softs, acp, CMD_ABORTED, STAT_ABORTED); break; } } --- 4011,4040 ---- uchar_t reason) { acp->flags |= AAC_CMD_ABORT; if (acp->pkt) { ! /* ! * Each lun should generate a unit attention ! * condition when reset. ! * Phys. drives are treated as logical ones ! * during error recovery. ! */ ! if (softs->flags & AAC_STATE_RESET) ! aac_set_arq_data_reset(softs, acp); switch (reason) { case CMD_TIMEOUT: aac_set_pkt_reason(softs, acp, CMD_TIMEOUT, STAT_TIMEOUT | STAT_BUS_RESET); break; case CMD_RESET: /* aac support only RESET_ALL */ aac_set_pkt_reason(softs, acp, CMD_RESET, STAT_BUS_RESET); break; case CMD_ABORTED: aac_set_pkt_reason(softs, acp, CMD_ABORTED, STAT_ABORTED); break; } }
*** 4335,4345 **** */ if (iocmd & AAC_IOCMD_OUTSTANDING) { struct aac_cmd *acp; for (i = 0; i < AAC_MAX_LD; i++) { ! if (AAC_DEV_IS_VALID(&softs->containers[i].dev)) softs->containers[i].reset = 1; } while ((acp = softs->q_busy.q_head) != NULL) aac_abort_iocmd(softs, acp, reason); } --- 4067,4077 ---- */ if (iocmd & AAC_IOCMD_OUTSTANDING) { struct aac_cmd *acp; for (i = 0; i < AAC_MAX_LD; i++) { ! if (softs->containers[i].dev.valid) softs->containers[i].reset = 1; } while ((acp = softs->q_busy.q_head) != NULL) aac_abort_iocmd(softs, acp, reason); }
*** 4366,4376 **** { struct aac_softstate *softs = arg; mutex_enter(&softs->io_lock); if (softs->ndrains) { - softs->drain_timeid = 0; /* * If both ASYNC and SYNC bus throttle are held, * wake up threads only when both are drained out. */ if ((softs->bus_throttle[AAC_CMDQ_ASYNC] > 0 || --- 4098,4107 ----
*** 4391,4401 **** */ static void aac_start_drain(struct aac_softstate *softs) { if (softs->ndrains == 0) { - ASSERT(softs->drain_timeid == 0); softs->drain_timeid = timeout(aac_check_drain, softs, AAC_QUIESCE_TICK * drv_usectohz(1000000)); } softs->ndrains++; } --- 4122,4131 ----
*** 4430,4478 **** * from multiple places. */ static int aac_reset_adapter(struct aac_softstate *softs) { int health; ! uint32_t status; ! int rval = AAC_IOP_RESET_FAILED; DBCALLED(softs, 1); - ASSERT(softs->state & AAC_STATE_RESET); ! ddi_fm_acc_err_clear(softs->pci_mem_handle, DDI_FME_VER0); /* Disable interrupt */ ! AAC_DISABLE_INTR(softs); health = aac_check_adapter_health(softs); if (health == -1) { ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); goto finish; } if (health == 0) /* flush drives if possible */ (void) aac_shutdown(softs); /* Execute IOP reset */ ! if ((aac_sync_mbcommand(softs, AAC_IOP_RESET, 0, 0, 0, 0, ! &status)) != AACOK) { ! ddi_acc_handle_t acc; ! struct aac_fib *fibp; ! struct aac_pause_command *pc; ! ! if ((status & 0xf) == 0xf) { ! uint32_t wait_count; ! /* * Sunrise Lake has dual cores and we must drag the * other core with us to reset simultaneously. There * are 2 bits in the Inbound Reset Control and Status * Register (offset 0x38) of the Sunrise Lake to reset * the chip without clearing out the PCI configuration * info (COMMAND & BARS). */ ! PCI_MEM_PUT32(softs, AAC_IRCSR, AAC_IRCSR_CORES_RST); /* * We need to wait for 5 seconds before accessing the MU * again 10000 * 100us = 1000,000us = 1000ms = 1s */ --- 4160,4204 ---- * from multiple places. */ static int aac_reset_adapter(struct aac_softstate *softs) { + ddi_acc_handle_t acc = softs->comm_space_acc_handle; int health; ! uint32_t status, wait_count, reset_mask; ! struct aac_fib *fibp; ! struct aac_pause_command *pc; ! int rval = AACERR; DBCALLED(softs, 1); ASSERT(softs->state & AAC_STATE_RESET); ! aac_fm_acc_err_clear(softs->pci_mem_handle[0], DDI_FME_VER0); /* Disable interrupt */ ! AAC_SET_INTR(softs, 0); health = aac_check_adapter_health(softs); + AACDB_PRINT(softs, CE_NOTE, + "aac_reset_adapter() called, health %d", health); if (health == -1) { ! aac_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); goto finish; } if (health == 0) /* flush drives if possible */ (void) aac_shutdown(softs); /* Execute IOP reset */ ! if (softs->aac_support_opt2 & AAC_SUPPORTED_MU_RESET) { /* * Sunrise Lake has dual cores and we must drag the * other core with us to reset simultaneously. There * are 2 bits in the Inbound Reset Control and Status * Register (offset 0x38) of the Sunrise Lake to reset * the chip without clearing out the PCI configuration * info (COMMAND & BARS). */ ! PCI_MEM_PUT32(softs, 0, AAC_IRCSR, AAC_IRCSR_CORES_RST); /* * We need to wait for 5 seconds before accessing the MU * again 10000 * 100us = 1000,000us = 1000ms = 1s */
*** 4480,4499 **** while (wait_count) { drv_usecwait(100); /* delay 100 microseconds */ wait_count--; } } else { ! if (status == SRB_STATUS_INVALID_REQUEST) cmn_err(CE_WARN, "!IOP_RESET not supported"); ! else /* probably timeout */ cmn_err(CE_WARN, "!IOP_RESET failed"); ! /* Unwind aac_shutdown() */ ! (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac); ! acc = softs->sync_ac.slotp->fib_acc_handle; ! ! fibp = softs->sync_ac.slotp->fibp; pc = (struct aac_pause_command *)&fibp->data[0]; bzero(pc, sizeof (*pc)); ddi_put32(acc, &pc->Command, VM_ContainerConfig); ddi_put32(acc, &pc->Type, CT_PAUSE_IO); --- 4206,4229 ---- while (wait_count) { drv_usecwait(100); /* delay 100 microseconds */ wait_count--; } } else { ! softs->sync_slot_busy = 1; ! if ((aac_sync_mbcommand(softs, AAC_IOP_RESET_ALWAYS, 0, 0, 0, 0, ! &status, &reset_mask)) != AACOK) { ! if (status == SRB_STATUS_INVALID_REQUEST) { cmn_err(CE_WARN, "!IOP_RESET not supported"); ! AACDB_PRINT(softs, CE_NOTE, ! "IOP_RESET not supported"); ! } else { /* probably timeout */ cmn_err(CE_WARN, "!IOP_RESET failed"); ! AACDB_PRINT(softs, CE_NOTE, ! "IOP_RESET failed"); ! } /* Unwind aac_shutdown() */ ! fibp = softs->sync_slot->fibp; pc = (struct aac_pause_command *)&fibp->data[0]; bzero(pc, sizeof (*pc)); ddi_put32(acc, &pc->Command, VM_ContainerConfig); ddi_put32(acc, &pc->Type, CT_PAUSE_IO);
*** 4501,4536 **** ddi_put32(acc, &pc->Min, 1); ddi_put32(acc, &pc->NoRescan, 1); (void) aac_sync_fib(softs, ContainerCommand, AAC_FIB_SIZEOF(struct aac_pause_command)); - aac_sync_fib_slot_release(softs, &softs->sync_ac); ! if (aac_check_adapter_health(softs) != 0) ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); ! else /* ! * IOP reset not supported or IOP not reseted */ ! rval = AAC_IOP_RESET_ABNORMAL; ! goto finish; } } /* * Re-read and renegotiate the FIB parameters, as one of the actions * that can result from an IOP reset is the running of a new firmware * image. */ if (aac_common_attach(softs) != AACOK) goto finish; ! rval = AAC_IOP_RESET_SUCCEED; finish: ! AAC_ENABLE_INTR(softs); return (rval); } static void aac_set_throttle(struct aac_softstate *softs, struct aac_device *dvp, int q, --- 4231,4274 ---- ddi_put32(acc, &pc->Min, 1); ddi_put32(acc, &pc->NoRescan, 1); (void) aac_sync_fib(softs, ContainerCommand, AAC_FIB_SIZEOF(struct aac_pause_command)); ! aac_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); ! if (health == 0) ! rval = AACOK2; ! goto finish; ! } else if (softs->aac_support_opt2 & AAC_SUPPORTED_DOORBELL_RESET) { ! PCI_MEM_PUT32(softs, 0, AAC_SRC_IDBR, reset_mask); /* ! * We need to wait for 5 seconds before accessing the doorbell ! * again 10000 * 100us = 1000,000us = 1000ms = 1s */ ! wait_count = 5 * 10000; ! while (wait_count) { ! drv_usecwait(100); /* delay 100 microseconds */ ! wait_count--; } } + } + cmn_err(CE_NOTE, "!IOP_RESET finished successfully"); + AACDB_PRINT(softs, CE_NOTE, "IOP_RESET finished successfully"); /* * Re-read and renegotiate the FIB parameters, as one of the actions * that can result from an IOP reset is the running of a new firmware * image. */ if (aac_common_attach(softs) != AACOK) goto finish; ! rval = AACOK; finish: ! AAC_SET_INTR(softs, 1); return (rval); } static void aac_set_throttle(struct aac_softstate *softs, struct aac_device *dvp, int q,
*** 4565,4575 **** } static void aac_unhold_bus(struct aac_softstate *softs, int iocmds) { ! int i, q, max_throttle; for (q = 0; q < AAC_CMDQ_NUM; q++) { if (iocmds & (1 << q)) { /* * Should not unhold AAC_IOCMD_ASYNC bus, if it has been --- 4303,4313 ---- } static void aac_unhold_bus(struct aac_softstate *softs, int iocmds) { ! int i, q; for (q = 0; q < AAC_CMDQ_NUM; q++) { if (iocmds & (1 << q)) { /* * Should not unhold AAC_IOCMD_ASYNC bus, if it has been
*** 4577,4624 **** * threads. */ if (q == AAC_CMDQ_ASYNC && ((softs->state & AAC_STATE_QUIESCED) || softs->ndrains)) continue; ! if (q == AAC_CMDQ_ASYNC) ! max_throttle = softs->total_slots - ! AAC_MGT_SLOT_NUM; ! else ! max_throttle = softs->total_slots - 1; ! softs->bus_throttle[q] = max_throttle; for (i = 0; i < AAC_MAX_LD; i++) aac_set_throttle(softs, &softs->containers[i].dev, ! q, max_throttle); for (i = 0; i < AAC_MAX_PD(softs); i++) aac_set_throttle(softs, &softs->nondasds[i].dev, ! q, max_throttle); } } } static int aac_do_reset(struct aac_softstate *softs) { ! int health; ! int rval; softs->state |= AAC_STATE_RESET; health = aac_check_adapter_health(softs); /* * Hold off new io commands and wait all outstanding io * commands to complete. */ ! if (health == 0) { ! int sync_cmds = softs->bus_ncmds[AAC_CMDQ_SYNC]; ! int async_cmds = softs->bus_ncmds[AAC_CMDQ_ASYNC]; ! ! if (sync_cmds == 0 && async_cmds == 0) { ! rval = AAC_IOP_RESET_SUCCEED; ! goto finish; ! } /* * Give the adapter up to AAC_QUIESCE_TIMEOUT more seconds * to complete the outstanding io commands */ int timeout = AAC_QUIESCE_TIMEOUT * 1000 * 10; --- 4315,4353 ---- * threads. */ if (q == AAC_CMDQ_ASYNC && ((softs->state & AAC_STATE_QUIESCED) || softs->ndrains)) continue; ! softs->bus_throttle[q] = softs->total_slots; for (i = 0; i < AAC_MAX_LD; i++) aac_set_throttle(softs, &softs->containers[i].dev, ! q, softs->total_slots); for (i = 0; i < AAC_MAX_PD(softs); i++) aac_set_throttle(softs, &softs->nondasds[i].dev, ! q, softs->total_slots); } } } static int aac_do_reset(struct aac_softstate *softs) { ! int health, rval; ! int sync_cmds, async_cmds; softs->state |= AAC_STATE_RESET; health = aac_check_adapter_health(softs); + AACDB_PRINT(softs, CE_NOTE, "aac_do_reset() called, health %d", health); /* * Hold off new io commands and wait all outstanding io * commands to complete. */ ! sync_cmds = softs->bus_ncmds[AAC_CMDQ_SYNC]; ! async_cmds = softs->bus_ncmds[AAC_CMDQ_ASYNC]; ! if (health == 0 && (sync_cmds || async_cmds)) { /* * Give the adapter up to AAC_QUIESCE_TIMEOUT more seconds * to complete the outstanding io commands */ int timeout = AAC_QUIESCE_TIMEOUT * 1000 * 10;
*** 4627,4710 **** aac_hold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC); /* * Poll the adapter by ourselves in case interrupt is disabled * and to avoid releasing the io_lock. */ ! intr_handler = (softs->flags & AAC_FLAGS_NEW_COMM) ? ! aac_process_intr_new : aac_process_intr_old; while ((softs->bus_ncmds[AAC_CMDQ_SYNC] || softs->bus_ncmds[AAC_CMDQ_ASYNC]) && timeout) { drv_usecwait(100); (void) intr_handler(softs); timeout--; } aac_unhold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC); - - if (softs->bus_ncmds[AAC_CMDQ_SYNC] == 0 && - softs->bus_ncmds[AAC_CMDQ_ASYNC] == 0) { - /* Cmds drained out */ - rval = AAC_IOP_RESET_SUCCEED; - goto finish; - } else if (softs->bus_ncmds[AAC_CMDQ_SYNC] < sync_cmds || - softs->bus_ncmds[AAC_CMDQ_ASYNC] < async_cmds) { - /* Cmds not drained out, adapter overloaded */ - rval = AAC_IOP_RESET_ABNORMAL; - goto finish; } - } /* ! * If a longer waiting time still can't drain any outstanding io * commands, do IOP reset. */ ! if ((rval = aac_reset_adapter(softs)) == AAC_IOP_RESET_FAILED) softs->state |= AAC_STATE_DEAD; - finish: softs->state &= ~AAC_STATE_RESET; return (rval); } static int aac_tran_reset(struct scsi_address *ap, int level) { struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran); ! int rval; DBCALLED(softs, 1); if (level != RESET_ALL) { cmn_err(CE_NOTE, "!reset target/lun not supported"); return (0); } mutex_enter(&softs->io_lock); ! switch (rval = aac_do_reset(softs)) { ! case AAC_IOP_RESET_SUCCEED: aac_abort_iocmds(softs, AAC_IOCMD_OUTSTANDING | AAC_IOCMD_ASYNC, NULL, CMD_RESET); aac_start_waiting_io(softs); ! break; ! case AAC_IOP_RESET_FAILED: ! /* Abort IOCTL cmds when adapter is dead */ aac_abort_iocmds(softs, AAC_IOCMD_ALL, NULL, CMD_RESET); - break; - case AAC_IOP_RESET_ABNORMAL: - aac_start_waiting_io(softs); } mutex_exit(&softs->io_lock); aac_drain_comp_q(softs); ! return (rval == 0); } static int aac_tran_abort(struct scsi_address *ap, struct scsi_pkt *pkt) { struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran); DBCALLED(softs, 1); mutex_enter(&softs->io_lock); aac_abort_iocmds(softs, 0, pkt, CMD_ABORTED); mutex_exit(&softs->io_lock); --- 4356,4438 ---- aac_hold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC); /* * Poll the adapter by ourselves in case interrupt is disabled * and to avoid releasing the io_lock. */ ! if ((softs->flags & AAC_FLAGS_NEW_COMM_TYPE1) || ! (softs->flags & AAC_FLAGS_NEW_COMM_TYPE2) || ! (softs->flags & AAC_FLAGS_NEW_COMM_TYPE34)) ! intr_handler = aac_process_intr_new_type1; ! else if (softs->flags & AAC_FLAGS_NEW_COMM) ! intr_handler = aac_process_intr_new; ! else ! intr_handler = aac_process_intr_old; while ((softs->bus_ncmds[AAC_CMDQ_SYNC] || softs->bus_ncmds[AAC_CMDQ_ASYNC]) && timeout) { drv_usecwait(100); (void) intr_handler(softs); timeout--; } aac_unhold_bus(softs, AAC_IOCMD_SYNC | AAC_IOCMD_ASYNC); } /* ! * If a longer waiting time still can't drain all outstanding io * commands, do IOP reset. */ ! if ((sync_cmds || async_cmds) && ! (softs->bus_ncmds[AAC_CMDQ_SYNC] == sync_cmds) && ! (softs->bus_ncmds[AAC_CMDQ_ASYNC] == async_cmds)) { ! if ((rval = aac_reset_adapter(softs)) == AACERR) softs->state |= AAC_STATE_DEAD; + } else { + rval = AACOK2; + } softs->state &= ~AAC_STATE_RESET; return (rval); } static int aac_tran_reset(struct scsi_address *ap, int level) { struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran); ! int rval, rval2; DBCALLED(softs, 1); + AACDB_PRINT(softs, CE_NOTE, "aac_tran_reset() called, level %d", level); if (level != RESET_ALL) { cmn_err(CE_NOTE, "!reset target/lun not supported"); return (0); } mutex_enter(&softs->io_lock); ! rval2 = aac_do_reset(softs); ! rval = (rval2 != AACERR) ? 1 : 0; ! if (rval == 1 && !ddi_in_panic()) { ! if (rval2 == AACOK) aac_abort_iocmds(softs, AAC_IOCMD_OUTSTANDING | AAC_IOCMD_ASYNC, NULL, CMD_RESET); aac_start_waiting_io(softs); ! } else { ! /* Abort IOCTL cmds when system panic or adapter dead */ aac_abort_iocmds(softs, AAC_IOCMD_ALL, NULL, CMD_RESET); } mutex_exit(&softs->io_lock); aac_drain_comp_q(softs); ! return (rval); } static int aac_tran_abort(struct scsi_address *ap, struct scsi_pkt *pkt) { struct aac_softstate *softs = AAC_TRAN2SOFTS(ap->a_hba_tran); DBCALLED(softs, 1); + AACDB_PRINT(softs, CE_NOTE, "aac_tran_abort() called, pkt %p", pkt); mutex_enter(&softs->io_lock); aac_abort_iocmds(softs, 0, pkt, CMD_ABORTED); mutex_exit(&softs->io_lock);
*** 4713,4750 **** } void aac_free_dmamap(struct aac_cmd *acp) { /* Free dma mapping */ if (acp->flags & AAC_CMD_DMA_VALID) { ! ASSERT(acp->buf_dma_handle); ! (void) ddi_dma_unbind_handle(acp->buf_dma_handle); acp->flags &= ~AAC_CMD_DMA_VALID; } ! if (acp->abp != NULL) { /* free non-aligned buf DMA */ ! ASSERT(acp->buf_dma_handle); if ((acp->flags & AAC_CMD_BUF_WRITE) == 0 && acp->bp) ! ddi_rep_get8(acp->abh, (uint8_t *)acp->bp->b_un.b_addr, ! (uint8_t *)acp->abp, acp->bp->b_bcount, DDI_DEV_AUTOINCR); ! ddi_dma_mem_free(&acp->abh); ! acp->abp = NULL; } ! if (acp->buf_dma_handle) { ! ddi_dma_free_handle(&acp->buf_dma_handle); ! acp->buf_dma_handle = NULL; } } static void aac_unknown_scmd(struct aac_softstate *softs, struct aac_cmd *acp) { AACDB_PRINT(softs, CE_CONT, "SCMD 0x%x not supported", ! ((union scsi_cdb *)(void *)acp->pkt->pkt_cdbp)->scc_cmd); aac_free_dmamap(acp); aac_set_arq_data(acp->pkt, KEY_ILLEGAL_REQUEST, 0x20, 0x00, 0); aac_soft_callback(softs, acp); } --- 4441,4489 ---- } void aac_free_dmamap(struct aac_cmd *acp) { + uint_t i; + uint32_t offset; + /* Free dma mapping */ if (acp->flags & AAC_CMD_DMA_VALID) { ! ASSERT(acp->segments[0].buf_dma_handle); ! for (i = 0; i < acp->segment_cnt; ++i) ! (void) ddi_dma_unbind_handle(acp->segments[i].buf_dma_handle); acp->flags &= ~AAC_CMD_DMA_VALID; } ! if (acp->segments[0].abp != NULL) { /* free non-aligned buf DMA */ ! ASSERT(acp->segments[0].buf_dma_handle); ! for (i = 0, offset = 0; i < acp->segment_cnt; ++i) { if ((acp->flags & AAC_CMD_BUF_WRITE) == 0 && acp->bp) ! ddi_rep_get8(acp->segments[i].abh, ! (uint8_t *)acp->bp->b_un.b_addr + offset, ! (uint8_t *)acp->segments[i].abp, ! acp->segments[i].abp_size, DDI_DEV_AUTOINCR); ! offset += acp->segments[i].abp_size; ! ddi_dma_mem_free(&acp->segments[i].abh); ! acp->segments[i].abp = NULL; } + } ! for (i = 0; i < acp->segment_cnt; ++i) { ! if (acp->segments[i].buf_dma_handle) { ! ddi_dma_free_handle(&acp->segments[i].buf_dma_handle); ! acp->segments[i].buf_dma_handle = NULL; } + } } static void aac_unknown_scmd(struct aac_softstate *softs, struct aac_cmd *acp) { AACDB_PRINT(softs, CE_CONT, "SCMD 0x%x not supported", ! ((union scsi_cdb *)acp->pkt->pkt_cdbp)->scc_cmd); aac_free_dmamap(acp); aac_set_arq_data(acp->pkt, KEY_ILLEGAL_REQUEST, 0x20, 0x00, 0); aac_soft_callback(softs, acp); }
*** 4760,4770 **** struct buf *bp; int rval; dvp = (struct aac_container *)acp->dvp; pkt = acp->pkt; ! cdbp = (void *)pkt->pkt_cdbp; bp = acp->bp; switch (cdbp->scc_cmd) { case SCMD_INQUIRY: /* inquiry */ aac_free_dmamap(acp); --- 4499,4509 ---- struct buf *bp; int rval; dvp = (struct aac_container *)acp->dvp; pkt = acp->pkt; ! cdbp = (union scsi_cdb *)pkt->pkt_cdbp; bp = acp->bp; switch (cdbp->scc_cmd) { case SCMD_INQUIRY: /* inquiry */ aac_free_dmamap(acp);
*** 4788,4798 **** cap.lbasize = BE_32(AAC_SECTOR_SIZE); aac_free_dmamap(acp); if (bp->b_flags & (B_PHYS|B_PAGEIO)) bp_mapin(bp); ! bcopy(&cap, bp->b_un.b_addr, min(bp->b_bcount, 8)); pkt->pkt_state |= STATE_XFERRED_DATA; } aac_soft_callback(softs, acp); rval = TRAN_ACCEPT; break; --- 4527,4538 ---- cap.lbasize = BE_32(AAC_SECTOR_SIZE); aac_free_dmamap(acp); if (bp->b_flags & (B_PHYS|B_PAGEIO)) bp_mapin(bp); ! bcopy(&cap, bp->b_un.b_addr, ! bp->b_bcount < 8 ? bp->b_bcount : 8); pkt->pkt_state |= STATE_XFERRED_DATA; } aac_soft_callback(softs, acp); rval = TRAN_ACCEPT; break;
*** 4803,4820 **** if (bp && bp->b_un.b_addr && bp->b_bcount) { struct scsi_capacity_16 cap16; int cap_len = sizeof (struct scsi_capacity_16); bzero(&cap16, cap_len); ! cap16.sc_capacity = BE_64(dvp->size - 1); cap16.sc_lbasize = BE_32(AAC_SECTOR_SIZE); aac_free_dmamap(acp); if (bp->b_flags & (B_PHYS | B_PAGEIO)) bp_mapin(bp); bcopy(&cap16, bp->b_un.b_addr, ! min(bp->b_bcount, cap_len)); pkt->pkt_state |= STATE_XFERRED_DATA; } aac_soft_callback(softs, acp); } else { aac_unknown_scmd(softs, acp); --- 4543,4560 ---- if (bp && bp->b_un.b_addr && bp->b_bcount) { struct scsi_capacity_16 cap16; int cap_len = sizeof (struct scsi_capacity_16); bzero(&cap16, cap_len); ! cap16.sc_capacity = BE_64(dvp->size); cap16.sc_lbasize = BE_32(AAC_SECTOR_SIZE); aac_free_dmamap(acp); if (bp->b_flags & (B_PHYS | B_PAGEIO)) bp_mapin(bp); bcopy(&cap16, bp->b_un.b_addr, ! bp->b_bcount < cap_len ? bp->b_bcount : cap_len); pkt->pkt_state |= STATE_XFERRED_DATA; } aac_soft_callback(softs, acp); } else { aac_unknown_scmd(softs, acp);
*** 4839,4853 **** case SCMD_READ: /* read_6 */ case SCMD_WRITE: /* write_6 */ acp->blkno = GETG0ADDR(cdbp); goto do_io; - case SCMD_READ_G5: /* read_12 */ - case SCMD_WRITE_G5: /* write_12 */ - acp->blkno = GETG5ADDR(cdbp); - goto do_io; - case SCMD_READ_G1: /* read_10 */ case SCMD_WRITE_G1: /* write_10 */ acp->blkno = (uint32_t)GETG1ADDR(cdbp); do_io: if (acp->flags & AAC_CMD_DMA_VALID) { --- 4579,4588 ----
*** 4897,4914 **** aac_soft_callback(softs, acp); rval = TRAN_ACCEPT; break; } - case SCMD_START_STOP: - if (softs->support_opt2 & AAC_SUPPORTED_POWER_MANAGEMENT) { - acp->aac_cmd_fib = aac_cmd_fib_startstop; - acp->ac_comp = aac_startstop_complete; - rval = aac_do_io(softs, acp); - break; - } - /* FALLTHRU */ case SCMD_TEST_UNIT_READY: case SCMD_REQUEST_SENSE: case SCMD_FORMAT: aac_free_dmamap(acp); if (bp && bp->b_un.b_addr && bp->b_bcount) { --- 4632,4641 ----
*** 4935,4944 **** --- 4662,4679 ---- dvp->locked = (pkt->pkt_cdbp[4] & 0x01) ? 1 : 0; aac_soft_callback(softs, acp); rval = TRAN_ACCEPT; break; + case SCMD_START_STOP: + aac_free_dmamap(acp); + if (softs->aac_support_opt2 & AAC_SUPPORTED_POWER_MANAGEMENT) + aac_startstop(softs, cdbp, dvp->cid); + aac_soft_callback(softs, acp); + rval = TRAN_ACCEPT; + break; + default: /* unknown command */ aac_unknown_scmd(softs, acp); rval = TRAN_ACCEPT; break; }
*** 4963,5021 **** acp->flags &= AAC_CMD_CONSISTENT | AAC_CMD_DMA_PARTIAL | \ AAC_CMD_BUF_READ | AAC_CMD_BUF_WRITE | AAC_CMD_DMA_VALID; acp->timeout = acp->pkt->pkt_time; if (pkt->pkt_flags & FLAG_NOINTR) acp->flags |= AAC_CMD_NO_INTR; ! #ifdef DEBUG ! acp->fib_flags = AACDB_FLAGS_FIB_SCMD; ! #endif pkt->pkt_reason = CMD_CMPLT; pkt->pkt_state = 0; pkt->pkt_statistics = 0; ! *pkt->pkt_scbp = STATUS_GOOD; /* clear arq scsi_status */ if (acp->flags & AAC_CMD_DMA_VALID) { pkt->pkt_resid = acp->bcount; /* Consistent packets need to be sync'ed first */ if ((acp->flags & AAC_CMD_CONSISTENT) && (acp->flags & AAC_CMD_BUF_WRITE)) if (aac_dma_sync_ac(acp) != AACOK) { ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); return (TRAN_BADPKT); } } else { pkt->pkt_resid = 0; } mutex_enter(&softs->io_lock); AACDB_PRINT_SCMD(softs, acp); ! if ((dvp->flags & (AAC_DFLAG_VALID | AAC_DFLAG_CONFIGURING)) && ! !(softs->state & AAC_STATE_DEAD)) { ! if (dvp->type == AAC_DEV_LD) { ! if (ap->a_lun == 0) rval = aac_tran_start_ld(softs, acp); else - goto error; - } else { rval = aac_do_io(softs, acp); - } } else { - error: - #ifdef DEBUG - if (!(softs->state & AAC_STATE_DEAD)) { - AACDB_PRINT_TRAN(softs, - "Cannot send cmd to target t%dL%d: %s", - ap->a_target, ap->a_lun, - "target invalid"); - } else { AACDB_PRINT(softs, CE_WARN, "Cannot send cmd to target t%dL%d: %s", ap->a_target, ap->a_lun, ! "adapter dead"); ! } ! #endif rval = TRAN_FATAL_ERROR; } mutex_exit(&softs->io_lock); return (rval); } --- 4698,4742 ---- acp->flags &= AAC_CMD_CONSISTENT | AAC_CMD_DMA_PARTIAL | \ AAC_CMD_BUF_READ | AAC_CMD_BUF_WRITE | AAC_CMD_DMA_VALID; acp->timeout = acp->pkt->pkt_time; if (pkt->pkt_flags & FLAG_NOINTR) acp->flags |= AAC_CMD_NO_INTR; ! acp->cur_segment = 0; pkt->pkt_reason = CMD_CMPLT; pkt->pkt_state = 0; pkt->pkt_statistics = 0; ! *pkt->pkt_scbp = 0; /* clear arq scsi_status */ if (acp->flags & AAC_CMD_DMA_VALID) { pkt->pkt_resid = acp->bcount; /* Consistent packets need to be sync'ed first */ if ((acp->flags & AAC_CMD_CONSISTENT) && (acp->flags & AAC_CMD_BUF_WRITE)) if (aac_dma_sync_ac(acp) != AACOK) { ! aac_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); return (TRAN_BADPKT); } } else { pkt->pkt_resid = 0; } mutex_enter(&softs->io_lock); AACDB_PRINT_SCMD(softs, acp); ! if (dvp->valid && ap->a_lun == 0 && !(softs->state & AAC_STATE_DEAD)) { ! if (dvp->type == AAC_DEV_LD) rval = aac_tran_start_ld(softs, acp); + else if (acp->segment_cnt > 1) + rval = TRAN_BADPKT; else rval = aac_do_io(softs, acp); } else { AACDB_PRINT(softs, CE_WARN, "Cannot send cmd to target t%dL%d: %s", ap->a_target, ap->a_lun, ! (softs->state & AAC_STATE_DEAD) ? ! "adapter dead" : "target invalid"); rval = TRAN_FATAL_ERROR; } mutex_exit(&softs->io_lock); return (rval); }
*** 5036,5048 **** return (-1); } mutex_enter(&softs->io_lock); dvp = AAC_DEV(softs, ap->a_target); ! if (dvp == NULL || !AAC_DEV_IS_VALID(dvp)) { mutex_exit(&softs->io_lock); ! AACDB_PRINT_TRAN(softs, "Bad target t%dL%d to getcap", ap->a_target, ap->a_lun); return (-1); } switch (scsi_hba_lookup_capstr(cap)) { --- 4757,4769 ---- return (-1); } mutex_enter(&softs->io_lock); dvp = AAC_DEV(softs, ap->a_target); ! if (dvp == NULL || !dvp->valid) { mutex_exit(&softs->io_lock); ! AACDB_PRINT(softs, CE_WARN, "Bad target t%dL%d to getcap", ap->a_target, ap->a_lun); return (-1); } switch (scsi_hba_lookup_capstr(cap)) {
*** 5052,5062 **** case SCSI_CAP_UNTAGGED_QING: case SCSI_CAP_TAGGED_QING: rval = 1; break; case SCSI_CAP_DMA_MAX: ! rval = softs->dma_max; break; default: rval = -1; break; } --- 4773,4783 ---- case SCSI_CAP_UNTAGGED_QING: case SCSI_CAP_TAGGED_QING: rval = 1; break; case SCSI_CAP_DMA_MAX: ! rval = softs->buf_dma_attr.dma_attr_maxxfer; break; default: rval = -1; break; }
*** 5084,5096 **** return (-1); } mutex_enter(&softs->io_lock); dvp = AAC_DEV(softs, ap->a_target); ! if (dvp == NULL || !AAC_DEV_IS_VALID(dvp)) { mutex_exit(&softs->io_lock); ! AACDB_PRINT_TRAN(softs, "Bad target t%dL%d to setcap", ap->a_target, ap->a_lun); return (-1); } switch (scsi_hba_lookup_capstr(cap)) { --- 4805,4817 ---- return (-1); } mutex_enter(&softs->io_lock); dvp = AAC_DEV(softs, ap->a_target); ! if (dvp == NULL || !dvp->valid) { mutex_exit(&softs->io_lock); ! AACDB_PRINT(softs, CE_WARN, "Bad target t%dL%d to setcap", ap->a_target, ap->a_lun); return (-1); } switch (scsi_hba_lookup_capstr(cap)) {
*** 5144,5169 **** if (acp->total_nwin > 0) { if (++acp->cur_win < acp->total_nwin) { off_t off; size_t len; ! rval = ddi_dma_getwin(acp->buf_dma_handle, acp->cur_win, ! &off, &len, &acp->cookie, &acp->left_cookien); if (rval == DDI_SUCCESS) goto get_dma_cookies; AACDB_PRINT(softs, CE_WARN, "ddi_dma_getwin() fail %d", rval); return (AACERR); ! } AACDB_PRINT(softs, CE_WARN, "Nothing to transfer"); return (AACERR); } /* We need to transfer data, so we alloc DMA resources for this pkt */ if (bp && bp->b_bcount != 0 && !(acp->flags & AAC_CMD_DMA_VALID)) { uint_t dma_flags = 0; struct aac_sge *sge; /* * We will still use this point to fake some * infomation in tran_start */ --- 4865,4897 ---- if (acp->total_nwin > 0) { if (++acp->cur_win < acp->total_nwin) { off_t off; size_t len; ! rval = ddi_dma_getwin(acp->segments[0].buf_dma_handle, ! acp->cur_win, &off, &len, ! &acp->segments[0].cookie, &acp->segments[0].left_cookien); ! acp->segment_cnt = 1; ! acp->left_cookien = acp->segments[0].left_cookien; if (rval == DDI_SUCCESS) goto get_dma_cookies; AACDB_PRINT(softs, CE_WARN, "ddi_dma_getwin() fail %d", rval); return (AACERR); ! } else { AACDB_PRINT(softs, CE_WARN, "Nothing to transfer"); return (AACERR); } + } /* We need to transfer data, so we alloc DMA resources for this pkt */ if (bp && bp->b_bcount != 0 && !(acp->flags & AAC_CMD_DMA_VALID)) { uint_t dma_flags = 0; struct aac_sge *sge; + int repeat = 0; + uint_t i, j; + uint32_t offset; /* * We will still use this point to fake some * infomation in tran_start */
*** 5180,5242 **** if (flags & PKT_CONSISTENT) dma_flags |= DDI_DMA_CONSISTENT; if (flags & PKT_DMA_PARTIAL) dma_flags |= DDI_DMA_PARTIAL; /* Alloc buf dma handle */ ! if (!acp->buf_dma_handle) { rval = ddi_dma_alloc_handle(softs->devinfo_p, &softs->buf_dma_attr, cb, arg, ! &acp->buf_dma_handle); if (rval != DDI_SUCCESS) { AACDB_PRINT(softs, CE_WARN, "Can't allocate DMA handle, errno=%d", rval); goto error_out; } } ! ! /* Bind buf */ ! if (((uintptr_t)bp->b_un.b_addr & AAC_DMA_ALIGN_MASK) == 0) { ! rval = ddi_dma_buf_bind_handle(acp->buf_dma_handle, ! bp, dma_flags, cb, arg, &acp->cookie, ! &acp->left_cookien); } else { - size_t bufsz; - AACDB_PRINT_TRAN(softs, "non-aligned buffer: addr=0x%p, cnt=%lu", (void *)bp->b_un.b_addr, bp->b_bcount); if (bp->b_flags & (B_PAGEIO|B_PHYS)) bp_mapin(bp); ! rval = ddi_dma_mem_alloc(acp->buf_dma_handle, AAC_ROUNDUP(bp->b_bcount, AAC_DMA_ALIGN), ! &softs->acc_attr, DDI_DMA_STREAMING, ! cb, arg, &acp->abp, &bufsz, &acp->abh); if (rval != DDI_SUCCESS) { AACDB_PRINT(softs, CE_NOTE, "Cannot alloc DMA to non-aligned buf"); bioerr = 0; goto error_out; } ! if (acp->flags & AAC_CMD_BUF_WRITE) ! ddi_rep_put8(acp->abh, ! (uint8_t *)bp->b_un.b_addr, ! (uint8_t *)acp->abp, bp->b_bcount, DDI_DEV_AUTOINCR); ! rval = ddi_dma_addr_bind_handle(acp->buf_dma_handle, ! NULL, acp->abp, bufsz, dma_flags, cb, arg, ! &acp->cookie, &acp->left_cookien); } switch (rval) { case DDI_DMA_PARTIAL_MAP: ! if (ddi_dma_numwin(acp->buf_dma_handle, &acp->total_nwin) == DDI_FAILURE) { AACDB_PRINT(softs, CE_WARN, "Cannot get number of DMA windows"); bioerr = 0; goto error_out; --- 4908,5042 ---- if (flags & PKT_CONSISTENT) dma_flags |= DDI_DMA_CONSISTENT; if (flags & PKT_DMA_PARTIAL) dma_flags |= DDI_DMA_PARTIAL; + do { + /* Bind buf */ + if (((uintptr_t)bp->b_un.b_addr & AAC_DMA_ALIGN_MASK) == 0 + && !repeat) { /* Alloc buf dma handle */ ! if (!acp->segments[0].buf_dma_handle) { rval = ddi_dma_alloc_handle(softs->devinfo_p, &softs->buf_dma_attr, cb, arg, ! &acp->segments[0].buf_dma_handle); if (rval != DDI_SUCCESS) { AACDB_PRINT(softs, CE_WARN, "Can't allocate DMA handle, errno=%d", rval); goto error_out; } } ! rval = ddi_dma_buf_bind_handle(acp->segments[0].buf_dma_handle, ! bp, dma_flags, cb, arg, &acp->segments[0].cookie, ! &acp->segments[0].left_cookien); ! acp->segment_cnt = 1; ! acp->left_cookien = acp->segments[0].left_cookien; } else { AACDB_PRINT_TRAN(softs, "non-aligned buffer: addr=0x%p, cnt=%lu", (void *)bp->b_un.b_addr, bp->b_bcount); if (bp->b_flags & (B_PAGEIO|B_PHYS)) bp_mapin(bp); ! if (repeat) { ! repeat = 0; ! acp->segment_cnt = (bp->b_bcount - 1) / ! softs->buf_dma_attr.dma_attr_maxxfer + 1; ! if (acp->segment_cnt > AAC_MAXSEGMENTS) { ! AACDB_PRINT(softs, CE_WARN, ! "After DDI_DMA_TOOBIG: Too much segments!"); ! acp->segment_cnt = AAC_MAXSEGMENTS; ! goto error_out; ! } ! ! for (i = 0; i < acp->segment_cnt; ++i) { ! rval = ddi_dma_alloc_handle(softs->devinfo_p, ! &softs->buf_dma_attr, cb, arg, ! &acp->segments[i].buf_dma_handle); ! if (rval != DDI_SUCCESS) { ! AACDB_PRINT(softs, CE_WARN, ! "After DDI_DMA_TOOBIG: Can't allocate DMA handle, errno=%d", ! rval); ! goto error_out; ! } ! if ((i == acp->segment_cnt - 1) && ! (bp->b_bcount % softs->buf_dma_attr.dma_attr_maxxfer)) ! acp->segments[i].abp_size = bp->b_bcount % ! softs->buf_dma_attr.dma_attr_maxxfer; ! else ! acp->segments[i].abp_size = ! softs->buf_dma_attr.dma_attr_maxxfer; ! rval = ddi_dma_mem_alloc(acp->segments[i].buf_dma_handle, ! acp->segments[i].abp_size, ! &aac_acc_attr, DDI_DMA_STREAMING, ! cb, arg, &acp->segments[i].abp, ! &acp->segments[i].abp_real_size, ! &acp->segments[i].abh); ! ! if (rval != DDI_SUCCESS) { ! AACDB_PRINT(softs, CE_NOTE, ! "Cannot alloc DMA to non-aligned buf"); ! bioerr = 0; ! goto error_out; ! } ! } ! } else { ! /* Alloc buf dma handle */ ! if (!acp->segments[0].buf_dma_handle) { ! rval = ddi_dma_alloc_handle(softs->devinfo_p, ! &softs->buf_dma_attr, cb, arg, ! &acp->segments[0].buf_dma_handle); ! if (rval != DDI_SUCCESS) { ! AACDB_PRINT(softs, CE_WARN, ! "Can't allocate DMA handle, errno=%d", ! rval); ! goto error_out; ! } ! } ! rval = ddi_dma_mem_alloc(acp->segments[0].buf_dma_handle, AAC_ROUNDUP(bp->b_bcount, AAC_DMA_ALIGN), ! &aac_acc_attr, DDI_DMA_STREAMING, ! cb, arg, &acp->segments[0].abp, ! &acp->segments[0].abp_real_size, ! &acp->segments[0].abh); if (rval != DDI_SUCCESS) { AACDB_PRINT(softs, CE_NOTE, "Cannot alloc DMA to non-aligned buf"); bioerr = 0; goto error_out; } + acp->segment_cnt = 1; + acp->segments[0].abp_size = bp->b_bcount; + } ! acp->left_cookien = 0; ! for (i = 0, offset = 0; i < acp->segment_cnt; ++i) { ! if (acp->flags & AAC_CMD_BUF_WRITE) { ! ddi_rep_put8(acp->segments[i].abh, ! (uint8_t *)bp->b_un.b_addr + offset, ! (uint8_t *)acp->segments[i].abp, ! acp->segments[i].abp_size, DDI_DEV_AUTOINCR); + offset += acp->segments[i].abp_size; + } ! rval = ddi_dma_addr_bind_handle(acp->segments[i].buf_dma_handle, ! NULL, acp->segments[i].abp, ! acp->segments[i].abp_real_size, dma_flags, cb, arg, ! &acp->segments[i].cookie, &acp->segments[i].left_cookien); ! if (rval != DDI_DMA_MAPPED) ! break; ! ! acp->left_cookien += acp->segments[i].left_cookien; } + } switch (rval) { case DDI_DMA_PARTIAL_MAP: ! if (ddi_dma_numwin(acp->segments[0].buf_dma_handle, &acp->total_nwin) == DDI_FAILURE) { AACDB_PRINT(softs, CE_WARN, "Cannot get number of DMA windows"); bioerr = 0; goto error_out;
*** 5263,5293 **** bioerr = EFAULT; AACDB_PRINT(softs, CE_WARN, "Cannot bind buf for DMA: DDI_DMA_NOMAPPING"); goto error_out; case DDI_DMA_TOOBIG: bioerr = EINVAL; AACDB_PRINT(softs, CE_WARN, ! "Cannot bind buf for DMA: DDI_DMA_TOOBIG(%d)", bp->b_bcount); goto error_out; default: bioerr = EINVAL; AACDB_PRINT(softs, CE_WARN, "Cannot bind buf for DMA: %d", rval); goto error_out; } acp->flags |= AAC_CMD_DMA_VALID; get_dma_cookies: ASSERT(acp->left_cookien > 0); - if (acp->left_cookien > softs->aac_sg_tablesize) { - AACDB_PRINT(softs, CE_NOTE, "large cookiec received %d", - acp->left_cookien); - bioerr = EINVAL; - goto error_out; - } if (oldcookiec != acp->left_cookien && acp->sgt != NULL) { kmem_free(acp->sgt, sizeof (struct aac_sge) * \ oldcookiec); acp->sgt = NULL; } --- 5063,5094 ---- bioerr = EFAULT; AACDB_PRINT(softs, CE_WARN, "Cannot bind buf for DMA: DDI_DMA_NOMAPPING"); goto error_out; case DDI_DMA_TOOBIG: + if (bp->b_bcount > softs->buf_dma_attr.dma_attr_maxxfer && + acp->segment_cnt == 1) { + repeat = 1; + break; + } else { bioerr = EINVAL; AACDB_PRINT(softs, CE_WARN, ! "Cannot bind buf for DMA: DDI_DMA_TOOBIG(%d) - returning EINVAL", bp->b_bcount); goto error_out; + } default: bioerr = EINVAL; AACDB_PRINT(softs, CE_WARN, "Cannot bind buf for DMA: %d", rval); goto error_out; } + } while (repeat); acp->flags |= AAC_CMD_DMA_VALID; get_dma_cookies: ASSERT(acp->left_cookien > 0); if (oldcookiec != acp->left_cookien && acp->sgt != NULL) { kmem_free(acp->sgt, sizeof (struct aac_sge) * \ oldcookiec); acp->sgt = NULL; }
*** 5301,5354 **** goto error_out; } } sge = &acp->sgt[0]; ! sge->bcount = acp->cookie.dmac_size; ! sge->addr.ad64.lo = AAC_LS32(acp->cookie.dmac_laddress); ! sge->addr.ad64.hi = AAC_MS32(acp->cookie.dmac_laddress); ! acp->bcount = acp->cookie.dmac_size; ! for (sge++; sge < &acp->sgt[acp->left_cookien]; sge++) { ! ddi_dma_nextcookie(acp->buf_dma_handle, &acp->cookie); ! sge->bcount = acp->cookie.dmac_size; ! sge->addr.ad64.lo = AAC_LS32(acp->cookie.dmac_laddress); ! sge->addr.ad64.hi = AAC_MS32(acp->cookie.dmac_laddress); ! acp->bcount += acp->cookie.dmac_size; } /* * Note: The old DMA engine do not correctly handle * dma_attr_maxxfer attribute. So we have to ensure * it by ourself. */ ! if (acp->bcount > softs->buf_dma_attr.dma_attr_maxxfer) { AACDB_PRINT(softs, CE_NOTE, "large xfer size received %d\n", acp->bcount); bioerr = EINVAL; goto error_out; } acp->total_xfer += acp->bcount; - if (acp->pkt) { /* Return remaining byte count */ ! if (acp->total_xfer <= bp->b_bcount) { ! acp->pkt->pkt_resid = bp->b_bcount - \ ! acp->total_xfer; ! } else { ! /* ! * Allocated DMA size is greater than the buf ! * size of bp. This is caused by devices like ! * tape. we have extra bytes allocated, but ! * the packet residual has to stay correct. ! */ ! acp->pkt->pkt_resid = 0; ! } AACDB_PRINT_TRAN(softs, "bp=0x%p, xfered=%d/%d, resid=%d", (void *)bp->b_un.b_addr, (int)acp->total_xfer, (int)bp->b_bcount, (int)acp->pkt->pkt_resid); } } return (AACOK); error_out: --- 5102,5156 ---- goto error_out; } } sge = &acp->sgt[0]; ! acp->bcount = 0; ! for (i = 0; i < acp->segment_cnt; ++i) { ! acp->segments[i].sgt = sge; ! if (acp->segments[i].left_cookien > softs->aac_sg_tablesize) { ! AACDB_PRINT(softs, CE_NOTE, "large cookiec received %d", ! acp->segments[i].left_cookien); ! bioerr = EINVAL; ! goto error_out; } + for (j = 0; j < acp->segments[i].left_cookien; ++j) { + if (j > 0) + ddi_dma_nextcookie(acp->segments[i].buf_dma_handle, + &acp->segments[i].cookie); + sge->bcount = acp->segments[i].cookie.dmac_size; + sge->addr.ad64.lo = AAC_LS32(acp->segments[i].cookie.dmac_laddress); + sge->addr.ad64.hi = AAC_MS32(acp->segments[i].cookie.dmac_laddress); + acp->bcount += acp->segments[i].cookie.dmac_size; + sge++; + } + } /* * Note: The old DMA engine do not correctly handle * dma_attr_maxxfer attribute. So we have to ensure * it by ourself. */ ! if (acp->segment_cnt == 1 && ! acp->bcount > softs->buf_dma_attr.dma_attr_maxxfer) { AACDB_PRINT(softs, CE_NOTE, "large xfer size received %d\n", acp->bcount); bioerr = EINVAL; goto error_out; } acp->total_xfer += acp->bcount; if (acp->pkt) { /* Return remaining byte count */ ! acp->pkt->pkt_resid = bp->b_bcount - acp->total_xfer; ! AACDB_PRINT_TRAN(softs, "bp=0x%p, xfered=%d/%d, resid=%d", (void *)bp->b_un.b_addr, (int)acp->total_xfer, (int)bp->b_bcount, (int)acp->pkt->pkt_resid); + + ASSERT(acp->pkt->pkt_resid >= 0); } } return (AACOK); error_out:
*** 5416,5426 **** struct aac_cmd *acp = PKT2AC(pkt); DBCALLED(NULL, 2); if (aac_dma_sync_ac(acp) != AACOK) ! ddi_fm_service_impact( (AAC_TRAN2SOFTS(ap->a_hba_tran))->devinfo_p, DDI_SERVICE_UNAFFECTED); } /* --- 5218,5228 ---- struct aac_cmd *acp = PKT2AC(pkt); DBCALLED(NULL, 2); if (aac_dma_sync_ac(acp) != AACOK) ! aac_fm_service_impact( (AAC_TRAN2SOFTS(ap->a_hba_tran))->devinfo_p, DDI_SERVICE_UNAFFECTED); } /*
*** 5527,5536 **** --- 5329,5341 ---- hba_tran->tran_sync_pkt = aac_tran_sync_pkt; hba_tran->tran_dmafree = aac_tran_dmafree; hba_tran->tran_quiesce = aac_tran_quiesce; hba_tran->tran_unquiesce = aac_tran_unquiesce; hba_tran->tran_bus_config = aac_tran_bus_config; + #if 0 + hba_tran->tran_interconnect_type = INTERCONNECT_PARALLEL; + #endif rval = scsi_hba_attach_setup(softs->devinfo_p, &softs->buf_dma_attr, hba_tran, 0); if (rval != DDI_SUCCESS) { scsi_hba_tran_free(hba_tran); AACDB_PRINT(softs, CE_WARN, "aac_hba_setup failed");
*** 5547,5604 **** /* * Init FIB header */ static void ! aac_cmd_fib_header(struct aac_softstate *softs, struct aac_cmd *acp, ! uint16_t cmd) { - struct aac_slot *slotp = acp->slotp; ddi_acc_handle_t acc = slotp->fib_acc_handle; struct aac_fib *fibp = slotp->fibp; uint32_t xfer_state; xfer_state = AAC_FIBSTATE_HOSTOWNED | AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY | - AAC_FIBSTATE_FAST_RESPONSE | /* enable fast io */ AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_REXPECTED | AAC_FIBSTATE_NORM; - if (!(acp->flags & AAC_CMD_SYNC)) - xfer_state |= AAC_FIBSTATE_ASYNC; - ddi_put32(acc, &fibp->Header.XferState, xfer_state); ddi_put16(acc, &fibp->Header.Command, cmd); ddi_put8(acc, &fibp->Header.StructType, AAC_FIBTYPE_TFIB); ! ddi_put8(acc, &fibp->Header.Flags, 0); /* don't care */ ! ddi_put16(acc, &fibp->Header.Size, acp->fib_size); ! ddi_put16(acc, &fibp->Header.SenderSize, softs->aac_max_fib_size); ddi_put32(acc, &fibp->Header.SenderFibAddress, (slotp->index << 2)); ! ddi_put32(acc, &fibp->Header.ReceiverFibAddress, slotp->fib_phyaddr); ! ddi_put32(acc, &fibp->Header.SenderData, 0); /* don't care */ } /* * Init FIB for raw IO command */ static void aac_cmd_fib_rawio(struct aac_softstate *softs, struct aac_cmd *acp) { ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; struct aac_raw_io *io = (struct aac_raw_io *)&acp->slotp->fibp->data[0]; struct aac_sg_entryraw *sgp; ! struct aac_sge *sge; /* Calculate FIB size */ acp->fib_size = sizeof (struct aac_fib_header) + \ ! sizeof (struct aac_raw_io) + (acp->left_cookien - 1) * \ sizeof (struct aac_sg_entryraw); ! aac_cmd_fib_header(softs, acp, RawIo); ddi_put16(acc, &io->Flags, (acp->flags & AAC_CMD_BUF_READ) ? 1 : 0); ddi_put16(acc, &io->BpTotal, 0); ddi_put16(acc, &io->BpComplete, 0); --- 5352,5555 ---- /* * Init FIB header */ static void ! aac_cmd_fib_header(struct aac_softstate *softs, struct aac_slot *slotp, ! uint16_t cmd, uint16_t fib_size) { ddi_acc_handle_t acc = slotp->fib_acc_handle; struct aac_fib *fibp = slotp->fibp; uint32_t xfer_state; xfer_state = AAC_FIBSTATE_HOSTOWNED | AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY | AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_REXPECTED | AAC_FIBSTATE_NORM; + if (slotp->acp && !(slotp->acp->flags & AAC_CMD_SYNC)) { + xfer_state |= + AAC_FIBSTATE_ASYNC | + AAC_FIBSTATE_FAST_RESPONSE /* enable fast io */; + ddi_put16(acc, &fibp->Header.SenderSize, + softs->aac_max_fib_size); + } else { + ddi_put16(acc, &fibp->Header.SenderSize, AAC_FIB_SIZE); + } ddi_put32(acc, &fibp->Header.XferState, xfer_state); ddi_put16(acc, &fibp->Header.Command, cmd); ddi_put8(acc, &fibp->Header.StructType, AAC_FIBTYPE_TFIB); ! ddi_put8(acc, &fibp->Header.Unused, 0); /* don't care */ ! ddi_put16(acc, &fibp->Header.Size, fib_size); ddi_put32(acc, &fibp->Header.SenderFibAddress, (slotp->index << 2)); ! ddi_put32(acc, &fibp->Header.a.ReceiverFibAddress, slotp->fib_phyaddr); ! ddi_put32(acc, &fibp->Header.Handle, slotp->index + 1); } /* + * Init FIB for raw IO2 command + */ + static void + aac_cmd_fib_rawio2(struct aac_softstate *softs, struct aac_cmd *acp) + { + ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; + struct aac_raw_io2 *io = (struct aac_raw_io2 *)&acp->slotp->fibp->data[0]; + struct aac_sge_ieee1212 *sgp; + struct aac_sge *sge = &acp->sgt[0]; + uint_t i, left_cookien, conformable; + uint32_t min_size, cur_size, nom_size; + uint16_t flags; + + if (acp->segment_cnt > 1) { + uint_t idx = acp->cur_segment; + left_cookien = acp->segments[idx].left_cookien; + acp->bcount = acp->segments[idx].abp_size; + sge = acp->segments[idx].sgt; + if (idx > 0) + acp->blkno += acp->segments[idx-1].abp_size / AAC_BLK_SIZE; + } else + left_cookien = acp->left_cookien; + + ddi_put32(acc, &io->strtBlkLow, AAC_LS32(acp->blkno)); + ddi_put32(acc, &io->strtBlkHigh, AAC_MS32(acp->blkno)); + ddi_put32(acc, &io->byteCnt, acp->bcount); + ddi_put16(acc, &io->ldNum, + ((struct aac_container *)acp->dvp)->cid); + flags = (acp->flags & AAC_CMD_BUF_READ) ? + RIO2_IO_TYPE_READ : RIO2_IO_TYPE_WRITE; + flags |= RIO2_SG_FORMAT_IEEE1212; + + /* Fill SG table */ + for (i = 0, sgp = &io->sge[0]; i < left_cookien; i++, sge++, sgp++) { + ddi_put32(acc, &sgp->addrLow, sge->addr.ad64.lo); + ddi_put32(acc, &sgp->addrHigh, sge->addr.ad64.hi); + ddi_put32(acc, &sgp->length, sge->bcount); + ddi_put32(acc, &sgp->flags, 0L); + cur_size = sge->bcount; + if (i == 0) { + conformable = 1; + ddi_put32(acc, &io->sgeFirstSize, cur_size); + } else if (i == 1) { + nom_size = cur_size; + ddi_put32(acc, &io->sgeNominalSize, nom_size); + min_size = cur_size; + } else if ((i+1) < left_cookien && cur_size != nom_size) { + conformable = 0; + if (cur_size < min_size) + min_size = cur_size; + } + } + + /* not conformable: evaluate required sg elements */ + if (!conformable) { + uint_t j, err_found, left_cookien_new = left_cookien; + for (i = min_size / AAC_PAGE_SIZE; i >= 1; --i) { + err_found = 0; + left_cookien_new = 2; + for (j = 1; j < left_cookien - 1; ++j) { + if (ddi_get32(acc, &io->sge[j].length) % (i*AAC_PAGE_SIZE)) { + err_found = 1; + break; + } + left_cookien_new += (ddi_get32(acc, &io->sge[j].length) / (i*AAC_PAGE_SIZE)); + } + if (!err_found) + break; + } + if (i > 0 && left_cookien_new <= softs->aac_sg_tablesize && + !softs->no_sgl_conv) + left_cookien = aac_convert_sgraw2(softs, + acp, i, left_cookien, left_cookien_new, &flags); + } else { + flags |= RIO2_SGL_CONFORMANT; + } + ddi_put16(acc, &io->flags, flags); + ddi_put8(acc, &io->sgeCnt, left_cookien); + + /* Calculate FIB size */ + acp->fib_size = sizeof (struct aac_fib_header) + \ + sizeof (struct aac_raw_io2) + (left_cookien - 1) * \ + sizeof (struct aac_sge_ieee1212); + + aac_cmd_fib_header(softs, acp->slotp, RawIo2, acp->fib_size); + } + + + static uint_t + aac_convert_sgraw2(struct aac_softstate *softs, struct aac_cmd *acp, + uint_t pages, uint_t left_cookien, uint_t left_cookien_new, + uint16_t *flags) + { + ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; + struct aac_raw_io2 *io = (struct aac_raw_io2 *)&acp->slotp->fibp->data[0]; + struct aac_sge_ieee1212 *sge; + uint_t i, j, pos; + uint32_t addr_low_new, addr_low; + + sge = kmem_alloc(left_cookien_new * sizeof(struct aac_sge_ieee1212), + KM_NOSLEEP); + if (sge == NULL) + return left_cookien; + + for (i = 1, pos = 1; i < left_cookien-1; ++i) { + for (j = 0; j < ddi_get32(acc, &io->sge[i].length) / (pages * AAC_PAGE_SIZE); ++j) { + addr_low = ddi_get32(acc, &io->sge[i].addrLow); + addr_low_new = addr_low + j * pages * AAC_PAGE_SIZE; + sge[pos].addrLow = addr_low_new; + sge[pos].addrHigh = ddi_get32(acc, &io->sge[i].addrHigh); + if (addr_low_new < addr_low) + sge[pos].addrHigh++; + sge[pos].length = pages * AAC_PAGE_SIZE; + sge[pos].flags = 0; + pos++; + } + } + sge[pos].addrLow = ddi_get32(acc, &io->sge[left_cookien-1].addrLow); + sge[pos].addrHigh = ddi_get32(acc, &io->sge[left_cookien-1].addrHigh); + sge[pos].length = ddi_get32(acc, &io->sge[left_cookien-1].length); + sge[pos].flags = 0; + ddi_rep_put8(acc, (uint8_t *)&sge[1], + (uint8_t *)&io->sge[1], (left_cookien_new-1) * + sizeof(struct aac_sge_ieee1212), DDI_DEV_AUTOINCR); + + kmem_free(sge, left_cookien_new * sizeof(struct aac_sge_ieee1212)); + *flags |= RIO2_SGL_CONFORMANT; + ddi_put32(acc, &io->sgeNominalSize, pages * AAC_PAGE_SIZE); + return left_cookien_new; + } + + /* * Init FIB for raw IO command */ static void aac_cmd_fib_rawio(struct aac_softstate *softs, struct aac_cmd *acp) { ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; struct aac_raw_io *io = (struct aac_raw_io *)&acp->slotp->fibp->data[0]; struct aac_sg_entryraw *sgp; ! struct aac_sge *sge = &acp->sgt[0]; ! uint_t i, left_cookien; + if (acp->segment_cnt > 1) { + uint_t idx = acp->cur_segment; + left_cookien = acp->segments[idx].left_cookien; + acp->bcount = acp->segments[idx].abp_size; + sge = acp->segments[idx].sgt; + if (idx > 0) + acp->blkno += acp->segments[idx-1].abp_size / AAC_BLK_SIZE; + } else + left_cookien = acp->left_cookien; + /* Calculate FIB size */ acp->fib_size = sizeof (struct aac_fib_header) + \ ! sizeof (struct aac_raw_io) + (left_cookien - 1) * \ sizeof (struct aac_sg_entryraw); ! aac_cmd_fib_header(softs, acp->slotp, RawIo, acp->fib_size); ddi_put16(acc, &io->Flags, (acp->flags & AAC_CMD_BUF_READ) ? 1 : 0); ddi_put16(acc, &io->BpTotal, 0); ddi_put16(acc, &io->BpComplete, 0);
*** 5606,5620 **** ddi_put32(acc, AAC_HI32(&io->BlockNumber), AAC_MS32(acp->blkno)); ddi_put16(acc, &io->ContainerId, ((struct aac_container *)acp->dvp)->cid); /* Fill SG table */ ! ddi_put32(acc, &io->SgMapRaw.SgCount, acp->left_cookien); ddi_put32(acc, &io->ByteCount, acp->bcount); ! for (sge = &acp->sgt[0], sgp = &io->SgMapRaw.SgEntryRaw[0]; ! sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) { ddi_put32(acc, AAC_LO32(&sgp->SgAddress), sge->addr.ad64.lo); ddi_put32(acc, AAC_HI32(&sgp->SgAddress), sge->addr.ad64.hi); ddi_put32(acc, &sgp->SgByteCount, sge->bcount); sgp->Next = 0; sgp->Prev = 0; --- 5557,5571 ---- ddi_put32(acc, AAC_HI32(&io->BlockNumber), AAC_MS32(acp->blkno)); ddi_put16(acc, &io->ContainerId, ((struct aac_container *)acp->dvp)->cid); /* Fill SG table */ ! ddi_put32(acc, &io->SgMapRaw.SgCount, left_cookien); ddi_put32(acc, &io->ByteCount, acp->bcount); ! for (i = 0, sgp = &io->SgMapRaw.SgEntryRaw[0]; ! i < left_cookien; i++, sge++, sgp++) { ddi_put32(acc, AAC_LO32(&sgp->SgAddress), sge->addr.ad64.lo); ddi_put32(acc, AAC_HI32(&sgp->SgAddress), sge->addr.ad64.hi); ddi_put32(acc, &sgp->SgByteCount, sge->bcount); sgp->Next = 0; sgp->Prev = 0;
*** 5628,5644 **** { ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; struct aac_blockread64 *br = (struct aac_blockread64 *) \ &acp->slotp->fibp->data[0]; struct aac_sg_entry64 *sgp; ! struct aac_sge *sge; acp->fib_size = sizeof (struct aac_fib_header) + \ ! sizeof (struct aac_blockread64) + (acp->left_cookien - 1) * \ sizeof (struct aac_sg_entry64); ! aac_cmd_fib_header(softs, acp, ContainerCommand64); /* * The definitions for aac_blockread64 and aac_blockwrite64 * are the same. */ --- 5579,5607 ---- { ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; struct aac_blockread64 *br = (struct aac_blockread64 *) \ &acp->slotp->fibp->data[0]; struct aac_sg_entry64 *sgp; ! struct aac_sge *sge = &acp->sgt[0]; ! uint_t i, left_cookien; + if (acp->segment_cnt > 1) { + uint_t idx = acp->cur_segment; + left_cookien = acp->segments[idx].left_cookien; + acp->bcount = acp->segments[idx].abp_size; + sge = acp->segments[idx].sgt; + if (idx > 0) + acp->blkno += acp->segments[idx-1].abp_size / AAC_BLK_SIZE; + } else + left_cookien = acp->left_cookien; + acp->fib_size = sizeof (struct aac_fib_header) + \ ! sizeof (struct aac_blockread64) + (left_cookien - 1) * \ sizeof (struct aac_sg_entry64); ! aac_cmd_fib_header(softs, acp->slotp, ContainerCommand64, ! acp->fib_size); /* * The definitions for aac_blockread64 and aac_blockwrite64 * are the same. */
*** 5649,5663 **** VM_CtHostRead64 : VM_CtHostWrite64); ddi_put16(acc, &br->Pad, 0); ddi_put16(acc, &br->Flags, 0); /* Fill SG table */ ! ddi_put32(acc, &br->SgMap64.SgCount, acp->left_cookien); ddi_put16(acc, &br->SectorCount, acp->bcount / AAC_BLK_SIZE); ! for (sge = &acp->sgt[0], sgp = &br->SgMap64.SgEntry64[0]; ! sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) { ddi_put32(acc, AAC_LO32(&sgp->SgAddress), sge->addr.ad64.lo); ddi_put32(acc, AAC_HI32(&sgp->SgAddress), sge->addr.ad64.hi); ddi_put32(acc, &sgp->SgByteCount, sge->bcount); } } --- 5612,5626 ---- VM_CtHostRead64 : VM_CtHostWrite64); ddi_put16(acc, &br->Pad, 0); ddi_put16(acc, &br->Flags, 0); /* Fill SG table */ ! ddi_put32(acc, &br->SgMap64.SgCount, left_cookien); ddi_put16(acc, &br->SectorCount, acp->bcount / AAC_BLK_SIZE); ! for (i = 0, sgp = &br->SgMap64.SgEntry64[0]; ! i < left_cookien; i++, sge++, sgp++) { ddi_put32(acc, AAC_LO32(&sgp->SgAddress), sge->addr.ad64.lo); ddi_put32(acc, AAC_HI32(&sgp->SgAddress), sge->addr.ad64.hi); ddi_put32(acc, &sgp->SgByteCount, sge->bcount); } }
*** 5669,5700 **** ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; struct aac_blockread *br = (struct aac_blockread *) \ &acp->slotp->fibp->data[0]; struct aac_sg_entry *sgp; struct aac_sge *sge = &acp->sgt[0]; if (acp->flags & AAC_CMD_BUF_READ) { acp->fib_size = sizeof (struct aac_fib_header) + \ ! sizeof (struct aac_blockread) + (acp->left_cookien - 1) * \ sizeof (struct aac_sg_entry); ddi_put32(acc, &br->Command, VM_CtBlockRead); ! ddi_put32(acc, &br->SgMap.SgCount, acp->left_cookien); sgp = &br->SgMap.SgEntry[0]; } else { struct aac_blockwrite *bw = (struct aac_blockwrite *)br; acp->fib_size = sizeof (struct aac_fib_header) + \ ! sizeof (struct aac_blockwrite) + (acp->left_cookien - 1) * \ sizeof (struct aac_sg_entry); ddi_put32(acc, &bw->Command, VM_CtBlockWrite); ddi_put32(acc, &bw->Stable, CUNSTABLE); ! ddi_put32(acc, &bw->SgMap.SgCount, acp->left_cookien); sgp = &bw->SgMap.SgEntry[0]; } ! aac_cmd_fib_header(softs, acp, ContainerCommand); /* * aac_blockread and aac_blockwrite have the similar * structure head, so use br for bw here */ --- 5632,5674 ---- ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; struct aac_blockread *br = (struct aac_blockread *) \ &acp->slotp->fibp->data[0]; struct aac_sg_entry *sgp; struct aac_sge *sge = &acp->sgt[0]; + uint_t i, left_cookien; + if (acp->segment_cnt > 1) { + uint_t idx = acp->cur_segment; + left_cookien = acp->segments[idx].left_cookien; + acp->bcount = acp->segments[idx].abp_size; + sge = acp->segments[idx].sgt; + if (idx > 0) + acp->blkno += acp->segments[idx-1].abp_size / AAC_BLK_SIZE; + } else + left_cookien = acp->left_cookien; + if (acp->flags & AAC_CMD_BUF_READ) { acp->fib_size = sizeof (struct aac_fib_header) + \ ! sizeof (struct aac_blockread) + (left_cookien - 1) * \ sizeof (struct aac_sg_entry); ddi_put32(acc, &br->Command, VM_CtBlockRead); ! ddi_put32(acc, &br->SgMap.SgCount, left_cookien); sgp = &br->SgMap.SgEntry[0]; } else { struct aac_blockwrite *bw = (struct aac_blockwrite *)br; acp->fib_size = sizeof (struct aac_fib_header) + \ ! sizeof (struct aac_blockwrite) + (left_cookien - 1) * \ sizeof (struct aac_sg_entry); ddi_put32(acc, &bw->Command, VM_CtBlockWrite); ddi_put32(acc, &bw->Stable, CUNSTABLE); ! ddi_put32(acc, &bw->SgMap.SgCount, left_cookien); sgp = &bw->SgMap.SgEntry[0]; } ! aac_cmd_fib_header(softs, acp->slotp, ContainerCommand, acp->fib_size); /* * aac_blockread and aac_blockwrite have the similar * structure head, so use br for bw here */
*** 5702,5713 **** ddi_put32(acc, &br->ContainerId, ((struct aac_container *)acp->dvp)->cid); ddi_put32(acc, &br->ByteCount, acp->bcount); /* Fill SG table */ ! for (sge = &acp->sgt[0]; ! sge < &acp->sgt[acp->left_cookien]; sge++, sgp++) { ddi_put32(acc, &sgp->SgAddress, sge->addr.ad32); ddi_put32(acc, &sgp->SgByteCount, sge->bcount); } } --- 5676,5686 ---- ddi_put32(acc, &br->ContainerId, ((struct aac_container *)acp->dvp)->cid); ddi_put32(acc, &br->ByteCount, acp->bcount); /* Fill SG table */ ! for (i = 0; i < left_cookien; i++, sge++, sgp++) { ddi_put32(acc, &sgp->SgAddress, sge->addr.ad32); ddi_put32(acc, &sgp->SgByteCount, sge->bcount); } }
*** 5720,5782 **** ddi_acc_handle_t acc = slotp->fib_acc_handle; ddi_rep_put8(acc, (uint8_t *)acp->fibp, (uint8_t *)fibp, acp->fib_size, /* only copy data of needed length */ DDI_DEV_AUTOINCR); ! ddi_put32(acc, &fibp->Header.ReceiverFibAddress, slotp->fib_phyaddr); ddi_put32(acc, &fibp->Header.SenderFibAddress, slotp->index << 2); } static void aac_cmd_fib_sync(struct aac_softstate *softs, struct aac_cmd *acp) { ! ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; struct aac_synchronize_command *sync = ! (struct aac_synchronize_command *)&acp->slotp->fibp->data[0]; ! acp->fib_size = AAC_FIB_SIZEOF(struct aac_synchronize_command); ! aac_cmd_fib_header(softs, acp, ContainerCommand); ddi_put32(acc, &sync->Command, VM_ContainerConfig); ddi_put32(acc, &sync->Type, (uint32_t)CT_FLUSH_CACHE); ddi_put32(acc, &sync->Cid, ((struct aac_container *)acp->dvp)->cid); ddi_put32(acc, &sync->Count, sizeof (((struct aac_synchronize_reply *)0)->Data)); } - /* - * Start/Stop unit (Power Management) - */ static void ! aac_cmd_fib_startstop(struct aac_softstate *softs, struct aac_cmd *acp) { ! ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; ! struct aac_Container *cmd = ! (struct aac_Container *)&acp->slotp->fibp->data[0]; ! union scsi_cdb *cdbp = (void *)acp->pkt->pkt_cdbp; ! acp->fib_size = AAC_FIB_SIZEOF(struct aac_Container); ! aac_cmd_fib_header(softs, acp, ContainerCommand); ! bzero(cmd, sizeof (*cmd) - CT_PACKET_SIZE); ! ddi_put32(acc, &cmd->Command, VM_ContainerConfig); ! ddi_put32(acc, &cmd->CTCommand.command, CT_PM_DRIVER_SUPPORT); ! ddi_put32(acc, &cmd->CTCommand.param[0], cdbp->cdb_opaque[4] & 1 ? \ ! AAC_PM_DRIVERSUP_START_UNIT : AAC_PM_DRIVERSUP_STOP_UNIT); ! ddi_put32(acc, &cmd->CTCommand.param[1], ! ((struct aac_container *)acp->dvp)->cid); ! ddi_put32(acc, &cmd->CTCommand.param[2], cdbp->cdb_opaque[1] & 1); } /* * Init FIB for pass-through SCMD */ static void aac_cmd_fib_srb(struct aac_cmd *acp) { ! ddi_acc_handle_t acc = acp->slotp->fib_acc_handle; ! struct aac_srb *srb = (struct aac_srb *)&acp->slotp->fibp->data[0]; uint8_t *cdb; ddi_put32(acc, &srb->function, SRBF_ExecuteScsi); ddi_put32(acc, &srb->retry_limit, 0); ddi_put32(acc, &srb->cdb_size, acp->cmdlen); --- 5693,5749 ---- ddi_acc_handle_t acc = slotp->fib_acc_handle; ddi_rep_put8(acc, (uint8_t *)acp->fibp, (uint8_t *)fibp, acp->fib_size, /* only copy data of needed length */ DDI_DEV_AUTOINCR); ! ddi_put32(acc, &fibp->Header.a.ReceiverFibAddress,slotp->fib_phyaddr); ddi_put32(acc, &fibp->Header.SenderFibAddress, slotp->index << 2); + ddi_put32(acc, &fibp->Header.Handle, slotp->index + 1); } static void aac_cmd_fib_sync(struct aac_softstate *softs, struct aac_cmd *acp) { ! struct aac_slot *slotp = acp->slotp; ! ddi_acc_handle_t acc = slotp->fib_acc_handle; struct aac_synchronize_command *sync = ! (struct aac_synchronize_command *)&slotp->fibp->data[0]; ! acp->fib_size = sizeof (struct aac_fib_header) + \ ! sizeof (struct aac_synchronize_command); ! aac_cmd_fib_header(softs, slotp, ContainerCommand, acp->fib_size); ddi_put32(acc, &sync->Command, VM_ContainerConfig); ddi_put32(acc, &sync->Type, (uint32_t)CT_FLUSH_CACHE); ddi_put32(acc, &sync->Cid, ((struct aac_container *)acp->dvp)->cid); ddi_put32(acc, &sync->Count, sizeof (((struct aac_synchronize_reply *)0)->Data)); } static void ! aac_cmd_aif_request(struct aac_softstate *softs, struct aac_cmd *acp) { ! struct aac_slot *slotp = acp->slotp; ! ddi_acc_handle_t acc = slotp->fib_acc_handle; ! struct aac_aif_command *aif = ! (struct aac_aif_command *)&slotp->fibp->data[0]; ! acp->fib_size = sizeof(struct aac_fib); ! aac_cmd_fib_header(softs, slotp, AifRequest, acp->fib_size); ! ddi_put32(acc, (uint32_t *)&aif->command, AifReqEvent); } /* * Init FIB for pass-through SCMD */ static void aac_cmd_fib_srb(struct aac_cmd *acp) { ! struct aac_slot *slotp = acp->slotp; ! ddi_acc_handle_t acc = slotp->fib_acc_handle; ! struct aac_srb *srb = (struct aac_srb *)&slotp->fibp->data[0]; uint8_t *cdb; ddi_put32(acc, &srb->function, SRBF_ExecuteScsi); ddi_put32(acc, &srb->retry_limit, 0); ddi_put32(acc, &srb->cdb_size, acp->cmdlen);
*** 5814,5824 **** acp->fib_size = sizeof (struct aac_fib_header) + \ sizeof (struct aac_srb) - sizeof (struct aac_sg_entry) + \ acp->left_cookien * sizeof (struct aac_sg_entry); /* Fill FIB and SRB headers, and copy cdb */ ! aac_cmd_fib_header(softs, acp, ScsiPortCommand); aac_cmd_fib_srb(acp); /* Fill SG table */ ddi_put32(acc, &srb->sg.SgCount, acp->left_cookien); ddi_put32(acc, &srb->count, acp->bcount); --- 5781,5791 ---- acp->fib_size = sizeof (struct aac_fib_header) + \ sizeof (struct aac_srb) - sizeof (struct aac_sg_entry) + \ acp->left_cookien * sizeof (struct aac_sg_entry); /* Fill FIB and SRB headers, and copy cdb */ ! aac_cmd_fib_header(softs, acp->slotp, ScsiPortCommand, acp->fib_size); aac_cmd_fib_srb(acp); /* Fill SG table */ ddi_put32(acc, &srb->sg.SgCount, acp->left_cookien); ddi_put32(acc, &srb->count, acp->bcount);
*** 5841,5851 **** acp->fib_size = sizeof (struct aac_fib_header) + \ sizeof (struct aac_srb) - sizeof (struct aac_sg_entry) + \ acp->left_cookien * sizeof (struct aac_sg_entry64); /* Fill FIB and SRB headers, and copy cdb */ ! aac_cmd_fib_header(softs, acp, ScsiPortCommandU64); aac_cmd_fib_srb(acp); /* Fill SG table */ ddi_put32(acc, &srb->sg.SgCount, acp->left_cookien); ddi_put32(acc, &srb->count, acp->bcount); --- 5808,5819 ---- acp->fib_size = sizeof (struct aac_fib_header) + \ sizeof (struct aac_srb) - sizeof (struct aac_sg_entry) + \ acp->left_cookien * sizeof (struct aac_sg_entry64); /* Fill FIB and SRB headers, and copy cdb */ ! aac_cmd_fib_header(softs, acp->slotp, ScsiPortCommandU64, ! acp->fib_size); aac_cmd_fib_srb(acp); /* Fill SG table */ ddi_put32(acc, &srb->sg.SgCount, acp->left_cookien); ddi_put32(acc, &srb->count, acp->bcount);
*** 5862,5877 **** --- 5830,5853 ---- static int aac_cmd_slot_bind(struct aac_softstate *softs, struct aac_cmd *acp) { struct aac_slot *slotp; + if ((softs->flags & AAC_FLAGS_SYNC_MODE) && + softs->sync_slot_busy) + return (AACERR); + if (slotp = aac_get_slot(softs)) { acp->slotp = slotp; slotp->acp = acp; acp->aac_cmd_fib(softs, acp); (void) ddi_dma_sync(slotp->fib_dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV); + if (softs->flags & AAC_FLAGS_SYNC_MODE) { + softs->sync_slot_busy = 1; + softs->sync_mode_slot = slotp; + } return (AACOK); } return (AACERR); }
*** 5879,5937 **** aac_bind_io(struct aac_softstate *softs, struct aac_cmd *acp) { struct aac_device *dvp = acp->dvp; int q = AAC_CMDQ(acp); - if (softs->bus_ncmds[q] < softs->bus_throttle[q]) { if (dvp) { if (dvp->ncmds[q] < dvp->throttle[q]) { if (!(acp->flags & AAC_CMD_NTAG) || dvp->ncmds[q] == 0) { return (aac_cmd_slot_bind(softs, acp)); } ASSERT(q == AAC_CMDQ_ASYNC); aac_set_throttle(softs, dvp, AAC_CMDQ_ASYNC, AAC_THROTTLE_DRAIN); } } else { ! return (aac_cmd_slot_bind(softs, acp)); } - } return (AACERR); } - static int - aac_sync_fib_slot_bind(struct aac_softstate *softs, struct aac_cmd *acp) - { - struct aac_slot *slotp; - - while (softs->sync_ac.slotp) - cv_wait(&softs->sync_fib_cv, &softs->io_lock); - - if (slotp = aac_get_slot(softs)) { - ASSERT(acp->slotp == NULL); - - acp->slotp = slotp; - slotp->acp = acp; - return (AACOK); - } - return (AACERR); - } - static void - aac_sync_fib_slot_release(struct aac_softstate *softs, struct aac_cmd *acp) - { - ASSERT(acp->slotp); - - aac_release_slot(softs, acp->slotp); - acp->slotp->acp = NULL; - acp->slotp = NULL; - - cv_signal(&softs->sync_fib_cv); - } - - static void aac_start_io(struct aac_softstate *softs, struct aac_cmd *acp) { struct aac_slot *slotp = acp->slotp; int q = AAC_CMDQ(acp); int rval; --- 5855,5883 ---- aac_bind_io(struct aac_softstate *softs, struct aac_cmd *acp) { struct aac_device *dvp = acp->dvp; int q = AAC_CMDQ(acp); if (dvp) { if (dvp->ncmds[q] < dvp->throttle[q]) { if (!(acp->flags & AAC_CMD_NTAG) || dvp->ncmds[q] == 0) { + do_bind: return (aac_cmd_slot_bind(softs, acp)); } ASSERT(q == AAC_CMDQ_ASYNC); aac_set_throttle(softs, dvp, AAC_CMDQ_ASYNC, AAC_THROTTLE_DRAIN); } } else { ! if (softs->bus_ncmds[q] < softs->bus_throttle[q]) ! goto do_bind; } return (AACERR); } static void aac_start_io(struct aac_softstate *softs, struct aac_cmd *acp) { struct aac_slot *slotp = acp->slotp; int q = AAC_CMDQ(acp); int rval;
*** 5947,5960 **** if (acp->dvp) acp->dvp->ncmds[q]++; softs->bus_ncmds[q]++; aac_cmd_enqueue(&softs->q_busy, acp); - AACDB_PRINT_FIB(softs, slotp); ! if (softs->flags & AAC_FLAGS_NEW_COMM) { ! rval = aac_send_command(softs, slotp); } else { /* * If fib can not be enqueued, the adapter is in an abnormal * state, there will be no interrupt to us. */ --- 5893,5909 ---- if (acp->dvp) acp->dvp->ncmds[q]++; softs->bus_ncmds[q]++; aac_cmd_enqueue(&softs->q_busy, acp); ! if (softs->flags & AAC_FLAGS_SYNC_MODE) { ! uint32_t wait = 0; ! rval = aac_sync_mbcommand(softs, AAC_MONKER_SYNCFIB, ! slotp->fib_phyaddr, 0, 0, 0, &wait, NULL); ! } else if (softs->flags & AAC_FLAGS_NEW_COMM) { ! rval = AAC_SEND_COMMAND(softs, slotp); } else { /* * If fib can not be enqueued, the adapter is in an abnormal * state, there will be no interrupt to us. */
*** 5961,5971 **** rval = aac_fib_enqueue(softs, AAC_ADAP_NORM_CMD_Q, slotp->fib_phyaddr, acp->fib_size); } if (aac_check_dma_handle(slotp->fib_dma_handle) != DDI_SUCCESS) ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); /* * NOTE: We send command only when slots availabe, so should never * reach here. */ --- 5910,5920 ---- rval = aac_fib_enqueue(softs, AAC_ADAP_NORM_CMD_Q, slotp->fib_phyaddr, acp->fib_size); } if (aac_check_dma_handle(slotp->fib_dma_handle) != DDI_SUCCESS) ! aac_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); /* * NOTE: We send command only when slots availabe, so should never * reach here. */
*** 6031,6077 **** * Consistent packets need to be sync'ed first */ if ((acp->flags & AAC_CMD_CONSISTENT) && (acp->flags & AAC_CMD_BUF_READ)) { if (aac_dma_sync_ac(acp) != AACOK) { ! ddi_fm_service_impact( softs->devinfo_p, DDI_SERVICE_UNAFFECTED); pkt->pkt_reason = CMD_TRAN_ERR; pkt->pkt_statistics = 0; } } if ((aac_check_acc_handle(softs-> \ comm_space_acc_handle) != DDI_SUCCESS) || (aac_check_acc_handle(softs-> \ ! pci_mem_handle) != DDI_SUCCESS)) { ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); ! ddi_fm_acc_err_clear(softs-> \ ! pci_mem_handle, DDI_FME_VER0); pkt->pkt_reason = CMD_TRAN_ERR; pkt->pkt_statistics = 0; } if (aac_check_dma_handle(softs-> \ comm_space_dma_handle) != DDI_SUCCESS) { ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); pkt->pkt_reason = CMD_TRAN_ERR; pkt->pkt_statistics = 0; } } ! scsi_hba_pkt_comp(pkt); } else { break; } } } static int aac_alloc_fib(struct aac_softstate *softs, struct aac_slot *slotp) { ! size_t rlen; ddi_dma_cookie_t cookie; uint_t cookien; /* Allocate FIB dma resource */ if (ddi_dma_alloc_handle( --- 5980,6026 ---- * Consistent packets need to be sync'ed first */ if ((acp->flags & AAC_CMD_CONSISTENT) && (acp->flags & AAC_CMD_BUF_READ)) { if (aac_dma_sync_ac(acp) != AACOK) { ! aac_fm_service_impact( softs->devinfo_p, DDI_SERVICE_UNAFFECTED); pkt->pkt_reason = CMD_TRAN_ERR; pkt->pkt_statistics = 0; } } if ((aac_check_acc_handle(softs-> \ comm_space_acc_handle) != DDI_SUCCESS) || (aac_check_acc_handle(softs-> \ ! pci_mem_handle[0]) != DDI_SUCCESS)) { ! aac_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); ! aac_fm_acc_err_clear(softs-> \ ! pci_mem_handle[0], DDI_FME_VER0); pkt->pkt_reason = CMD_TRAN_ERR; pkt->pkt_statistics = 0; } if (aac_check_dma_handle(softs-> \ comm_space_dma_handle) != DDI_SUCCESS) { ! aac_fm_service_impact(softs->devinfo_p, DDI_SERVICE_UNAFFECTED); pkt->pkt_reason = CMD_TRAN_ERR; pkt->pkt_statistics = 0; } } ! (*pkt->pkt_comp)(pkt); } else { break; } } } static int aac_alloc_fib(struct aac_softstate *softs, struct aac_slot *slotp) { ! size_t rlen, maxsize; ddi_dma_cookie_t cookie; uint_t cookien; /* Allocate FIB dma resource */ if (ddi_dma_alloc_handle(
*** 6082,6095 **** &slotp->fib_dma_handle) != DDI_SUCCESS) { AACDB_PRINT(softs, CE_WARN, "Cannot alloc dma handle for slot fib area"); goto error; } if (ddi_dma_mem_alloc( slotp->fib_dma_handle, ! softs->aac_max_fib_size, ! &softs->acc_attr, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, (caddr_t *)&slotp->fibp, &rlen, --- 6031,6051 ---- &slotp->fib_dma_handle) != DDI_SUCCESS) { AACDB_PRINT(softs, CE_WARN, "Cannot alloc dma handle for slot fib area"); goto error; } + + if (softs->flags & AAC_FLAGS_NEW_COMM_TYPE1) + maxsize = softs->aac_max_fib_size + sizeof(struct aac_fib_xporthdr) + 31; + else if (softs->flags & AAC_FLAGS_NEW_COMM_TYPE2) + maxsize = softs->aac_max_fib_size + 31; + else + maxsize = softs->aac_max_fib_size; if (ddi_dma_mem_alloc( slotp->fib_dma_handle, ! maxsize, ! &aac_acc_attr, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, (caddr_t *)&slotp->fibp, &rlen,
*** 6100,6110 **** } if (ddi_dma_addr_bind_handle( slotp->fib_dma_handle, NULL, (caddr_t)slotp->fibp, ! softs->aac_max_fib_size, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &cookie, &cookien) != DDI_DMA_MAPPED) { --- 6056,6066 ---- } if (ddi_dma_addr_bind_handle( slotp->fib_dma_handle, NULL, (caddr_t)slotp->fibp, ! maxsize, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &cookie, &cookien) != DDI_DMA_MAPPED) {
*** 6113,6133 **** goto error; } /* Check dma handles allocated in fib attach */ if (aac_check_dma_handle(slotp->fib_dma_handle) != DDI_SUCCESS) { ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); goto error; } /* Check acc handles allocated in fib attach */ if (aac_check_acc_handle(slotp->fib_acc_handle) != DDI_SUCCESS) { ! ddi_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); goto error; } slotp->fib_phyaddr = cookie.dmac_laddress; return (AACOK); error: if (slotp->fib_acc_handle) { ddi_dma_mem_free(&slotp->fib_acc_handle); --- 6069,6104 ---- goto error; } /* Check dma handles allocated in fib attach */ if (aac_check_dma_handle(slotp->fib_dma_handle) != DDI_SUCCESS) { ! aac_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); goto error; } /* Check acc handles allocated in fib attach */ if (aac_check_acc_handle(slotp->fib_acc_handle) != DDI_SUCCESS) { ! aac_fm_service_impact(softs->devinfo_p, DDI_SERVICE_LOST); goto error; } slotp->fib_phyaddr = cookie.dmac_laddress; + if (softs->flags & AAC_FLAGS_NEW_COMM_TYPE1) { + uint64_t fibphys_aligned; + fibphys_aligned = + (slotp->fib_phyaddr + sizeof(struct aac_fib_xporthdr) + 31) & ~31; + slotp->fibp = (struct aac_fib *) + ((uint8_t *)slotp->fibp + (fibphys_aligned - slotp->fib_phyaddr)); + slotp->fib_phyaddr = fibphys_aligned; + } else if (softs->flags & AAC_FLAGS_NEW_COMM_TYPE2) { + uint64_t fibphys_aligned; + fibphys_aligned = + (slotp->fib_phyaddr + 31) & ~31; + slotp->fibp = (struct aac_fib *) + ((uint8_t *)slotp->fibp + (fibphys_aligned - slotp->fib_phyaddr)); + slotp->fib_phyaddr = fibphys_aligned; + } return (AACOK); error: if (slotp->fib_acc_handle) { ddi_dma_mem_free(&slotp->fib_acc_handle);
*** 6167,6176 **** --- 6138,6148 ---- /* Insert the slot to the free slot list */ aac_release_slot(softs, slotp); softs->total_fibs++; } + aac_alloc_fib(softs, softs->sync_slot); } static void aac_destroy_fibs(struct aac_softstate *softs) {
*** 6182,6221 **** aac_free_fib(slotp); ASSERT(slotp->index == (slotp - softs->io_slot)); softs->total_fibs--; } ASSERT(softs->total_fibs == 0); } static int aac_create_slots(struct aac_softstate *softs) { int i; softs->total_slots = softs->aac_max_fibs; softs->io_slot = kmem_zalloc(sizeof (struct aac_slot) * \ ! softs->total_slots, KM_SLEEP); if (softs->io_slot == NULL) { AACDB_PRINT(softs, CE_WARN, "Cannot allocate slot"); return (AACERR); } for (i = 0; i < softs->total_slots; i++) softs->io_slot[i].index = i; softs->free_io_slot_head = NULL; softs->total_fibs = 0; return (AACOK); } static void aac_destroy_slots(struct aac_softstate *softs) { ASSERT(softs->free_io_slot_head == NULL); kmem_free(softs->io_slot, sizeof (struct aac_slot) * \ ! softs->total_slots); softs->io_slot = NULL; softs->total_slots = 0; } struct aac_slot * aac_get_slot(struct aac_softstate *softs) { --- 6154,6200 ---- aac_free_fib(slotp); ASSERT(slotp->index == (slotp - softs->io_slot)); softs->total_fibs--; } ASSERT(softs->total_fibs == 0); + aac_free_fib(softs->sync_slot); } static int aac_create_slots(struct aac_softstate *softs) { int i; softs->total_slots = softs->aac_max_fibs; + /* FIXME: patch max. outstanding commands */ + if (softs->total_slots > 1) + softs->total_slots -= 1; + softs->io_slot = kmem_zalloc(sizeof (struct aac_slot) * \ ! (softs->total_slots + 1), KM_SLEEP); if (softs->io_slot == NULL) { AACDB_PRINT(softs, CE_WARN, "Cannot allocate slot"); return (AACERR); } for (i = 0; i < softs->total_slots; i++) softs->io_slot[i].index = i; softs->free_io_slot_head = NULL; softs->total_fibs = 0; + softs->sync_slot = &softs->io_slot[softs->total_slots]; return (AACOK); } static void aac_destroy_slots(struct aac_softstate *softs) { ASSERT(softs->free_io_slot_head == NULL); kmem_free(softs->io_slot, sizeof (struct aac_slot) * \ ! (softs->total_slots + 1)); softs->io_slot = NULL; softs->total_slots = 0; + softs->sync_slot = NULL; } struct aac_slot * aac_get_slot(struct aac_softstate *softs) {
*** 6269,6280 **** int (*intr_handler)(struct aac_softstate *); /* * Interrupt is disabled, we have to poll the adapter by ourselves. */ ! intr_handler = (softs->flags & AAC_FLAGS_NEW_COMM) ? ! aac_process_intr_new : aac_process_intr_old; while (!(acp->flags & (AAC_CMD_CMPLT | AAC_CMD_ABORT))) { int i = AAC_POLL_TIME * 1000; AAC_BUSYWAIT((intr_handler(softs) != AAC_DB_RESPONSE_READY), i); if (i == 0) --- 6248,6265 ---- int (*intr_handler)(struct aac_softstate *); /* * Interrupt is disabled, we have to poll the adapter by ourselves. */ ! if ((softs->flags & AAC_FLAGS_NEW_COMM_TYPE1) || ! (softs->flags & AAC_FLAGS_NEW_COMM_TYPE2) || ! (softs->flags & AAC_FLAGS_NEW_COMM_TYPE34)) ! intr_handler = aac_process_intr_new_type1; ! else if (softs->flags & AAC_FLAGS_NEW_COMM) ! intr_handler = aac_process_intr_new; ! else ! intr_handler = aac_process_intr_old; while (!(acp->flags & (AAC_CMD_CMPLT | AAC_CMD_ABORT))) { int i = AAC_POLL_TIME * 1000; AAC_BUSYWAIT((intr_handler(softs) != AAC_DB_RESPONSE_READY), i); if (i == 0)
*** 6302,6445 **** } static int aac_dma_sync_ac(struct aac_cmd *acp) { ! if (acp->buf_dma_handle) { if (acp->flags & AAC_CMD_BUF_WRITE) { ! if (acp->abp != NULL) ! ddi_rep_put8(acp->abh, ! (uint8_t *)acp->bp->b_un.b_addr, ! (uint8_t *)acp->abp, acp->bp->b_bcount, DDI_DEV_AUTOINCR); ! (void) ddi_dma_sync(acp->buf_dma_handle, 0, 0, ! DDI_DMA_SYNC_FORDEV); } else { ! (void) ddi_dma_sync(acp->buf_dma_handle, 0, 0, ! DDI_DMA_SYNC_FORCPU); ! if (aac_check_dma_handle(acp->buf_dma_handle) != ! DDI_SUCCESS) ! return (AACERR); ! if (acp->abp != NULL) ! ddi_rep_get8(acp->abh, ! (uint8_t *)acp->bp->b_un.b_addr, ! (uint8_t *)acp->abp, acp->bp->b_bcount, DDI_DEV_AUTOINCR); } } ! return (AACOK); ! } ! ! /* ! * Copy AIF from adapter to the empty AIF slot and inform AIF threads ! */ ! static void ! aac_save_aif(struct aac_softstate *softs, ddi_acc_handle_t acc, ! struct aac_fib *fibp0, int fib_size0) ! { ! struct aac_fib *fibp; /* FIB in AIF queue */ ! int fib_size; ! uint16_t fib_command; ! int current, next; ! ! /* Ignore non AIF messages */ ! fib_command = ddi_get16(acc, &fibp0->Header.Command); ! if (fib_command != AifRequest) { ! cmn_err(CE_WARN, "!Unknown command from controller"); ! return; } - - mutex_enter(&softs->aifq_mutex); - - /* Save AIF */ - fibp = &softs->aifq[softs->aifq_idx].d; - fib_size = (fib_size0 > AAC_FIB_SIZE) ? AAC_FIB_SIZE : fib_size0; - ddi_rep_get8(acc, (uint8_t *)fibp, (uint8_t *)fibp0, fib_size, - DDI_DEV_AUTOINCR); - - if (aac_check_acc_handle(softs->pci_mem_handle) != DDI_SUCCESS) { - ddi_fm_service_impact(softs->devinfo_p, - DDI_SERVICE_UNAFFECTED); - mutex_exit(&softs->aifq_mutex); - return; - } - - AACDB_PRINT_AIF(softs, (struct aac_aif_command *)&fibp->data[0]); - - /* Modify AIF contexts */ - current = softs->aifq_idx; - next = (current + 1) % AAC_AIFQ_LENGTH; - if (next == 0) { - struct aac_fib_context *ctx_p; - - softs->aifq_wrap = 1; - for (ctx_p = softs->fibctx_p; ctx_p; ctx_p = ctx_p->next) { - if (next == ctx_p->ctx_idx) { - ctx_p->ctx_flags |= AAC_CTXFLAG_FILLED; - } else if (current == ctx_p->ctx_idx && - (ctx_p->ctx_flags & AAC_CTXFLAG_FILLED)) { - ctx_p->ctx_idx = next; - ctx_p->ctx_overrun++; - } - } - } - softs->aifq_idx = next; - - /* Wakeup AIF threads */ - cv_broadcast(&softs->aifq_cv); - mutex_exit(&softs->aifq_mutex); - - /* Wakeup event thread to handle aif */ - aac_event_disp(softs, AAC_EVENT_AIF); - } - - static int - aac_return_aif_common(struct aac_softstate *softs, struct aac_fib_context *ctx, - struct aac_fib **fibpp) - { - int current; - - current = ctx->ctx_idx; - if (current == softs->aifq_idx && - !(ctx->ctx_flags & AAC_CTXFLAG_FILLED)) - return (EAGAIN); /* Empty */ - - *fibpp = &softs->aifq[current].d; - - ctx->ctx_flags &= ~AAC_CTXFLAG_FILLED; - ctx->ctx_idx = (current + 1) % AAC_AIFQ_LENGTH; - return (0); - } - - int - aac_return_aif(struct aac_softstate *softs, struct aac_fib_context *ctx, - struct aac_fib **fibpp) - { - int rval; - - mutex_enter(&softs->aifq_mutex); - rval = aac_return_aif_common(softs, ctx, fibpp); - mutex_exit(&softs->aifq_mutex); return (rval); } - int - aac_return_aif_wait(struct aac_softstate *softs, struct aac_fib_context *ctx, - struct aac_fib **fibpp) - { - int rval; - - mutex_enter(&softs->aifq_mutex); - rval = aac_return_aif_common(softs, ctx, fibpp); - if (rval == EAGAIN) { - AACDB_PRINT(softs, CE_NOTE, "Waiting for AIF"); - rval = cv_wait_sig(&softs->aifq_cv, &softs->aifq_mutex); - } - mutex_exit(&softs->aifq_mutex); - return ((rval > 0) ? 0 : EINTR); - } - /* * The following function comes from Adaptec: * * When driver sees a particular event that means containers are changed, it * will rescan containers. However a change may not be complete until some --- 6287,6334 ---- } static int aac_dma_sync_ac(struct aac_cmd *acp) { ! uint_t i; ! uint32_t offset; ! int rval = AACOK; ! ! for (i = 0, offset = 0; i < acp->segment_cnt; ++i) { ! if (!acp->segments[i].buf_dma_handle) { ! offset += acp->segments[i].abp_size; ! continue; ! } if (acp->flags & AAC_CMD_BUF_WRITE) { ! if (acp->segments[i].abp != NULL) { ! ddi_rep_put8(acp->segments[i].abh, ! (uint8_t *)acp->bp->b_un.b_addr + offset, ! (uint8_t *)acp->segments[i].abp, ! acp->segments[i].abp_size, DDI_DEV_AUTOINCR); ! } ! (void) ddi_dma_sync(acp->segments[i].buf_dma_handle, ! 0, 0, DDI_DMA_SYNC_FORDEV); } else { ! (void) ddi_dma_sync(acp->segments[i].buf_dma_handle, ! 0, 0, DDI_DMA_SYNC_FORCPU); ! if (aac_check_dma_handle(acp->segments[i].buf_dma_handle) != ! DDI_SUCCESS) { ! rval = AACERR; ! } else if (acp->segments[i].abp != NULL) { ! ddi_rep_get8(acp->segments[i].abh, ! (uint8_t *)acp->bp->b_un.b_addr + offset, ! (uint8_t *)acp->segments[i].abp, ! acp->segments[i].abp_size, DDI_DEV_AUTOINCR); } } ! offset += acp->segments[i].abp_size; } return (rval); } /* * The following function comes from Adaptec: * * When driver sees a particular event that means containers are changed, it * will rescan containers. However a change may not be complete until some
*** 6447,6486 **** * incur as many as six AifEnConfigChange events which would generate six * container rescans. To diminish rescans, driver set a flag to wait for * another particular event. When sees that events come in, it will do rescan. */ static int ! aac_handle_aif(struct aac_softstate *softs, struct aac_aif_command *aif) { ddi_acc_handle_t acc = softs->comm_space_acc_handle; int en_type; int devcfg_needed; ! int cid; ! uint32_t bus_id, tgt_id; ! enum aac_cfg_event event = AAC_CFG_NULL_EXIST; devcfg_needed = 0; en_type = LE_32((uint32_t)aif->data.EN.type); switch (LE_32((uint32_t)aif->command)) { case AifCmdDriverNotify: { ! cid = LE_32(aif->data.EN.data.ECC.container[0]); switch (en_type) { case AifDenMorphComplete: case AifDenVolumeExtendComplete: ! if (AAC_DEV_IS_VALID(&softs->containers[cid].dev)) softs->devcfg_wait_on = AifEnConfigChange; break; } if (softs->devcfg_wait_on == en_type) devcfg_needed = 1; break; } case AifCmdEventNotify: - cid = LE_32(aif->data.EN.data.ECC.container[0]); switch (en_type) { case AifEnAddContainer: case AifEnDeleteContainer: softs->devcfg_wait_on = AifEnConfigChange; break; --- 6336,6385 ---- * incur as many as six AifEnConfigChange events which would generate six * container rescans. To diminish rescans, driver set a flag to wait for * another particular event. When sees that events come in, it will do rescan. */ static int ! aac_handle_aif(struct aac_softstate *softs, struct aac_fib *fibp) { ddi_acc_handle_t acc = softs->comm_space_acc_handle; + uint16_t fib_command; + struct aac_aif_command *aif; int en_type; int devcfg_needed; ! int current, next; + fib_command = LE_16(fibp->Header.Command); + if (fib_command != AifRequest) { + cmn_err(CE_NOTE, "!Unknown command from controller: 0x%x", + fib_command); + return (AACERR); + } + + /* Update internal container state */ + aif = (struct aac_aif_command *)&fibp->data[0]; + + AACDB_PRINT_AIF(softs, aif); devcfg_needed = 0; en_type = LE_32((uint32_t)aif->data.EN.type); switch (LE_32((uint32_t)aif->command)) { case AifCmdDriverNotify: { ! int cid = LE_32(aif->data.EN.data.ECC.container[0]); switch (en_type) { case AifDenMorphComplete: case AifDenVolumeExtendComplete: ! if (cid < AAC_MAX_LD && softs->containers[cid].dev.valid) softs->devcfg_wait_on = AifEnConfigChange; break; } if (softs->devcfg_wait_on == en_type) devcfg_needed = 1; break; } case AifCmdEventNotify: switch (en_type) { case AifEnAddContainer: case AifEnDeleteContainer: softs->devcfg_wait_on = AifEnConfigChange; break;
*** 6492,6513 **** if (ddi_get32(acc, &aif-> \ data.EN.data.ECE.eventType) == CT_PUP_MISSING_DRIVE) devcfg_needed = 1; break; case AifEnAddJBOD: - if (!(softs->flags & AAC_FLAGS_JBOD)) - return (AACERR); - event = AAC_CFG_ADD; - bus_id = (cid >> 24) & 0xf; - tgt_id = cid & 0xffff; - break; case AifEnDeleteJBOD: ! if (!(softs->flags & AAC_FLAGS_JBOD)) ! return (AACERR); ! event = AAC_CFG_DELETE; ! bus_id = (cid >> 24) & 0xf; ! tgt_id = cid & 0xffff; break; } if (softs->devcfg_wait_on == en_type) devcfg_needed = 1; break; --- 6391,6403 ---- if (ddi_get32(acc, &aif-> \ data.EN.data.ECE.eventType) == CT_PUP_MISSING_DRIVE) devcfg_needed = 1; break; case AifEnAddJBOD: case AifEnDeleteJBOD: ! case AifRawDeviceRemove: ! timeout(aac_config_pd, softs, drv_usectohz(1000)); break; } if (softs->devcfg_wait_on == en_type) devcfg_needed = 1; break;
*** 6529,6844 **** softs->devcfg_wait_on = AifEnContainerChange; } break; } ! if (devcfg_needed) { ! softs->devcfg_wait_on = 0; (void) aac_probe_containers(softs); - } ! if (event != AAC_CFG_NULL_EXIST) { ! ASSERT(en_type == AifEnAddJBOD || en_type == AifEnDeleteJBOD); ! (void) aac_probe_jbod(softs, ! AAC_P2VTGT(softs, bus_id, tgt_id), event); } return (AACOK); } - /* ! * Check and handle AIF events */ static void ! aac_aif_event(struct aac_softstate *softs) { ! struct aac_fib *fibp; ! /*CONSTCOND*/ ! while (1) { ! if (aac_return_aif(softs, &softs->aifctx, &fibp) != 0) ! break; /* No more AIFs to handle, end loop */ ! /* AIF overrun, array create/delete may missed. */ ! if (softs->aifctx.ctx_overrun) { ! softs->aifctx.ctx_overrun = 0; } ! /* AIF received, handle it */ ! struct aac_aif_command *aifp = ! (struct aac_aif_command *)&fibp->data[0]; ! uint32_t aif_command = LE_32((uint32_t)aifp->command); ! ! if (aif_command == AifCmdDriverNotify || ! aif_command == AifCmdEventNotify || ! aif_command == AifCmdJobProgress) ! (void) aac_handle_aif(softs, aifp); } ! } ! ! /* ! * Timeout recovery ! */ ! /*ARGSUSED*/ ! static void ! aac_cmd_timeout(struct aac_softstate *softs, struct aac_cmd *acp) ! { ! #ifdef DEBUG ! acp->fib_flags |= AACDB_FLAGS_FIB_TIMEOUT; ! AACDB_PRINT(softs, CE_WARN, "acp %p timed out", acp); ! AACDB_PRINT_FIB(softs, acp->slotp); #endif /* * Besides the firmware in unhealthy state, an overloaded * adapter may also incur pkt timeout. * There is a chance for an adapter with a slower IOP to take * longer than 60 seconds to process the commands, such as when * to perform IOs. So the adapter is doing a build on a RAID-5 * while being required longer completion times should be * tolerated. */ ! switch (aac_do_reset(softs)) { ! case AAC_IOP_RESET_SUCCEED: ! aac_abort_iocmds(softs, AAC_IOCMD_OUTSTANDING, NULL, CMD_RESET); aac_start_waiting_io(softs); ! break; ! case AAC_IOP_RESET_FAILED: ! /* Abort all waiting cmds when adapter is dead */ ! aac_abort_iocmds(softs, AAC_IOCMD_ALL, NULL, CMD_TIMEOUT); ! break; ! case AAC_IOP_RESET_ABNORMAL: aac_start_waiting_io(softs); } } /* * The following function comes from Adaptec: * * Time sync. command added to synchronize time with firmware every 30 * minutes (required for correct AIF timestamps etc.) */ ! static void aac_sync_tick(struct aac_softstate *softs) { ! ddi_acc_handle_t acc; ! int rval; ! mutex_enter(&softs->time_mutex); ! ASSERT(softs->time_sync <= softs->timebase); ! softs->time_sync = 0; ! mutex_exit(&softs->time_mutex); ! /* Time sync. with firmware every AAC_SYNC_TICK */ ! (void) aac_sync_fib_slot_bind(softs, &softs->sync_ac); ! acc = softs->sync_ac.slotp->fib_acc_handle; ! ddi_put32(acc, (void *)&softs->sync_ac.slotp->fibp->data[0], ! ddi_get_time()); ! rval = aac_sync_fib(softs, SendHostTime, AAC_FIB_SIZEOF(uint32_t)); ! aac_sync_fib_slot_release(softs, &softs->sync_ac); ! mutex_enter(&softs->time_mutex); ! softs->time_sync = softs->timebase; ! if (rval != AACOK) ! /* retry shortly */ ! softs->time_sync += aac_tick << 1; else ! softs->time_sync += AAC_SYNC_TICK; ! mutex_exit(&softs->time_mutex); } /* ! * Timeout checking and handling */ static void ! aac_daemon(struct aac_softstate *softs) { ! int time_out; /* set if timeout happened */ ! int time_adjust; ! uint32_t softs_timebase; ! mutex_enter(&softs->time_mutex); ! ASSERT(softs->time_out <= softs->timebase); ! softs->time_out = 0; ! softs_timebase = softs->timebase; ! mutex_exit(&softs->time_mutex); ! /* Check slots for timeout pkts */ ! time_adjust = 0; ! do { ! struct aac_cmd *acp; ! time_out = 0; ! for (acp = softs->q_busy.q_head; acp; acp = acp->next) { ! if (acp->timeout == 0) ! continue; ! /* ! * If timeout happened, update outstanding cmds ! * to be checked later again. ! */ ! if (time_adjust) { ! acp->timeout += time_adjust; ! continue; ! } ! if (acp->timeout <= softs_timebase) { ! aac_cmd_timeout(softs, acp); ! time_out = 1; ! time_adjust = aac_tick * drv_usectohz(1000000); ! break; /* timeout happened */ ! } else { ! break; /* no timeout */ ! } ! } ! } while (time_out); ! ! mutex_enter(&softs->time_mutex); ! softs->time_out = softs->timebase + aac_tick; ! mutex_exit(&softs->time_mutex); } - /* - * The event thread handles various tasks serially for the other parts of - * the driver, so that they can run fast. - */ static void ! aac_event_thread(struct aac_softstate *softs) { ! int run = 1; ! DBCALLED(softs, 1); ! mutex_enter(&softs->ev_lock); ! while (run) { ! int events; ! ! if ((events = softs->events) == 0) { ! cv_wait(&softs->event_disp_cv, &softs->ev_lock); ! events = softs->events; } - softs->events = 0; - mutex_exit(&softs->ev_lock); ! mutex_enter(&softs->io_lock); ! if ((softs->state & AAC_STATE_RUN) && ! (softs->state & AAC_STATE_DEAD) == 0) { ! if (events & AAC_EVENT_TIMEOUT) ! aac_daemon(softs); ! if (events & AAC_EVENT_SYNCTICK) ! aac_sync_tick(softs); ! if (events & AAC_EVENT_AIF) ! aac_aif_event(softs); ! } else { ! run = 0; ! } ! mutex_exit(&softs->io_lock); ! mutex_enter(&softs->ev_lock); ! } ! cv_signal(&softs->event_wait_cv); ! mutex_exit(&softs->ev_lock); } - /* - * Internal timer. It is only responsbile for time counting and report time - * related events. Events handling is done by aac_event_thread(), so that - * the timer itself could be as precise as possible. - */ static void ! aac_timer(void *arg) { ! struct aac_softstate *softs = arg; ! int events = 0; ! mutex_enter(&softs->time_mutex); ! ! /* If timer is being stopped, exit */ ! if (softs->timeout_id) { ! softs->timeout_id = timeout(aac_timer, (void *)softs, ! (aac_tick * drv_usectohz(1000000))); } else { ! mutex_exit(&softs->time_mutex); ! return; } ! /* Time counting */ ! softs->timebase += aac_tick; ! /* Check time related events */ ! if (softs->time_out && softs->time_out <= softs->timebase) ! events |= AAC_EVENT_TIMEOUT; ! if (softs->time_sync && softs->time_sync <= softs->timebase) ! events |= AAC_EVENT_SYNCTICK; ! ! mutex_exit(&softs->time_mutex); ! ! if (events) ! aac_event_disp(softs, events); } - /* - * Dispatch events to daemon thread for handling - */ static void ! aac_event_disp(struct aac_softstate *softs, int events) { ! mutex_enter(&softs->ev_lock); ! softs->events |= events; ! cv_broadcast(&softs->event_disp_cv); ! mutex_exit(&softs->ev_lock); } - /* - * Architecture dependent functions - */ static int ! aac_rx_get_fwstatus(struct aac_softstate *softs) { ! return (PCI_MEM_GET32(softs, AAC_OMR0)); } static int ! aac_rx_get_mailbox(struct aac_softstate *softs, int mb) { ! return (PCI_MEM_GET32(softs, AAC_RX_MAILBOX + mb * 4)); } static void ! aac_rx_set_mailbox(struct aac_softstate *softs, uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3) { ! PCI_MEM_PUT32(softs, AAC_RX_MAILBOX, cmd); ! PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 4, arg0); ! PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 8, arg1); ! PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 12, arg2); ! PCI_MEM_PUT32(softs, AAC_RX_MAILBOX + 16, arg3); } static int ! aac_rkt_get_fwstatus(struct aac_softstate *softs) { ! return (PCI_MEM_GET32(softs, AAC_OMR0)); } static int ! aac_rkt_get_mailbox(struct aac_softstate *softs, int mb) { ! return (PCI_MEM_GET32(softs, AAC_RKT_MAILBOX + mb *4)); } static void ! aac_rkt_set_mailbox(struct aac_softstate *softs, uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3) { ! PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX, cmd); ! PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 4, arg0); ! PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 8, arg1); ! PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 12, arg2); ! PCI_MEM_PUT32(softs, AAC_RKT_MAILBOX + 16, arg3); } /* * cb_ops functions */ --- 6419,6817 ---- softs->devcfg_wait_on = AifEnContainerChange; } break; } ! if (devcfg_needed) (void) aac_probe_containers(softs); ! /* Modify AIF contexts */ ! current = softs->aifq_idx; ! next = (current + 1) % AAC_AIFQ_LENGTH; ! if (next == 0) { ! struct aac_fib_context *ctx; ! ! softs->aifq_wrap = 1; ! for (ctx = softs->fibctx; ctx; ctx = ctx->next) { ! if (next == ctx->ctx_idx) { ! ctx->ctx_filled = 1; ! } else if (current == ctx->ctx_idx && ctx->ctx_filled) { ! ctx->ctx_idx = next; } + } + } + softs->aifq_idx = next; + + /* Wakeup applications */ + cv_broadcast(&softs->aifv); return (AACOK); } /* ! * Timeout recovery */ static void ! aac_cmd_timeout(struct aac_softstate *softs, struct aac_cmd *acp) { ! int rval; ! /* print timed out command */ ! #ifdef AAC_DEBUG ! { ! struct aac_slot *slotp = acp->slotp; ! ddi_acc_handle_t acc = slotp->fib_acc_handle; ! uint16_t i, cmd, size; ! uint8_t *dataptr; ! uint8_t data[16]; ! uint32_t timeout; ! timeout = acp->timeout - aac_timebase - aac_tick; ! if (acp->ac_comp == aac_ld_complete) { ! AACDB_PRINT(softs, CE_NOTE, ! "Container command timed out, index %d timeout %d flags 0x%x id %d", ! slotp->index, timeout, acp->flags, ! ((struct aac_container *)acp->dvp)->cid); ! } else if (acp->ac_comp == aac_pd_complete) { ! AACDB_PRINT(softs, CE_NOTE, ! "Nondasd command timed out, index %d timeout %d flags 0x%x bus %d tid %d", ! slotp->index, timeout, acp->flags, ! ((struct aac_nondasd *)acp->dvp)->bus, ! ((struct aac_nondasd *)acp->dvp)->tid); ! } else if (acp->ac_comp == aac_ioctl_complete) { ! AACDB_PRINT(softs, CE_NOTE, ! "IOCTL command timed out, index %d timeout %d flags 0x%x", ! slotp->index, timeout, acp->flags); ! } else if (acp->ac_comp == aac_synccache_complete) { ! AACDB_PRINT(softs, CE_NOTE, ! "Flush command timed out, index %d timeout %d flags 0x%x", ! slotp->index, timeout, acp->flags); ! } else if (acp->ac_comp == aac_aifreq_complete) { ! AACDB_PRINT(softs, CE_NOTE, ! "AIF request command timed out, index %d timeout %d flags 0x%x", ! slotp->index, timeout, acp->flags); } + cmd = ddi_get16(acc, &slotp->fibp->Header.Command); + size = acp->fib_size - sizeof(struct aac_fib_header); + AACDB_PRINT(softs, CE_NOTE, "Fib command 0x%x size %d data:", + cmd, size); ! if (size > AAC_FIB_DATASIZE) size = AAC_FIB_DATASIZE; ! dataptr = &slotp->fibp->data[0]; ! while (size) { ! for (i = 0; i < 16; ++i) { ! if (size) { ! data[i] = ddi_get8(acc, dataptr); ! ++dataptr; ! --size; ! } else { ! data[i] = 0; } ! } ! AACDB_PRINT(softs, CE_NOTE, "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", ! data[0], data[1], data[2], data[3], ! data[4], data[5], data[6], data[7], ! data[8], data[9], data[10], data[11], ! data[12], data[13], data[14], data[15]); ! } ! } #endif + /* * Besides the firmware in unhealthy state, an overloaded * adapter may also incur pkt timeout. * There is a chance for an adapter with a slower IOP to take * longer than 60 seconds to process the commands, such as when * to perform IOs. So the adapter is doing a build on a RAID-5 * while being required longer completion times should be * tolerated. */ ! rval = aac_do_reset(softs); ! if (rval == AACOK) { ! aac_abort_iocmds(softs, AAC_IOCMD_OUTSTANDING, NULL, ! CMD_RESET); aac_start_waiting_io(softs); ! } else if (rval == AACOK2) { aac_start_waiting_io(softs); + } else { + /* Abort all waiting cmds when adapter is dead */ + aac_abort_iocmds(softs, AAC_IOCMD_ALL, NULL, + CMD_TIMEOUT); } } /* * The following function comes from Adaptec: * * Time sync. command added to synchronize time with firmware every 30 * minutes (required for correct AIF timestamps etc.) */ ! static int aac_sync_tick(struct aac_softstate *softs) { ! ddi_acc_handle_t acc = softs->sync_slot->fib_acc_handle; ! struct aac_fib *fibp = softs->sync_slot->fibp; ! ddi_put32(acc, (uint32_t *)&fibp->data[0], ddi_get_time()); ! return (aac_sync_fib(softs, SendHostTime, AAC_FIB_SIZEOF(uint32_t))); ! } ! static void ! aac_daemon(void *arg) ! { ! struct aac_softstate *softs = (struct aac_softstate *)arg; ! struct aac_cmd *acp; ! DBCALLED(softs, 2); ! mutex_enter(&softs->io_lock); ! /* Check slot for timeout pkts */ ! aac_timebase += aac_tick; ! for (acp = softs->q_busy.q_head; acp; acp = acp->next) { ! if (acp->timeout) { ! if (acp->timeout <= aac_timebase) { ! aac_cmd_timeout(softs, acp); ! ddi_trigger_softintr(softs->softint_id); ! } ! break; ! } ! } ! ! /* Time sync. with firmware every AAC_SYNC_TICK */ ! if (aac_sync_time <= aac_timebase) { ! aac_sync_time = aac_timebase; ! if (aac_sync_tick(softs) != AACOK) ! aac_sync_time += aac_tick << 1; /* retry shortly */ else ! aac_sync_time += AAC_SYNC_TICK; ! } ! ! if ((softs->state & AAC_STATE_RUN) && (softs->timeout_id != 0)) ! softs->timeout_id = timeout(aac_daemon, (void *)softs, ! (aac_tick * drv_usectohz(1000000))); ! mutex_exit(&softs->io_lock); } /* ! * Architecture dependent functions */ static void ! aac_rx_set_intr(struct aac_softstate *softs, int enable) { ! if (enable) { ! if (softs->flags & AAC_FLAGS_NEW_COMM) ! PCI_MEM_PUT32(softs, 0, AAC_OIMR, ~AAC_DB_INTR_NEW); ! else ! PCI_MEM_PUT32(softs, 0, AAC_OIMR, ~AAC_DB_INTR_BITS); ! } else { ! PCI_MEM_PUT32(softs, 0, AAC_OIMR, ~0); ! } ! } ! static void ! aac_rx_status_clr(struct aac_softstate *softs, int mask) ! { ! PCI_MEM_PUT32(softs, 0, AAC_ODBR, mask); ! } ! static int ! aac_rx_status_get(struct aac_softstate *softs) ! { ! return (PCI_MEM_GET32(softs, 0, AAC_ODBR)); ! } ! static void ! aac_rx_notify(struct aac_softstate *softs, int val) ! { ! PCI_MEM_PUT32(softs, 0, AAC_IDBR, val); ! } ! static int ! aac_rx_get_fwstatus(struct aac_softstate *softs) ! { ! return (PCI_MEM_GET32(softs, 0, AAC_OMR0)); ! } ! static int ! aac_rx_get_mailbox(struct aac_softstate *softs, int mb) ! { ! return (PCI_MEM_GET32(softs, 0, AAC_RX_MAILBOX + mb * 4)); } static void ! aac_rx_set_mailbox(struct aac_softstate *softs, uint32_t cmd, ! uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3) { ! PCI_MEM_PUT32(softs, 0, AAC_RX_MAILBOX, cmd); ! PCI_MEM_PUT32(softs, 0, AAC_RX_MAILBOX + 4, arg0); ! PCI_MEM_PUT32(softs, 0, AAC_RX_MAILBOX + 8, arg1); ! PCI_MEM_PUT32(softs, 0, AAC_RX_MAILBOX + 12, arg2); ! PCI_MEM_PUT32(softs, 0, AAC_RX_MAILBOX + 16, arg3); ! } ! static int ! aac_rx_send_command(struct aac_softstate *softs, struct aac_slot *slotp) ! { ! uint32_t index, device; ! index = PCI_MEM_GET32(softs, 0, AAC_IQUE); ! if (index == 0xffffffffUL) { ! index = PCI_MEM_GET32(softs, 0, AAC_IQUE); ! if (index == 0xffffffffUL) ! return (AACERR); } ! device = index; ! PCI_MEM_PUT32(softs, 0, device, ! (uint32_t)(slotp->fib_phyaddr & 0xfffffffful)); ! device += 4; ! PCI_MEM_PUT32(softs, 0, device, (uint32_t)(slotp->fib_phyaddr >> 32)); ! device += 4; ! PCI_MEM_PUT32(softs, 0, device, slotp->acp->fib_size); ! PCI_MEM_PUT32(softs, 0, AAC_IQUE, index); ! return (AACOK); ! } ! static int ! aac_rkt_get_fwstatus(struct aac_softstate *softs) ! { ! return (PCI_MEM_GET32(softs, 0, AAC_OMR0)); ! } ! static int ! aac_rkt_get_mailbox(struct aac_softstate *softs, int mb) ! { ! return (PCI_MEM_GET32(softs, 0, AAC_RKT_MAILBOX + mb *4)); } static void ! aac_rkt_set_mailbox(struct aac_softstate *softs, uint32_t cmd, ! uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3) { ! PCI_MEM_PUT32(softs, 0, AAC_RKT_MAILBOX, cmd); ! PCI_MEM_PUT32(softs, 0, AAC_RKT_MAILBOX + 4, arg0); ! PCI_MEM_PUT32(softs, 0, AAC_RKT_MAILBOX + 8, arg1); ! PCI_MEM_PUT32(softs, 0, AAC_RKT_MAILBOX + 12, arg2); ! PCI_MEM_PUT32(softs, 0, AAC_RKT_MAILBOX + 16, arg3); ! } ! static void ! aac_src_set_intr(struct aac_softstate *softs, int enable) ! { ! if (enable) { ! PCI_MEM_PUT32(softs, 0, AAC_SRC_OIMR, ~AAC_DB_INTR_NEW_TYPE1); } else { ! PCI_MEM_PUT32(softs, 0, AAC_SRC_OIMR, ~0); } + } ! static void ! aac_src_status_clr(struct aac_softstate *softs, int mask) ! { ! PCI_MEM_PUT32(softs, 0, AAC_SRC_ODBR_C, mask << AAC_SRC_ODR_SHIFT); ! } ! static int ! aac_src_status_get(struct aac_softstate *softs) ! { ! return (PCI_MEM_GET32(softs, 0, AAC_SRC_ODBR_R) >> AAC_SRC_ODR_SHIFT); } static void ! aac_src_notify(struct aac_softstate *softs, int val) { ! PCI_MEM_PUT32(softs, 0, AAC_SRC_IDBR, val << AAC_SRC_IDR_SHIFT); } static int ! aac_src_get_fwstatus(struct aac_softstate *softs) { ! return (PCI_MEM_GET32(softs, 0, AAC_SRC_OMR)); } static int ! aac_src_get_mailbox(struct aac_softstate *softs, int mb) { ! return (PCI_MEM_GET32(softs, 0, AAC_SRC_MAILBOX + mb *4)); } static void ! aac_src_set_mailbox(struct aac_softstate *softs, uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3) { ! PCI_MEM_PUT32(softs, 0, AAC_SRC_MAILBOX, cmd); ! PCI_MEM_PUT32(softs, 0, AAC_SRC_MAILBOX + 4, arg0); ! PCI_MEM_PUT32(softs, 0, AAC_SRC_MAILBOX + 8, arg1); ! PCI_MEM_PUT32(softs, 0, AAC_SRC_MAILBOX + 12, arg2); ! PCI_MEM_PUT32(softs, 0, AAC_SRC_MAILBOX + 16, arg3); } static int ! aac_src_send_command(struct aac_softstate *softs, struct aac_slot *slotp) { ! ddi_acc_handle_t acc = slotp->fib_acc_handle; ! uint32_t fibsize, hdr_size, high_addr; ! uint64_t address; ! ! hdr_size = (uint32_t)ddi_get16(acc, &slotp->fibp->Header.Size); ! if (softs->flags & AAC_FLAGS_NEW_COMM_TYPE2) { ! struct aac_fib *fibp = slotp->fibp; ! ! /* Calculate the amount to the fibsize bits */ ! fibsize = (hdr_size + 127) / 128 - 1; ! /* New FIB header */ ! address = slotp->fib_phyaddr; ! high_addr = (uint32_t)(address >> 32); ! if (high_addr == 0L) { ! ddi_put8(acc, &fibp->Header.StructType, AAC_FIBTYPE_TFIB2); ! ddi_put32(acc, &fibp->Header.a.TimeStamp, 0L); ! } else { ! ddi_put8(acc, &fibp->Header.StructType, AAC_FIBTYPE_TFIB2_64); ! ddi_put32(acc, &fibp->Header.a.SenderFibAddressHigh, high_addr); ! } ! ddi_put32(acc, &fibp->Header.SenderFibAddress, (uint32_t)address); ! } else { ! struct aac_fib_xporthdr *pFibX; ! ! /* Calculate the amount to the fibsize bits */ ! fibsize = (sizeof(struct aac_fib_xporthdr) + hdr_size + 127) / 128 - 1; ! /* Fill XPORT header */ ! address = slotp->fib_phyaddr - sizeof(struct aac_fib_xporthdr); ! high_addr = (uint32_t)(address >> 32); ! pFibX = (struct aac_fib_xporthdr *) ! ((unsigned char *)slotp->fibp - sizeof(struct aac_fib_xporthdr)); ! ddi_put32(acc, &pFibX->Handle, slotp->index + 1); ! ddi_put64(acc, &pFibX->HostAddress, slotp->fib_phyaddr); ! ddi_put32(acc, &pFibX->Size, hdr_size); ! } ! ! if (fibsize > 31) ! fibsize = 31; ! if (high_addr) { ! PCI_MEM_PUT32(softs, 0, AAC_SRC_IQUE64_H, high_addr); ! PCI_MEM_PUT32(softs, 0, AAC_SRC_IQUE64_L, (uint32_t)address + fibsize); ! } else { ! PCI_MEM_PUT32(softs, 0, AAC_SRC_IQUE32, (uint32_t)address + fibsize); ! } ! return (AACOK); } static int ! aac_srcv_get_mailbox(struct aac_softstate *softs, int mb) { ! return (PCI_MEM_GET32(softs, 0, AAC_SRCV_MAILBOX + mb *4)); } static void ! aac_srcv_set_mailbox(struct aac_softstate *softs, uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, uint32_t arg3) { ! PCI_MEM_PUT32(softs, 0, AAC_SRCV_MAILBOX, cmd); ! PCI_MEM_PUT32(softs, 0, AAC_SRCV_MAILBOX + 4, arg0); ! PCI_MEM_PUT32(softs, 0, AAC_SRCV_MAILBOX + 8, arg1); ! PCI_MEM_PUT32(softs, 0, AAC_SRCV_MAILBOX + 12, arg2); ! PCI_MEM_PUT32(softs, 0, AAC_SRCV_MAILBOX + 16, arg3); } /* * cb_ops functions */
*** 6921,6930 **** --- 6894,6918 ---- return (aac_do_ioctl(softs, dev, cmd, arg, flag)); } return (ENXIO); } + static int + aac_atoi(char **pptr) + { + char *ptr = *pptr; + int digit, rval = 0; + + while (*ptr >= '0' && *ptr <= '9') { + digit = (int)(*ptr - '0'); + rval = rval*10 + digit; + ptr++; + } + *pptr = ptr; + return (rval); + } + /* * The IO fault service error handling callback function */ /*ARGSUSED*/ static int
*** 6948,6968 **** /* * Need to change iblock to priority for new MSI intr */ ddi_iblock_cookie_t fm_ibc; softs->fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, softs->devinfo_p, DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable", DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE); /* Only register with IO Fault Services if we have some capability */ if (softs->fm_capabilities) { /* Adjust access and dma attributes for FMA */ ! softs->reg_attr.devacc_attr_access = DDI_FLAGERR_ACC; ! softs->addr_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR; ! softs->buf_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR; /* * Register capabilities with IO Fault Services. * fm_capabilities will be updated to indicate * capabilities actually supported (not requested.) --- 6936,6962 ---- /* * Need to change iblock to priority for new MSI intr */ ddi_iblock_cookie_t fm_ibc; + if (!aac_fm_valid) + return; + + /* + * Initialize FMA + */ softs->fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, softs->devinfo_p, DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable", DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE); /* Only register with IO Fault Services if we have some capability */ if (softs->fm_capabilities) { /* Adjust access and dma attributes for FMA */ ! aac_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC; ! softs->buf_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; ! softs->addr_dma_attr.dma_attr_flags = DDI_DMA_FLAGERR; /* * Register capabilities with IO Fault Services. * fm_capabilities will be updated to indicate * capabilities actually supported (not requested.)
*** 6983,6992 **** --- 6977,6991 ---- */ if (DDI_FM_ERRCB_CAP(softs->fm_capabilities)) { ddi_fm_handler_register(softs->devinfo_p, aac_fm_error_cb, (void *) softs); } + } else { + /* Clear FMA if no capabilities */ + aac_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC; + softs->buf_dma_attr.dma_attr_flags = 0; + softs->addr_dma_attr.dma_attr_flags = 0; } } /* * aac_fm_fini - Releases fma capabilities and un-registers with IO
*** 6993,7002 **** --- 6992,7004 ---- * fault services. */ static void aac_fm_fini(struct aac_softstate *softs) { + if (!aac_fm_valid) + return; + /* Only unregister FMA capabilities if registered */ if (softs->fm_capabilities) { /* * Un-register error callback if error callback capable. */
*** 7012,7059 **** pci_ereport_teardown(softs->devinfo_p); } /* Unregister from IO Fault Services */ ddi_fm_fini(softs->devinfo_p); - - /* Adjust access and dma attributes for FMA */ - softs->reg_attr.devacc_attr_access = DDI_DEFAULT_ACC; - softs->addr_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; - softs->buf_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR; } } int aac_check_acc_handle(ddi_acc_handle_t handle) { ddi_fm_error_t de; ddi_fm_acc_err_get(handle, &de, DDI_FME_VERSION); return (de.fme_status); } int aac_check_dma_handle(ddi_dma_handle_t handle) { ddi_fm_error_t de; ddi_fm_dma_err_get(handle, &de, DDI_FME_VERSION); return (de.fme_status); } void ! aac_fm_ereport(struct aac_softstate *softs, char *detail) { uint64_t ena; char buf[FM_MAX_CLASS]; (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail); ena = fm_ena_generate(0, FM_ENA_FMT1); if (DDI_FM_EREPORT_CAP(softs->fm_capabilities)) { ddi_fm_ereport_post(softs->devinfo_p, buf, ena, DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERSION, NULL); } } /* * Autoconfiguration support */ --- 7014,7066 ---- pci_ereport_teardown(softs->devinfo_p); } /* Unregister from IO Fault Services */ ddi_fm_fini(softs->devinfo_p); } } int aac_check_acc_handle(ddi_acc_handle_t handle) { ddi_fm_error_t de; + if (!aac_fm_valid) + return (DDI_SUCCESS); + ddi_fm_acc_err_get(handle, &de, DDI_FME_VERSION); return (de.fme_status); } int aac_check_dma_handle(ddi_dma_handle_t handle) { ddi_fm_error_t de; + if (!aac_fm_valid) + return (DDI_SUCCESS); + ddi_fm_dma_err_get(handle, &de, DDI_FME_VERSION); return (de.fme_status); } void ! aac_fm_ereport(struct aac_softstate *softs, char *detail, int impact) { uint64_t ena; char buf[FM_MAX_CLASS]; + if (!aac_fm_valid) + return; + (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail); ena = fm_ena_generate(0, FM_ENA_FMT1); if (DDI_FM_EREPORT_CAP(softs->fm_capabilities)) { ddi_fm_ereport_post(softs->devinfo_p, buf, ena, DDI_NOSLEEP, FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERSION, NULL); } + ddi_fm_service_impact(softs->devinfo_p, impact); } /* * Autoconfiguration support */
*** 7098,7145 **** } return (AACOK); } static dev_info_t * ! aac_find_child(struct aac_softstate *softs, uint16_t tgt, uint8_t lun) { - dev_info_t *child = NULL; char addr[SCSI_MAXNAMELEN]; ! char tmp[MAXNAMELEN]; if (tgt < AAC_MAX_LD) { - if (lun == 0) { struct aac_device *dvp = &softs->containers[tgt].dev; ! child = dvp->dip; ! } } else { (void) sprintf(addr, "%x,%x", tgt, lun); for (child = ddi_get_child(softs->devinfo_p); child; child = ddi_get_next_sibling(child)) { ! /* We don't care about non-persistent node */ ! if (ndi_dev_is_persistent_node(child) == 0) ! continue; ! ! if (aac_name_node(child, tmp, MAXNAMELEN) != ! DDI_SUCCESS) ! continue; ! if (strcmp(addr, tmp) == 0) ! break; } } ! return (child); } static int aac_config_child(struct aac_softstate *softs, struct scsi_device *sd, dev_info_t **dipp) { char *nodename = NULL; char **compatible = NULL; int ncompatible = 0; - char *childname; dev_info_t *ldip = NULL; int tgt = sd->sd_address.a_target; int lun = sd->sd_address.a_lun; int dtype = sd->sd_inq->inq_dtype & DTYPE_MASK; int rval; --- 7105,7144 ---- } return (AACOK); } static dev_info_t * ! aac_find_child(struct aac_softstate *softs, int tgt, int lun) { char addr[SCSI_MAXNAMELEN]; ! dev_info_t *child; ! char *tmp; if (tgt < AAC_MAX_LD) { struct aac_device *dvp = &softs->containers[tgt].dev; ! if (lun == 0 && dvp->valid) ! return (dvp->dip); } else { (void) sprintf(addr, "%x,%x", tgt, lun); for (child = ddi_get_child(softs->devinfo_p); child; child = ddi_get_next_sibling(child)) { ! if ((tmp = ddi_get_name_addr(child)) != NULL && ! strcmp(addr, tmp) == 0) ! return (child); } } ! return (NULL); } static int aac_config_child(struct aac_softstate *softs, struct scsi_device *sd, dev_info_t **dipp) { char *nodename = NULL; char **compatible = NULL; int ncompatible = 0; dev_info_t *ldip = NULL; int tgt = sd->sd_address.a_target; int lun = sd->sd_address.a_lun; int dtype = sd->sd_inq->inq_dtype & DTYPE_MASK; int rval;
*** 7148,7165 **** scsi_hba_nodename_compatible_get(sd->sd_inq, NULL, dtype, NULL, &nodename, &compatible, &ncompatible); if (nodename == NULL) { AACDB_PRINT(softs, CE_WARN, ! "found no comptible driver for t%dL%d", tgt, lun); rval = NDI_FAILURE; goto finish; } ! childname = (softs->legacy && dtype == DTYPE_DIRECT) ? "sd" : nodename; /* Create dev node */ ! rval = ndi_devi_alloc(softs->devinfo_p, childname, DEVI_SID_NODEID, &ldip); if (rval == NDI_SUCCESS) { if (ndi_prop_update_int(DDI_DEV_T_NONE, ldip, "target", tgt) != DDI_PROP_SUCCESS) { AACDB_PRINT(softs, CE_WARN, "unable to create " --- 7147,7165 ---- scsi_hba_nodename_compatible_get(sd->sd_inq, NULL, dtype, NULL, &nodename, &compatible, &ncompatible); if (nodename == NULL) { AACDB_PRINT(softs, CE_WARN, ! "found no compatible driver for t%dL%d", tgt, lun); rval = NDI_FAILURE; goto finish; } ! if (softs->legacy && dtype == DTYPE_DIRECT) ! nodename = "sd"; /* Create dev node */ ! rval = ndi_devi_alloc(softs->devinfo_p, nodename, DEVI_SID_NODEID, &ldip); if (rval == NDI_SUCCESS) { if (ndi_prop_update_int(DDI_DEV_T_NONE, ldip, "target", tgt) != DDI_PROP_SUCCESS) { AACDB_PRINT(softs, CE_WARN, "unable to create "
*** 7192,7203 **** } } finish: if (dipp) *dipp = ldip; - - scsi_hba_nodename_compatible_free(nodename, compatible); return (rval); } /*ARGSUSED*/ static int --- 7192,7201 ----
*** 7206,7268 **** int tgt = sd->sd_address.a_target; int lun = sd->sd_address.a_lun; DBCALLED(softs, 2); ! if (tgt < AAC_MAX_LD) { ! enum aac_cfg_event event; ! ! if (lun == 0) { ! mutex_enter(&softs->io_lock); ! event = aac_probe_container(softs, tgt); ! mutex_exit(&softs->io_lock); ! if ((event != AAC_CFG_NULL_NOEXIST) && ! (event != AAC_CFG_DELETE)) { ! if (scsi_hba_probe(sd, NULL) == ! SCSIPROBE_EXISTS) ! return (NDI_SUCCESS); ! } ! } return (NDI_FAILURE); - } else { - int dtype; - int qual; /* device qualifier */ if (scsi_hba_probe(sd, NULL) != SCSIPROBE_EXISTS) return (NDI_FAILURE); - dtype = sd->sd_inq->inq_dtype & DTYPE_MASK; - qual = dtype >> 5; - AACDB_PRINT(softs, CE_NOTE, "Phys. device found: tgt %d dtype %d: %s", tgt, dtype, sd->sd_inq->inq_vid); ! /* Only non-DASD and JBOD mode DASD are allowed exposed */ ! if (dtype == DTYPE_RODIRECT /* CDROM */ || ! dtype == DTYPE_SEQUENTIAL /* TAPE */ || ! dtype == DTYPE_ESI /* SES */) { ! if (!(softs->flags & AAC_FLAGS_NONDASD)) return (NDI_FAILURE); ! AACDB_PRINT(softs, CE_NOTE, "non-DASD %d found", tgt); ! ! } else if (dtype == DTYPE_DIRECT) { ! if (!(softs->flags & AAC_FLAGS_JBOD) || qual != 0) ! return (NDI_FAILURE); ! AACDB_PRINT(softs, CE_NOTE, "JBOD DASD %d found", tgt); } - - mutex_enter(&softs->io_lock); - softs->nondasds[AAC_PD(tgt)].dev.flags |= AAC_DFLAG_VALID; - mutex_exit(&softs->io_lock); return (NDI_SUCCESS); - } } static int ! aac_config_lun(struct aac_softstate *softs, uint16_t tgt, uint8_t lun, ! dev_info_t **ldip) { struct scsi_device sd; dev_info_t *child; int rval; --- 7204,7239 ---- int tgt = sd->sd_address.a_target; int lun = sd->sd_address.a_lun; DBCALLED(softs, 2); ! if (tgt < AAC_MAX_LD && lun != 0) return (NDI_FAILURE); if (scsi_hba_probe(sd, NULL) != SCSIPROBE_EXISTS) return (NDI_FAILURE); + if (tgt >= AAC_MAX_LD) { + int dtype = sd->sd_inq->inq_dtype & DTYPE_MASK; AACDB_PRINT(softs, CE_NOTE, "Phys. device found: tgt %d dtype %d: %s", tgt, dtype, sd->sd_inq->inq_vid); ! /* Only non-DASD and JBOD devices exposed */ ! if (dtype != DTYPE_RODIRECT /* CDROM */ && ! dtype != DTYPE_SEQUENTIAL /* TYPE */ && ! dtype != DTYPE_ESI /* SES */ && ! !(dtype == DTYPE_DIRECT && ! (softs->aac_feature_bits & AAC_SUPPL_SUPPORTED_JBOD))) return (NDI_FAILURE); ! AACDB_PRINT(softs, CE_NOTE, "non-DASD/JBOD %d found", tgt); } return (NDI_SUCCESS); } static int ! aac_config_lun(struct aac_softstate *softs, int tgt, int lun, dev_info_t **ldip) { struct scsi_device sd; dev_info_t *child; int rval;
*** 7278,7317 **** sd.sd_address.a_hba_tran = softs->hba_tran; sd.sd_address.a_target = (uint16_t)tgt; sd.sd_address.a_lun = (uint8_t)lun; if ((rval = aac_probe_lun(softs, &sd)) == NDI_SUCCESS) rval = aac_config_child(softs, &sd, ldip); ! /* scsi_unprobe is blank now. Free buffer manually */ ! if (sd.sd_inq) { ! kmem_free(sd.sd_inq, SUN_INQSIZE); ! sd.sd_inq = (struct scsi_inquiry *)NULL; ! } return (rval); } static int aac_config_tgt(struct aac_softstate *softs, int tgt) { struct scsi_address ap; struct buf *bp = NULL; ! int buf_len = AAC_SCSI_RPTLUNS_HEAD_SIZE + AAC_SCSI_RPTLUNS_ADDR_SIZE; ! int list_len = 0; int lun_total = 0; dev_info_t *ldip; ! int i; ap.a_hba_tran = softs->hba_tran; ap.a_target = (uint16_t)tgt; ap.a_lun = 0; for (i = 0; i < 2; i++) { struct scsi_pkt *pkt; uchar_t *cdb; uchar_t *p; uint32_t data; if (bp == NULL) { if ((bp = scsi_alloc_consistent_buf(&ap, NULL, buf_len, B_READ, NULL_FUNC, NULL)) == NULL) return (AACERR); } if ((pkt = scsi_init_pkt(&ap, NULL, bp, CDB_GROUP5, --- 7249,7285 ---- sd.sd_address.a_hba_tran = softs->hba_tran; sd.sd_address.a_target = (uint16_t)tgt; sd.sd_address.a_lun = (uint8_t)lun; if ((rval = aac_probe_lun(softs, &sd)) == NDI_SUCCESS) rval = aac_config_child(softs, &sd, ldip); ! scsi_unprobe(&sd); return (rval); } static int aac_config_tgt(struct aac_softstate *softs, int tgt) { struct scsi_address ap; struct buf *bp = NULL; ! int list_len = 8; int lun_total = 0; dev_info_t *ldip; ! int i, cmd_ok = 1; ap.a_hba_tran = softs->hba_tran; ap.a_target = (uint16_t)tgt; ap.a_lun = 0; for (i = 0; i < 2; i++) { struct scsi_pkt *pkt; uchar_t *cdb; uchar_t *p; + int buf_len; uint32_t data; if (bp == NULL) { + buf_len = AAC_SCSI_RPTLUNS_HEAD_SIZE + list_len; if ((bp = scsi_alloc_consistent_buf(&ap, NULL, buf_len, B_READ, NULL_FUNC, NULL)) == NULL) return (AACERR); } if ((pkt = scsi_init_pkt(&ap, NULL, bp, CDB_GROUP5,
*** 7332,7389 **** } if (scsi_poll(pkt) < 0 || ((struct scsi_status *)pkt->pkt_scbp)->sts_chk) { scsi_destroy_pkt(pkt); break; } /* Convert list_len from LE_32 to local */ for (p = (uchar_t *)bp->b_un.b_addr; p < (uchar_t *)bp->b_un.b_addr + 4; p++) { data <<= 8; data |= *p; } list_len = data; - if (buf_len < list_len + AAC_SCSI_RPTLUNS_HEAD_SIZE) { scsi_free_consistent_buf(bp); bp = NULL; - buf_len = list_len + AAC_SCSI_RPTLUNS_HEAD_SIZE; } - scsi_destroy_pkt(pkt); } - if (i >= 2) { - uint8_t *buf = (uint8_t *)(bp->b_un.b_addr + - AAC_SCSI_RPTLUNS_HEAD_SIZE); for (i = 0; i < (list_len / AAC_SCSI_RPTLUNS_ADDR_SIZE); i++) { ! uint16_t lun; /* Determine report luns addressing type */ ! switch (buf[0] & AAC_SCSI_RPTLUNS_ADDR_MASK) { /* * Vendors in the field have been found to be * concatenating bus/target/lun to equal the * complete lun value instead of switching to * flat space addressing */ case AAC_SCSI_RPTLUNS_ADDR_PERIPHERAL: case AAC_SCSI_RPTLUNS_ADDR_LOGICAL_UNIT: case AAC_SCSI_RPTLUNS_ADDR_FLAT_SPACE: ! lun = ((buf[0] & 0x3f) << 8) | buf[1]; ! if (lun > UINT8_MAX) { ! AACDB_PRINT(softs, CE_WARN, ! "abnormal lun number: %d", lun); ! break; ! } if (aac_config_lun(softs, tgt, lun, &ldip) == NDI_SUCCESS) lun_total++; break; } - - buf += AAC_SCSI_RPTLUNS_ADDR_SIZE; } } else { /* The target may do not support SCMD_REPORT_LUNS. */ if (aac_config_lun(softs, tgt, 0, &ldip) == NDI_SUCCESS) lun_total++; --- 7300,7354 ---- } if (scsi_poll(pkt) < 0 || ((struct scsi_status *)pkt->pkt_scbp)->sts_chk) { scsi_destroy_pkt(pkt); + cmd_ok = 0; break; } + scsi_destroy_pkt(pkt); /* Convert list_len from LE_32 to local */ for (p = (uchar_t *)bp->b_un.b_addr; p < (uchar_t *)bp->b_un.b_addr + 4; p++) { data <<= 8; data |= *p; } + + if (data <= list_len) + break; + if (i == 0) { list_len = data; scsi_free_consistent_buf(bp); bp = NULL; } } + if (cmd_ok) { + char *buf = bp->b_un.b_addr + 8; + for (i = 0; i < (list_len / AAC_SCSI_RPTLUNS_ADDR_SIZE); i++) { ! int lun; /* Determine report luns addressing type */ ! switch (buf[i] & AAC_SCSI_RPTLUNS_ADDR_MASK) { /* * Vendors in the field have been found to be * concatenating bus/target/lun to equal the * complete lun value instead of switching to * flat space addressing */ case AAC_SCSI_RPTLUNS_ADDR_PERIPHERAL: case AAC_SCSI_RPTLUNS_ADDR_LOGICAL_UNIT: case AAC_SCSI_RPTLUNS_ADDR_FLAT_SPACE: ! lun = (buf[i] & 0x3f) << 8; ! lun |= buf[i + 1]; if (aac_config_lun(softs, tgt, lun, &ldip) == NDI_SUCCESS) lun_total++; break; } } } else { /* The target may do not support SCMD_REPORT_LUNS. */ if (aac_config_lun(softs, tgt, 0, &ldip) == NDI_SUCCESS) lun_total++;
*** 7391,7413 **** scsi_free_consistent_buf(bp); return (lun_total); } static void ! aac_devcfg(struct aac_softstate *softs, int tgt, int en) { ! struct aac_device *dvp; ! mutex_enter(&softs->io_lock); ! dvp = AAC_DEV(softs, tgt); ! if (en) ! dvp->flags |= AAC_DFLAG_CONFIGURING; ! else ! dvp->flags &= ~AAC_DFLAG_CONFIGURING; mutex_exit(&softs->io_lock); } static int aac_tran_bus_config(dev_info_t *parent, uint_t flags, ddi_bus_config_op_t op, void *arg, dev_info_t **childp) { struct aac_softstate *softs; --- 7356,7397 ---- scsi_free_consistent_buf(bp); return (lun_total); } static void ! aac_enable_pd(struct aac_softstate *softs, int tgt, int en) { ! if (tgt >= AAC_MAX_LD) { mutex_enter(&softs->io_lock); ! softs->nondasds[AAC_PD(tgt)].dev.valid = (uint8_t)en; mutex_exit(&softs->io_lock); + } } + static void + aac_config_pd(void *arg) + { + struct aac_softstate *softs = (struct aac_softstate *)arg; + uint32_t bus, tgt; + int index, total; + + total = 0; + index = AAC_MAX_LD; + for (bus = 0; bus < softs->bus_max; bus++) { + AACDB_PRINT(softs, CE_NOTE, "bus %d:", bus); + for (tgt = 0; tgt < softs->tgt_max; tgt++, index++) { + aac_enable_pd(softs, index, 1); + if (aac_config_tgt(softs, index) == 0) + aac_enable_pd(softs, index, 0); + else + total++; + } + } + AACDB_PRINT(softs, CE_CONT, + "Total %d phys. device(s) found", total); + } + static int aac_tran_bus_config(dev_info_t *parent, uint_t flags, ddi_bus_config_op_t op, void *arg, dev_info_t **childp) { struct aac_softstate *softs;
*** 7416,7485 **** if ((softs = ddi_get_soft_state(aac_softstatep, ddi_get_instance(parent))) == NULL) return (NDI_FAILURE); - /* Commands for bus config should be blocked as the bus is quiesced */ - mutex_enter(&softs->io_lock); - if (softs->state & AAC_STATE_QUIESCED) { - AACDB_PRINT(softs, CE_NOTE, - "bus_config abroted because bus is quiesced"); - mutex_exit(&softs->io_lock); - return (NDI_FAILURE); - } - mutex_exit(&softs->io_lock); - DBCALLED(softs, 1); /* Hold the nexus across the bus_config */ ndi_devi_enter(parent, &circ); switch (op) { case BUS_CONFIG_ONE: { int tgt, lun; if (aac_parse_devname(arg, &tgt, &lun) != AACOK) { rval = NDI_FAILURE; break; } ! if (tgt >= AAC_MAX_LD) { ! if (tgt >= AAC_MAX_DEV(softs)) { ! rval = NDI_FAILURE; break; } - } ! AAC_DEVCFG_BEGIN(softs, tgt); ! rval = aac_config_lun(softs, tgt, lun, childp); ! AAC_DEVCFG_END(softs, tgt); break; } case BUS_CONFIG_DRIVER: case BUS_CONFIG_ALL: { ! uint32_t bus, tgt; ! int index, total; ! for (tgt = 0; tgt < AAC_MAX_LD; tgt++) { ! AAC_DEVCFG_BEGIN(softs, tgt); (void) aac_config_lun(softs, tgt, 0, NULL); - AAC_DEVCFG_END(softs, tgt); - } /* Config the non-DASD devices connected to the card */ ! total = 0; ! index = AAC_MAX_LD; ! for (bus = 0; bus < softs->bus_max; bus++) { ! AACDB_PRINT(softs, CE_NOTE, "bus %d:", bus); ! for (tgt = 0; tgt < softs->tgt_max; tgt++, index++) { ! AAC_DEVCFG_BEGIN(softs, index); ! if (aac_config_tgt(softs, index)) ! total++; ! AAC_DEVCFG_END(softs, index); ! } ! } ! AACDB_PRINT(softs, CE_CONT, ! "?Total %d phys. device(s) found", total); rval = NDI_SUCCESS; break; } } --- 7400,7449 ---- if ((softs = ddi_get_soft_state(aac_softstatep, ddi_get_instance(parent))) == NULL) return (NDI_FAILURE); DBCALLED(softs, 1); /* Hold the nexus across the bus_config */ ndi_devi_enter(parent, &circ); switch (op) { case BUS_CONFIG_ONE: { int tgt, lun; + struct scsi_device sd; if (aac_parse_devname(arg, &tgt, &lun) != AACOK) { rval = NDI_FAILURE; break; } ! if (*childp = aac_find_child(softs, tgt, lun)) { ! rval = NDI_SUCCESS; break; } ! aac_enable_pd(softs, tgt, 1); ! bzero(&sd, sizeof (struct scsi_device)); ! sd.sd_address.a_hba_tran = softs->hba_tran; ! sd.sd_address.a_target = (uint16_t)tgt; ! sd.sd_address.a_lun = (uint8_t)lun; ! if ((rval = aac_probe_lun(softs, &sd)) == NDI_SUCCESS) ! rval = aac_config_child(softs, &sd, childp); ! else ! aac_enable_pd(softs, tgt, 0); ! scsi_unprobe(&sd); break; } case BUS_CONFIG_DRIVER: case BUS_CONFIG_ALL: { ! uint32_t tgt; ! for (tgt = 0; tgt < AAC_MAX_LD; tgt++) (void) aac_config_lun(softs, tgt, 0, NULL); /* Config the non-DASD devices connected to the card */ ! aac_config_pd((void *)softs); rval = NDI_SUCCESS; break; } }
*** 7487,7544 **** rval = ndi_busop_bus_config(parent, flags, op, arg, childp, 0); ndi_devi_exit(parent, circ); return (rval); } ! /*ARGSUSED*/ ! static int ! aac_handle_dr(struct aac_softstate *softs, int tgt, int lun, int event) { struct aac_device *dvp; dev_info_t *dip; int valid; int circ1 = 0; DBCALLED(softs, 1); /* Hold the nexus across the bus_config */ ! dvp = AAC_DEV(softs, tgt); ! valid = AAC_DEV_IS_VALID(dvp); dip = dvp->dip; ! if (!(softs->state & AAC_STATE_RUN)) ! return (AACERR); mutex_exit(&softs->io_lock); ! switch (event) { ! case AAC_CFG_ADD: ! case AAC_CFG_DELETE: /* Device onlined */ if (dip == NULL && valid) { ndi_devi_enter(softs->devinfo_p, &circ1); ! (void) aac_config_lun(softs, tgt, 0, NULL); AACDB_PRINT(softs, CE_NOTE, "c%dt%dL%d onlined", ! softs->instance, tgt, lun); ndi_devi_exit(softs->devinfo_p, circ1); } /* Device offlined */ ! if (dip && !valid) { mutex_enter(&softs->io_lock); (void) aac_do_reset(softs); mutex_exit(&softs->io_lock); (void) ndi_devi_offline(dip, NDI_DEVI_REMOVE); AACDB_PRINT(softs, CE_NOTE, "c%dt%dL%d offlined", ! softs->instance, tgt, lun); } break; } ! mutex_enter(&softs->io_lock); return (AACOK); } ! #ifdef DEBUG /* -------------------------debug aid functions-------------------------- */ #define AAC_FIB_CMD_KEY_STRINGS \ TestCommandResponse, "TestCommandResponse", \ --- 7451,7529 ---- rval = ndi_busop_bus_config(parent, flags, op, arg, childp, 0); ndi_devi_exit(parent, circ); return (rval); } ! static void ! aac_handle_dr(struct aac_drinfo *drp) { + struct aac_softstate *softs = drp->softs; struct aac_device *dvp; dev_info_t *dip; int valid; int circ1 = 0; DBCALLED(softs, 1); /* Hold the nexus across the bus_config */ ! mutex_enter(&softs->io_lock); ! dvp = AAC_DEV(softs, drp->tgt); dip = dvp->dip; ! valid = dvp->valid; mutex_exit(&softs->io_lock); ! switch (drp->event) { ! case AAC_DEV_ONLINE: ! case AAC_DEV_OFFLINE: /* Device onlined */ if (dip == NULL && valid) { ndi_devi_enter(softs->devinfo_p, &circ1); ! (void) aac_config_lun(softs, drp->tgt, 0, NULL); AACDB_PRINT(softs, CE_NOTE, "c%dt%dL%d onlined", ! softs->instance, drp->tgt, drp->lun); ndi_devi_exit(softs->devinfo_p, circ1); } /* Device offlined */ ! if (dip && valid == 0) { mutex_enter(&softs->io_lock); (void) aac_do_reset(softs); mutex_exit(&softs->io_lock); (void) ndi_devi_offline(dip, NDI_DEVI_REMOVE); AACDB_PRINT(softs, CE_NOTE, "c%dt%dL%d offlined", ! softs->instance, drp->tgt, drp->lun); } break; } + kmem_free(drp, sizeof (struct aac_drinfo)); + } ! static int ! aac_dr_event(struct aac_softstate *softs, int tgt, int lun, int event) ! { ! struct aac_drinfo *drp; ! ! DBCALLED(softs, 1); ! ! if (softs->taskq == NULL || ! (drp = kmem_zalloc(sizeof (struct aac_drinfo), KM_NOSLEEP)) == NULL) ! return (AACERR); ! ! drp->softs = softs; ! drp->tgt = tgt; ! drp->lun = lun; ! drp->event = event; ! if ((ddi_taskq_dispatch(softs->taskq, (void (*)(void *))aac_handle_dr, ! drp, DDI_NOSLEEP)) != DDI_SUCCESS) { ! AACDB_PRINT(softs, CE_WARN, "DR task start failed"); ! kmem_free(drp, sizeof (struct aac_drinfo)); ! return (AACERR); ! } return (AACOK); } ! #ifdef AAC_DEBUG_ALL /* -------------------------debug aid functions-------------------------- */ #define AAC_FIB_CMD_KEY_STRINGS \ TestCommandResponse, "TestCommandResponse", \
*** 7978,8007 **** static struct aac_key_strings aac_aifens[] = { AAC_AIFEN_KEY_STRINGS, -1, NULL }; /* * The following function comes from Adaptec: * * Get the firmware print buffer parameters from the firmware, * if the command was successful map in the address. */ static int aac_get_fw_debug_buffer(struct aac_softstate *softs) { if (aac_sync_mbcommand(softs, AAC_MONKER_GETDRVPROP, ! 0, 0, 0, 0, NULL) == AACOK) { uint32_t mondrv_buf_paddrl = AAC_MAILBOX_GET(softs, 1); uint32_t mondrv_buf_paddrh = AAC_MAILBOX_GET(softs, 2); uint32_t mondrv_buf_size = AAC_MAILBOX_GET(softs, 3); uint32_t mondrv_hdr_size = AAC_MAILBOX_GET(softs, 4); if (mondrv_buf_size) { uint32_t offset = mondrv_buf_paddrl - \ ! softs->pci_mem_base_paddr; /* * See if the address is already mapped in, and * if so set it up from the base address */ --- 7963,7995 ---- static struct aac_key_strings aac_aifens[] = { AAC_AIFEN_KEY_STRINGS, -1, NULL }; + #endif /* AAC_DEBUG_ALL */ + #ifdef AAC_DEBUG /* * The following function comes from Adaptec: * * Get the firmware print buffer parameters from the firmware, * if the command was successful map in the address. */ static int aac_get_fw_debug_buffer(struct aac_softstate *softs) { + softs->sync_slot_busy = 1; if (aac_sync_mbcommand(softs, AAC_MONKER_GETDRVPROP, ! 0, 0, 0, 0, NULL, NULL) == AACOK) { uint32_t mondrv_buf_paddrl = AAC_MAILBOX_GET(softs, 1); uint32_t mondrv_buf_paddrh = AAC_MAILBOX_GET(softs, 2); uint32_t mondrv_buf_size = AAC_MAILBOX_GET(softs, 3); uint32_t mondrv_hdr_size = AAC_MAILBOX_GET(softs, 4); if (mondrv_buf_size) { uint32_t offset = mondrv_buf_paddrl - \ ! softs->pci_mem_base_paddr[1]; /* * See if the address is already mapped in, and * if so set it up from the base address */
*** 8010,8020 **** mutex_enter(&aac_prt_mutex); softs->debug_buf_offset = offset; softs->debug_header_size = mondrv_hdr_size; softs->debug_buf_size = mondrv_buf_size; softs->debug_fw_flags = 0; - softs->debug_flags &= ~AACDB_FLAGS_FW_PRINT; mutex_exit(&aac_prt_mutex); return (AACOK); } } --- 7998,8007 ----
*** 8094,8104 **** /* * Wait for no more than AAC_PRINT_TIMEOUT for the * previous message length to clear (the handshake). */ for (i = 0; i < AAC_PRINT_TIMEOUT; i++) { ! if (!PCI_MEM_GET32(softs, softs->debug_buf_offset + \ AAC_FW_DBG_STRLEN_OFFSET)) break; drv_usecwait(1000); --- 8081,8091 ---- /* * Wait for no more than AAC_PRINT_TIMEOUT for the * previous message length to clear (the handshake). */ for (i = 0; i < AAC_PRINT_TIMEOUT; i++) { ! if (!PCI_MEM_GET32(softs, 1, softs->debug_buf_offset + \ AAC_FW_DBG_STRLEN_OFFSET)) break; drv_usecwait(1000);
*** 8108,8128 **** * If the length is clear, copy over the message, the * flags, and the length. Make sure the length is the * last because that is the signal for the Firmware to * pick it up. */ ! if (!PCI_MEM_GET32(softs, softs->debug_buf_offset + \ AAC_FW_DBG_STRLEN_OFFSET)) { ! PCI_MEM_REP_PUT8(softs, softs->debug_buf_offset + \ softs->debug_header_size, aac_prt_buf, count); ! PCI_MEM_PUT32(softs, softs->debug_buf_offset + \ AAC_FW_DBG_FLAGS_OFFSET, softs->debug_fw_flags); ! PCI_MEM_PUT32(softs, softs->debug_buf_offset + \ AAC_FW_DBG_STRLEN_OFFSET, count); } else { cmn_err(CE_WARN, "UART output fail"); softs->debug_flags &= ~AACDB_FLAGS_FW_PRINT; --- 8095,8115 ---- * If the length is clear, copy over the message, the * flags, and the length. Make sure the length is the * last because that is the signal for the Firmware to * pick it up. */ ! if (!PCI_MEM_GET32(softs, 1, softs->debug_buf_offset + \ AAC_FW_DBG_STRLEN_OFFSET)) { ! PCI_MEM_REP_PUT8(softs, 1, softs->debug_buf_offset + \ softs->debug_header_size, aac_prt_buf, count); ! PCI_MEM_PUT32(softs, 1, softs->debug_buf_offset + \ AAC_FW_DBG_FLAGS_OFFSET, softs->debug_fw_flags); ! PCI_MEM_PUT32(softs, 1, softs->debug_buf_offset + \ AAC_FW_DBG_STRLEN_OFFSET, count); } else { cmn_err(CE_WARN, "UART output fail"); softs->debug_flags &= ~AACDB_FLAGS_FW_PRINT;
*** 8141,8151 **** --- 8128,8140 ---- if (aac_debug_flags & AACDB_FLAGS_KERNEL_PRINT) aac_cmn_err(softs, lev, sl, 1); } mutex_exit(&aac_prt_mutex); } + #endif /* AAC_DEBUG */ + #ifdef AAC_DEBUG_ALL /* * Translate command number to description string */ static char * aac_cmd_name(int cmd, struct aac_key_strings *cmdlist)
*** 8166,8176 **** struct scsi_address *ap = &pkt->pkt_address; int is_pd = 0; int ctl = ddi_get_instance(softs->devinfo_p); int tgt = ap->a_target; int lun = ap->a_lun; ! union scsi_cdb *cdbp = (void *)pkt->pkt_cdbp; uchar_t cmd = cdbp->scc_cmd; char *desc; if (tgt >= AAC_MAX_LD) { is_pd = 1; --- 8155,8165 ---- struct scsi_address *ap = &pkt->pkt_address; int is_pd = 0; int ctl = ddi_get_instance(softs->devinfo_p); int tgt = ap->a_target; int lun = ap->a_lun; ! union scsi_cdb *cdbp = (union scsi_cdb *)pkt->pkt_cdbp; uchar_t cmd = cdbp->scc_cmd; char *desc; if (tgt >= AAC_MAX_LD) { is_pd = 1;
*** 8211,8432 **** desc, GETG4ADDR(cdbp), GETG4ADDRTL(cdbp), GETG4COUNT(cdbp), (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr", ctl, tgt, lun, is_pd ? "(pd)" : ""); break; - case SCMD_READ_G5: - case SCMD_WRITE_G5: - aac_printf(softs, CE_NOTE, - "SCMD> %s 0x%x[%d] %s --> c%dt%dL%d %s", - desc, GETG5ADDR(cdbp), GETG5COUNT(cdbp), - (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr", - ctl, tgt, lun, is_pd ? "(pd)" : ""); - break; default: aac_printf(softs, CE_NOTE, "SCMD> %s --> c%dt%dL%d %s", desc, ctl, tgt, lun, is_pd ? "(pd)" : ""); } } void ! aac_print_fib(struct aac_softstate *softs, struct aac_slot *slotp) { - struct aac_cmd *acp = slotp->acp; - struct aac_fib *fibp = slotp->fibp; - ddi_acc_handle_t acc = slotp->fib_acc_handle; uint16_t fib_size; ! uint32_t fib_cmd, sub_cmd; char *cmdstr, *subcmdstr; ! char *caller; ! int i; ! if (acp) { ! if (!(softs->debug_fib_flags & acp->fib_flags)) ! return; ! if (acp->fib_flags & AACDB_FLAGS_FIB_SCMD) ! caller = "SCMD"; ! else if (acp->fib_flags & AACDB_FLAGS_FIB_IOCTL) ! caller = "IOCTL"; ! else if (acp->fib_flags & AACDB_FLAGS_FIB_SRB) ! caller = "SRB"; ! else ! return; ! } else { ! if (!(softs->debug_fib_flags & AACDB_FLAGS_FIB_SYNC)) ! return; ! caller = "SYNC"; ! } ! ! fib_cmd = ddi_get16(acc, &fibp->Header.Command); cmdstr = aac_cmd_name(fib_cmd, aac_fib_cmds); ! sub_cmd = (uint32_t)-1; subcmdstr = NULL; - /* Print FIB header */ - if (softs->debug_fib_flags & AACDB_FLAGS_FIB_HEADER) { - aac_printf(softs, CE_NOTE, "FIB> from %s", caller); - aac_printf(softs, CE_NOTE, " XferState %d", - ddi_get32(acc, &fibp->Header.XferState)); - aac_printf(softs, CE_NOTE, " Command %d", - ddi_get16(acc, &fibp->Header.Command)); - aac_printf(softs, CE_NOTE, " StructType %d", - ddi_get8(acc, &fibp->Header.StructType)); - aac_printf(softs, CE_NOTE, " Flags 0x%x", - ddi_get8(acc, &fibp->Header.Flags)); - aac_printf(softs, CE_NOTE, " Size %d", - ddi_get16(acc, &fibp->Header.Size)); - aac_printf(softs, CE_NOTE, " SenderSize %d", - ddi_get16(acc, &fibp->Header.SenderSize)); - aac_printf(softs, CE_NOTE, " SenderAddr 0x%x", - ddi_get32(acc, &fibp->Header.SenderFibAddress)); - aac_printf(softs, CE_NOTE, " RcvrAddr 0x%x", - ddi_get32(acc, &fibp->Header.ReceiverFibAddress)); - aac_printf(softs, CE_NOTE, " SenderData 0x%x", - ddi_get32(acc, &fibp->Header.SenderData)); - } - - /* Print FIB data */ switch (fib_cmd) { case ContainerCommand: ! sub_cmd = ddi_get32(acc, ! (void *)&(((uint32_t *)(void *)&fibp->data[0])[0])); subcmdstr = aac_cmd_name(sub_cmd, aac_ctvm_subcmds); if (subcmdstr == NULL) break; - - switch (sub_cmd) { - case VM_ContainerConfig: { - struct aac_Container *pContainer = - (struct aac_Container *)fibp->data; - fib_cmd = sub_cmd; cmdstr = subcmdstr; ! sub_cmd = (uint32_t)-1; subcmdstr = NULL; ! sub_cmd = ddi_get32(acc, ! &pContainer->CTCommand.command); subcmdstr = aac_cmd_name(sub_cmd, aac_ct_subcmds); if (subcmdstr == NULL) break; aac_printf(softs, CE_NOTE, "FIB> %s (0x%x, 0x%x, 0x%x)", subcmdstr, ! ddi_get32(acc, &pContainer->CTCommand.param[0]), ! ddi_get32(acc, &pContainer->CTCommand.param[1]), ! ddi_get32(acc, &pContainer->CTCommand.param[2])); return; - } - case VM_Ioctl: ! fib_cmd = sub_cmd; ! cmdstr = subcmdstr; ! sub_cmd = (uint32_t)-1; ! subcmdstr = NULL; ! ! sub_cmd = ddi_get32(acc, ! (void *)&(((uint32_t *)(void *)&fibp->data[0])[4])); subcmdstr = aac_cmd_name(sub_cmd, aac_ioctl_subcmds); break; - - case VM_CtBlockRead: - case VM_CtBlockWrite: { - struct aac_blockread *br = - (struct aac_blockread *)fibp->data; - struct aac_sg_table *sg = &br->SgMap; - uint32_t sgcount = ddi_get32(acc, &sg->SgCount); - - aac_printf(softs, CE_NOTE, - "FIB> %s Container %d 0x%x/%d", subcmdstr, - ddi_get32(acc, &br->ContainerId), - ddi_get32(acc, &br->BlockNumber), - ddi_get32(acc, &br->ByteCount)); - for (i = 0; i < sgcount; i++) - aac_printf(softs, CE_NOTE, - " %d: 0x%08x/%d", i, - ddi_get32(acc, &sg->SgEntry[i].SgAddress), - ddi_get32(acc, &sg->SgEntry[i]. \ - SgByteCount)); - return; } - } break; - case ContainerCommand64: { - struct aac_blockread64 *br = - (struct aac_blockread64 *)fibp->data; - struct aac_sg_table64 *sg = &br->SgMap64; - uint32_t sgcount = ddi_get32(acc, &sg->SgCount); - uint64_t sgaddr; - - sub_cmd = br->Command; - subcmdstr = NULL; - if (sub_cmd == VM_CtHostRead64) - subcmdstr = "VM_CtHostRead64"; - else if (sub_cmd == VM_CtHostWrite64) - subcmdstr = "VM_CtHostWrite64"; - else - break; - - aac_printf(softs, CE_NOTE, - "FIB> %s Container %d 0x%x/%d", subcmdstr, - ddi_get16(acc, &br->ContainerId), - ddi_get32(acc, &br->BlockNumber), - ddi_get16(acc, &br->SectorCount)); - for (i = 0; i < sgcount; i++) { - sgaddr = ddi_get64(acc, - &sg->SgEntry64[i].SgAddress); - aac_printf(softs, CE_NOTE, - " %d: 0x%08x.%08x/%d", i, - AAC_MS32(sgaddr), AAC_LS32(sgaddr), - ddi_get32(acc, &sg->SgEntry64[i]. \ - SgByteCount)); - } - return; - } - - case RawIo: { - struct aac_raw_io *io = (struct aac_raw_io *)fibp->data; - struct aac_sg_tableraw *sg = &io->SgMapRaw; - uint32_t sgcount = ddi_get32(acc, &sg->SgCount); - uint64_t sgaddr; - - aac_printf(softs, CE_NOTE, - "FIB> RawIo Container %d 0x%llx/%d 0x%x", - ddi_get16(acc, &io->ContainerId), - ddi_get64(acc, &io->BlockNumber), - ddi_get32(acc, &io->ByteCount), - ddi_get16(acc, &io->Flags)); - for (i = 0; i < sgcount; i++) { - sgaddr = ddi_get64(acc, &sg->SgEntryRaw[i].SgAddress); - aac_printf(softs, CE_NOTE, " %d: 0x%08x.%08x/%d", i, - AAC_MS32(sgaddr), AAC_LS32(sgaddr), - ddi_get32(acc, &sg->SgEntryRaw[i].SgByteCount)); - } - return; - } - case ClusterCommand: ! sub_cmd = ddi_get32(acc, ! (void *)&(((uint32_t *)(void *)fibp->data)[0])); subcmdstr = aac_cmd_name(sub_cmd, aac_cl_subcmds); break; case AifRequest: ! sub_cmd = ddi_get32(acc, ! (void *)&(((uint32_t *)(void *)fibp->data)[0])); subcmdstr = aac_cmd_name(sub_cmd, aac_aif_subcmds); break; default: break; } ! fib_size = ddi_get16(acc, &(fibp->Header.Size)); if (subcmdstr) aac_printf(softs, CE_NOTE, "FIB> %s, sz=%d", subcmdstr, fib_size); ! else if (cmdstr && sub_cmd == (uint32_t)-1) aac_printf(softs, CE_NOTE, "FIB> %s, sz=%d", cmdstr, fib_size); else if (cmdstr) aac_printf(softs, CE_NOTE, "FIB> %s: Unknown(0x%x), sz=%d", cmdstr, sub_cmd, fib_size); --- 8200,8278 ---- desc, GETG4ADDR(cdbp), GETG4ADDRTL(cdbp), GETG4COUNT(cdbp), (acp->flags & AAC_CMD_NO_INTR) ? "poll" : "intr", ctl, tgt, lun, is_pd ? "(pd)" : ""); break; default: aac_printf(softs, CE_NOTE, "SCMD> %s --> c%dt%dL%d %s", desc, ctl, tgt, lun, is_pd ? "(pd)" : ""); } } void ! aac_print_fib(struct aac_softstate *softs, struct aac_fib *fibp) { uint16_t fib_size; ! int32_t fib_cmd, sub_cmd; char *cmdstr, *subcmdstr; ! struct aac_Container *pContainer; ! fib_cmd = LE_16(fibp->Header.Command); cmdstr = aac_cmd_name(fib_cmd, aac_fib_cmds); ! sub_cmd = -1; subcmdstr = NULL; switch (fib_cmd) { case ContainerCommand: ! pContainer = (struct aac_Container *)fibp->data; ! sub_cmd = LE_32(pContainer->Command); subcmdstr = aac_cmd_name(sub_cmd, aac_ctvm_subcmds); if (subcmdstr == NULL) break; fib_cmd = sub_cmd; cmdstr = subcmdstr; ! sub_cmd = -1; subcmdstr = NULL; ! switch (pContainer->Command) { ! case VM_ContainerConfig: ! sub_cmd = LE_32(pContainer->CTCommand.command); subcmdstr = aac_cmd_name(sub_cmd, aac_ct_subcmds); if (subcmdstr == NULL) break; aac_printf(softs, CE_NOTE, "FIB> %s (0x%x, 0x%x, 0x%x)", subcmdstr, ! LE_32(pContainer->CTCommand.param[0]), ! LE_32(pContainer->CTCommand.param[1]), ! LE_32(pContainer->CTCommand.param[2])); return; case VM_Ioctl: ! sub_cmd = LE_32(((int32_t *)pContainer)[4]); subcmdstr = aac_cmd_name(sub_cmd, aac_ioctl_subcmds); break; } break; case ClusterCommand: ! sub_cmd = LE_32(((int32_t *)fibp->data)[0]); subcmdstr = aac_cmd_name(sub_cmd, aac_cl_subcmds); break; case AifRequest: ! sub_cmd = LE_32(((int32_t *)fibp->data)[0]); subcmdstr = aac_cmd_name(sub_cmd, aac_aif_subcmds); break; default: break; } ! fib_size = LE_16(fibp->Header.Size); if (subcmdstr) aac_printf(softs, CE_NOTE, "FIB> %s, sz=%d", subcmdstr, fib_size); ! else if (cmdstr && sub_cmd == -1) aac_printf(softs, CE_NOTE, "FIB> %s, sz=%d", cmdstr, fib_size); else if (cmdstr) aac_printf(softs, CE_NOTE, "FIB> %s: Unknown(0x%x), sz=%d", cmdstr, sub_cmd, fib_size);
*** 8495,8501 **** aac_printf(softs, CE_NOTE, "AIF! AIF %d (%d)", aif_command, aif_seqnumber); break; } } ! ! #endif /* DEBUG */ --- 8341,8346 ---- aac_printf(softs, CE_NOTE, "AIF! AIF %d (%d)", aif_command, aif_seqnumber); break; } } ! #endif /* AAC_DEBUG_ALL */