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 */