arcmsr.c revision 508aff1a85ed04f187fd074799bcaefd630490f1
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * O.S : Solaris
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * FILE NAME : arcmsr.c
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * BY : Erich Chen
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Description: SCSI RAID Device Driver for
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * ARECA RAID Host adapter
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Copyright (C) 2002,2007 Areca Technology Corporation All rights reserved.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Copyright (C) 2002,2007 Erich Chen
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Web site: www.areca.com.tw
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * E-mail: erich@areca.com.tw
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Redistribution and use in source and binary forms, with or without
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * modification, are permitted provided that the following conditions
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * are met:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * 1. Redistributions of source code must retain the above copyright
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * notice, this list of conditions and the following disclaimer.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * 2. Redistributions in binary form must reproduce the above copyright
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * notice, this list of conditions and the following disclaimer in the
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * documentation and/or other materials provided with the distribution.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * 3. The party using or redistributing the source code and binary forms
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * agrees to the disclaimer below and the terms and conditions set forth
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * herein.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * SUCH DAMAGE.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Use is subject to license terms.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#include <sys/types.h>
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#include <sys/ddidmareq.h>
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#include <sys/scsi/scsi.h>
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#include <sys/ddi.h>
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#include <sys/sunddi.h>
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#include <sys/file.h>
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#include <sys/disp.h>
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#include <sys/signal.h>
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#include <sys/debug.h>
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#include <sys/pci.h>
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#include <sys/policy.h>
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#include "arcmsr.h"
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int arcmsr_attach(dev_info_t *dev_info, ddi_attach_cmd_t cmd);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int arcmsr_cb_ioctl(dev_t dev, int ioctl_cmd, intptr_t arg,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int mode, cred_t *credp, int *rvalp);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int arcmsr_detach(dev_info_t *dev_info, ddi_detach_cmd_t cmd);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int arcmsr_reset(dev_info_t *resetdev, ddi_reset_cmd_t cmd);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int arcmsr_tran_start(struct scsi_address *ap, struct scsi_pkt *pkt);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int arcmsr_tran_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int arcmsr_tran_reset(struct scsi_address *ap, int level);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int arcmsr_tran_getcap(struct scsi_address *ap, char *cap, int whom);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int arcmsr_tran_setcap(struct scsi_address *ap, char *cap, int value,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int whom);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int arcmsr_tran_tgt_init(dev_info_t *host_dev_info,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dev_info_t *target_dev_info, scsi_hba_tran_t *hosttran,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct scsi_device *sd);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void arcmsr_tran_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void arcmsr_tran_destroy_pkt(struct scsi_address *ap,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct scsi_pkt *pkt);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void arcmsr_tran_sync_pkt(struct scsi_address *ap,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct scsi_pkt *pkt);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic struct scsi_pkt *arcmsr_tran_init_pkt(struct scsi_address *ap,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct scsi_pkt *pkt, struct buf *bp, int cmdlen, int statuslen,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int tgtlen, int flags, int (*callback)(), caddr_t arg);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic uint_t arcmsr_interrupt(caddr_t arg);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int arcmsr_initialize(struct ACB *acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int arcmsr_dma_alloc(struct ACB *acb,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct scsi_pkt *pkt, struct buf *bp, int flags, int (*callback)());
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int arcmsr_dma_move(struct ACB *acb,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct scsi_pkt *pkt, struct buf *bp);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void arcmsr_pcidev_disattach(struct ACB *acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void arcmsr_ccb_complete(struct CCB *ccb, int flag);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void arcmsr_iop_init(struct ACB *acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void arcmsr_iop_parking(struct ACB *acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void arcmsr_log(struct ACB *acb, int level, char *fmt, ...);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic struct CCB *arcmsr_get_freeccb(struct ACB *acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void arcmsr_flush_hba_cache(struct ACB *acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void arcmsr_flush_hbb_cache(struct ACB *acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void arcmsr_stop_hba_bgrb(struct ACB *acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void arcmsr_stop_hbb_bgrb(struct ACB *acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void arcmsr_start_hba_bgrb(struct ACB *acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void arcmsr_start_hba_bgrb(struct ACB *acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void arcmsr_polling_hba_ccbdone(struct ACB *acb, struct CCB *poll_ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void arcmsr_polling_hbb_ccbdone(struct ACB *acb, struct CCB *poll_ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void arcmsr_build_ccb(struct CCB *ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic struct ACB *ArcMSRHBA[ARCMSR_MAX_ADAPTER];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int arcmsr_hba_count;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void *arcmsr_soft_state = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic kmutex_t arcmsr_global_mutex;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic ddi_dma_attr_t arcmsr_dma_attr = {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DMA_ATTR_V0, /* ddi_dma_attr version */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson 0, /* low DMA address range */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson 0xffffffff, /* high DMA address range */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson 0x00ffffff, /* DMA counter counter upper bound */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson 1, /* DMA address alignment requirements */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DEFAULT_BURSTSIZE | BURST32 | BURST64, /* burst sizes */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson 1, /* minimum effective DMA size */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MAX_XFER_LEN, /* maximum DMA xfer size */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * The dma_attr_seg field supplies the limit of each Scatter/Gather
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * list element's "address+length". The Intel IOP331 can not use
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * segments over the 4G boundary due to segment boundary restrictions
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson 0x00ffffff,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MAX_SG_ENTRIES, /* scatter/gather list count */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson 1, /* device granularity */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_DMA_FORCE_PHYSICAL /* Bus specific DMA flags */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson};
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic ddi_dma_attr_t arcmsr_ccb_attr = {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DMA_ATTR_V0, /* ddi_dma_attr version */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson 0, /* low DMA address range */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson 0xffffffff, /* high DMA address range */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson 0x00ffffff, /* DMA counter counter upper bound */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson 1, /* default byte alignment */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DEFAULT_BURSTSIZE | BURST32 | BURST64, /* burst sizes */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson 1, /* minimum effective DMA size */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson 0xffffffff, /* maximum DMA xfer size */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson 0x00ffffff, /* max segment size, segment boundary restrictions */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson 1, /* scatter/gather list count */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson 1, /* device granularity */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_DMA_FORCE_PHYSICAL /* Bus specific DMA flags */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson};
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic struct cb_ops arcmsr_cb_ops = {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson scsi_hba_open, /* open(9E) */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson scsi_hba_close, /* close(9E) */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson nodev, /* strategy(9E), returns ENXIO */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson nodev, /* print(9E) */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson nodev, /* dump(9E) Cannot be used as a dump device */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson nodev, /* read(9E) */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson nodev, /* write(9E) */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_cb_ioctl, /* ioctl(9E) */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson nodev, /* devmap(9E) */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson nodev, /* mmap(9E) */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson nodev, /* segmap(9E) */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson NULL, /* chpoll(9E) returns ENXIO */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson nodev, /* prop_op(9E) */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson NULL, /* streamtab(9S) */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#ifdef _LP64
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * cb_ops cb_flag:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * D_NEW | D_MP compatibility flags, see conf.h
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * D_MP flag indicates that the driver is safe for
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * multi-threaded operation
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * D_64BIT flag driver properly handles 64-bit offsets
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson D_HOTPLUG | D_MP | D_64BIT,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#else
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson D_HOTPLUG | D_MP,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#endif
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CB_REV,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson nodev, /* aread(9E) */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson nodev /* awrite(9E) */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson};
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic struct dev_ops arcmsr_ops = {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DEVO_REV, /* devo_rev */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson 0, /* reference count */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson nodev, /* getinfo */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson nulldev, /* identify */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson nulldev, /* probe */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_attach, /* attach */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_detach, /* detach */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_reset, /* reset, shutdown, reboot notify */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &arcmsr_cb_ops, /* driver operations */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson NULL, /* bus operations */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson nulldev /* power */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson};
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonchar _depends_on[] = "misc/scsi";
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic struct modldrv arcmsr_modldrv = {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &mod_driverops, /* Type of module. This is a driver. */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_DRIVER_VERSION, /* module name, from arcmsr.h */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &arcmsr_ops, /* driver ops */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson};
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic struct modlinkage arcmsr_modlinkage = {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson MODREV_1,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &arcmsr_modldrv,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson NULL
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson};
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonint
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson_init(void) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int ret;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_init(&arcmsr_global_mutex, "arcmsr global mutex",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson MUTEX_DRIVER, NULL);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ret = ddi_soft_state_init(&arcmsr_soft_state,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct ACB), ARCMSR_MAX_ADAPTER);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ret != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (ret);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((ret = scsi_hba_init(&arcmsr_modlinkage)) != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_soft_state_fini(&arcmsr_soft_state);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (ret);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((ret = mod_install(&arcmsr_modlinkage)) != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_destroy(&arcmsr_global_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson scsi_hba_fini(&arcmsr_modlinkage);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (arcmsr_soft_state != NULL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_soft_state_fini(&arcmsr_soft_state);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (ret);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonint
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson_fini(void) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int ret;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ret = mod_remove(&arcmsr_modlinkage);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ret == 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* if ret = 0 , said driver can remove */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_destroy(&arcmsr_global_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson scsi_hba_fini(&arcmsr_modlinkage);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (arcmsr_soft_state != NULL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_soft_state_fini(&arcmsr_soft_state);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (ret);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonint
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson_info(struct modinfo *modinfop) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (mod_info(&arcmsr_modlinkage, modinfop));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#if defined(ARCMSR_DEBUG)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_dump_scsi_cdb(struct scsi_address *ap, struct scsi_pkt *pkt) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson static char hex[] = "0123456789abcdef";
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ACB *acb =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (struct ACB *)ap->a_hba_tran->tran_hba_private;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *ccb =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (struct CCB *)pkt->pkt_ha_private;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t *cdb = pkt->pkt_cdbp;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson char buf [256];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson char *p;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int i;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) sprintf(buf, "arcmsr%d: sgcount=%d <%d, %d> "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "cdb ",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info), ccb->arcmsr_cdb.sgcount,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ap->a_target, ap->a_lun);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson p = buf + strlen(buf);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *p++ = '[';
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson for (i = 0; i < ccb->arcmsr_cdb.CdbLength; i++, cdb++) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (i != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *p++ = ' ';
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *p++ = hex[(*cdb >> 4) & 0x0f];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *p++ = hex[*cdb & 0x0f];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *p++ = ']';
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *p++ = '.';
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *p = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT, buf);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#endif /* ARCMSR_DEBUG */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_ccbs_timeout(void* arg) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ACB *acb = (struct ACB *)arg;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *ccb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int i;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int current_time = ddi_get_time();
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->ccboutstandingcount != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* check each ccb */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson i = ddi_dma_sync(acb->ccbs_pool_handle, 0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->dma_sync_size, DDI_DMA_SYNC_FORKERNEL);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (i != DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((acb->timeout_id != 0) &&
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* do pkt timeout check each 60 secs */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->timeout_id = timeout(arcmsr_ccbs_timeout,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void*)acb,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (60 * drv_usectohz(1000000)));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb = acb->pccb_pool[i];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->acb != acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->startdone == ARCMSR_CCB_DONE) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson continue;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->pkt == NULL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson continue;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->pkt->pkt_time == 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson continue;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((int)ccb->ccb_time >= current_time) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson continue;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->startdone == ARCMSR_CCB_START) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int id = ccb->pkt->pkt_address.a_target;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int lun = ccb->pkt->pkt_address.a_lun;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * handle outstanding command of timeout ccb
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_reason = CMD_TIMEOUT;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_statistics = STAT_TIMEOUT;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: scsi target %d lun %d "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "outstanding command timeout",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info),
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson id, lun);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: scsi target %d lun %d "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "fatal error on target, device is gone",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info),
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson id, lun);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->devstate[id][lun] = ARECA_RAID_GONE;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_ccb_complete(ccb, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson continue;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->ccb_time = (time_t)(ccb->pkt->pkt_time +
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson current_time); /* adjust ccb_time of pending ccb */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((acb->timeout_id != 0) &&
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* do pkt timeout check each 60 secs */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->timeout_id = timeout(arcmsr_ccbs_timeout,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void*)acb, (60 * drv_usectohz(1000000)));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic uint32_t
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_disable_allintr(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t intmask_org;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (acb->adapter_type) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_A: {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* disable all outbound interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* disable outbound message0 int */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson intmask_org = CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->outbound_intmask) |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->outbound_intmask,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_B: {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* disable all outbound interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* disable outbound message0 int */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson intmask_org = CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->iop2drv_doorbell_mask) &
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* disable all interrupts */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->iop2drv_doorbell_mask, 0);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (intmask_org);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_enable_allintr(struct ACB *acb, uint32_t intmask_org) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int mask;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (acb->adapter_type) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_A: {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* enable outbound Post Queue, outbound doorbell Interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->outbound_intmask, intmask_org & mask);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_B: {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* disable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mask = (ARCMSR_IOP2DRV_DATA_WRITE_OK |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_IOP2DRV_DATA_READ_OK | ARCMSR_IOP2DRV_CDB_DONE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* 1=interrupt enable, 0=interrupt disable */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->iop2drv_doorbell_mask,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson intmask_org | mask);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_iop_parking(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb != NULL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* stop adapter background rebuild */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->acb_flags & ACB_F_MSG_START_BGRB) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t intmask_org;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* disable all outbound interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson intmask_org = arcmsr_disable_allintr(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->adapter_type == ACB_ADAPTER_TYPE_A) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_stop_hba_bgrb(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_flush_hba_cache(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_stop_hbb_bgrb(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_flush_hbb_cache(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * enable outbound Post Queue
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * enable outbound doorbell Interrupt
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_enable_allintr(acb, intmask_org);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_reset(dev_info_t *resetdev, ddi_reset_cmd_t cmd) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ACB *acb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson scsi_hba_tran_t *scsi_hba_transport;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson scsi_hba_transport = (scsi_hba_tran_t *)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_driver_private(resetdev);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!scsi_hba_transport)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb = (struct ACB *)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson scsi_hba_transport->tran_hba_private;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!acb)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((cmd == RESET_LUN) ||
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (cmd == RESET_BUS) ||
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (cmd == RESET_TARGET))
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: reset op (%d) not supported",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(resetdev), cmd);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_pcidev_disattach(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_SUCCESS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_do_ddi_attach(dev_info_t *dev_info, int instance) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson scsi_hba_tran_t *hba_trans;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_device_acc_attr_t dev_acc_attr;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ACB *acb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson static char buf[256];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint16_t wval;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int raid6 = 1;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson char *type;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Soft State Structure
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * The driver should allocate the per-device-instance
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * soft state structure, being careful to clean up properly if
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * an error occurs. Allocate data structure.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_soft_state_zalloc(arcmsr_soft_state, instance)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson != DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: ddi_soft_state_zalloc failed",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson instance);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb = ddi_get_soft_state(arcmsr_soft_state, instance);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb == NULL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: ddi_get_soft_state failed",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson instance);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto error_level_1;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* acb is already zalloc()d so we don't need to bzero() it */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dev_acc_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dev_acc_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dev_acc_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->dev_info = dev_info;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->dev_acc_attr = dev_acc_attr;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * The driver, if providing DMA, should also check that its hardware is
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * installed in a DMA-capable slot
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_slaveonly(dev_info) == DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: hardware is not installed in a "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "DMA-capable slot",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson instance);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto error_level_0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* We do not support adapter drivers with high-level interrupts */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_intr_hilevel(dev_info, 0) != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: high-level interrupt not supported",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson instance);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto error_level_0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (pci_config_setup(dev_info, &acb->pci_acc_handle)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson != DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_NOTE,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: pci_config_setup() failed, attach failed",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson instance);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_PROBE_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson wval = pci_config_get16(acb->pci_acc_handle, PCI_CONF_VENID);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (wval != PCI_VENDOR_ID_ARECA) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_NOTE,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: failing attach: 'vendorid (0x%04x) "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "does not match 0x%04x (PCI_VENDOR_ID_ARECA)\n",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson instance, wval, PCI_VENDOR_ID_ARECA);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_PROBE_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson wval = pci_config_get16(acb->pci_acc_handle, PCI_CONF_DEVID);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (wval) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case PCI_DEVICE_ID_ARECA_1110:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case PCI_DEVICE_ID_ARECA_1210:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case PCI_DEVICE_ID_ARECA_1201:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson raid6 = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*FALLTHRU*/
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case PCI_DEVICE_ID_ARECA_1120:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case PCI_DEVICE_ID_ARECA_1130:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case PCI_DEVICE_ID_ARECA_1160:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case PCI_DEVICE_ID_ARECA_1170:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case PCI_DEVICE_ID_ARECA_1220:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case PCI_DEVICE_ID_ARECA_1230:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case PCI_DEVICE_ID_ARECA_1260:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case PCI_DEVICE_ID_ARECA_1270:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case PCI_DEVICE_ID_ARECA_1280:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson type = "SATA";
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case PCI_DEVICE_ID_ARECA_1380:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case PCI_DEVICE_ID_ARECA_1381:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case PCI_DEVICE_ID_ARECA_1680:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case PCI_DEVICE_ID_ARECA_1681:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson type = "SAS";
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson default:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson type = "X-TYPE";
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) sprintf(buf, "Areca %s Host Adapter RAID Controller%s",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson type, raid6 ? " (RAID6 capable)" : "");
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT, "arcmsr%d:%s ", instance, buf);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT, "arcmsr%d:%s ", instance, ARCMSR_DRIVER_VERSION);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* we disable iop interrupt here */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (arcmsr_initialize(acb) == DDI_FAILURE) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_WARN, "arcmsr%d: arcmsr_initialize "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "failed", instance);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto error_level_1;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * The driver must first obtain the iblock cookie to initialize
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * mutexes used in the driver handler. Only after those mutexes
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * have been initialized can the interrupt handler be added.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_get_iblock_cookie(dev_info, 0, &acb->iblock_cookie)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson != DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_WARN, "arcmsr%d: "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "ddi_get_iblock_cookie failed", instance);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto error_level_2;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_init(&acb->acb_mutex, NULL, MUTEX_DRIVER,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void *)acb->iblock_cookie);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_init(&acb->postq_mutex, NULL, MUTEX_DRIVER,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void *)acb->iblock_cookie);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_init(&acb->workingQ_mutex, NULL, MUTEX_DRIVER,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void *)acb->iblock_cookie);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_init(&acb->ioctl_mutex, NULL, MUTEX_DRIVER,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void *)acb->iblock_cookie);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Allocate a transport structure */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans = scsi_hba_tran_alloc(dev_info, SCSI_HBA_CANSLEEP);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (hba_trans == NULL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: scsi_hba_tran_alloc failed",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson instance);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto error_level_3;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->scsi_hba_transport = hba_trans;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->dev_info = dev_info;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* init scsi host adapter transport entry */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_hba_private = acb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_tgt_private = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * If no per-target initialization is required, the HBA can leave
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * tran_tgt_init set to NULL.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_tgt_init = arcmsr_tran_tgt_init;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_tgt_probe = scsi_hba_probe;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_tgt_free = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_start = arcmsr_tran_start;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_abort = arcmsr_tran_abort;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_reset = arcmsr_tran_reset;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_getcap = arcmsr_tran_getcap;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_setcap = arcmsr_tran_setcap;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_init_pkt = arcmsr_tran_init_pkt;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_destroy_pkt = arcmsr_tran_destroy_pkt;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_dmafree = arcmsr_tran_dmafree;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_sync_pkt = arcmsr_tran_sync_pkt;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_reset_notify = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_get_bus_addr = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_get_name = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_quiesce = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_unquiesce = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_bus_reset = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_add_eventcall = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_get_eventcookie = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_post_event = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_remove_eventcall = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Adding an Interrupt Handler */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_add_intr(dev_info, 0, &acb->iblock_cookie, 0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_interrupt, (caddr_t)acb) != DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: failed to add interrupt handler",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson instance);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto error_level_4;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * The driver should attach this instance of the device, and
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * perform error cleanup if necessary
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (scsi_hba_attach_setup(dev_info, &arcmsr_dma_attr,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans, SCSI_HBA_TRAN_CLONE) != DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: scsi_hba_attach_setup failed",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson instance);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto error_level_5;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* iop init and enable interrupt here */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_enter(&arcmsr_global_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop_init(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_exit(&arcmsr_global_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Initialize power management bookkeeping. */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (pm_create_components(dev_info, 1) == DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (pm_idle_component(dev_info, 0) == DDI_FAILURE) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: pm_idle_component fail",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson instance);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto error_level_8;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pm_set_normal_power(dev_info, 0, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* acb->power_level = 1; */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: pm_create_components fail",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson instance);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto error_level_7;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Since this driver manages devices with "remote" hardware, "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * i.e. the devices themselves have no "reg" property, the SUSPEND/
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * RESUME commands in detach/attach will not be called by the power
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * management framework unless we request it by creating a
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * "pm-hardware-state" property and setting it to value
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * "needs-suspend-resume".
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_prop_update_string(DDI_DEV_T_NONE, dev_info,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "pm-hardware-state", "needs-suspend-resume")
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson != DDI_PROP_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: ddi_prop_update(\"pm-hardware-state\")failed",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson instance);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto error_level_8;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* active ccbs "timeout" watchdog */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->timeout_id = timeout(arcmsr_ccbs_timeout, (caddr_t)acb,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (60 * drv_usectohz(1000000)));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* report device info */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_report_dev(dev_info);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ArcMSRHBA[arcmsr_hba_count] = acb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_hba_count++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_SUCCESS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonerror_level_8:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pm_destroy_components(dev_info);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonerror_level_7:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Remove any previously allocated minor nodes */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_remove_minor_node(dev_info, NULL);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonerror_level_6:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson scsi_hba_tran_free(hba_trans);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonerror_level_5:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_remove_intr(dev_info, 0, (void *)acb->iblock_cookie);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonerror_level_4:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson scsi_hba_tran_free(hba_trans);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonerror_level_3:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_destroy(&acb->acb_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_destroy(&acb->postq_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_destroy(&acb->workingQ_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_destroy(&acb->ioctl_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonerror_level_2:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_mem_free(&acb->ccbs_acc_handle);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_free_handle(&acb->ccbs_pool_handle);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonerror_level_1:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_soft_state_free(arcmsr_soft_state, instance);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonerror_level_0:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Function: arcmsr_attach(9E)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Description: Set up all device state and allocate data structures,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * mutexes, condition variables, etc. for device operation.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Set mt_attr property for driver to indicate MT-safety.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Add interrupts needed.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Input: dev_info_t *dev_info, ddi_attach_cmd_t cmd
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Output: Return DDI_SUCCESS if device is ready,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * else return DDI_FAILURE
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_attach(dev_info_t *dev_info, ddi_attach_cmd_t cmd) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson scsi_hba_tran_t *hba_trans;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ACB *acb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#if defined(ARCMSR_DEBUG)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_NOTE,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr_attach called for device %lx (instance %d)",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &dev_info, ddi_get_instance(dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#endif
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (cmd) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case DDI_ATTACH:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (arcmsr_do_ddi_attach(dev_info,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(dev_info)));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case DDI_RESUME:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case DDI_PM_RESUME:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * There is no hardware state to restart and no timeouts to
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * restart since we didn't PM_SUSPEND with active cmds or
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * active timeouts We just need to unblock waiting threads
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * and restart I/O the code for DDI_RESUME is almost identical
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * except it uses the suspend flag rather than pm_suspend flag
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans = (scsi_hba_tran_t *)ddi_get_driver_private(dev_info);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!hba_trans) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb = (struct ACB *)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson hba_trans->tran_hba_private;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_enter(&acb->acb_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop_init(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* restart ccbs "timeout" watchdog */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->timeout_id = timeout(arcmsr_ccbs_timeout,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void*)acb, (60 * drv_usectohz(1000000)));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_exit(&acb->acb_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_SUCCESS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson default:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: ddi attach cmd (%d) unsupported",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmd, ddi_get_instance(dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Function: arcmsr_detach(9E)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Description: Remove all device allocation and system resources, disable
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * device interrupt.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Input: dev_info_t *dev_info
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * ddi_detach_cmd_t cmd
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Output: Return DDI_SUCCESS if done,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * else returnDDI_FAILURE
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_detach(dev_info_t *dev_info, ddi_detach_cmd_t cmd) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int instance;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ACB *acb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson instance = ddi_get_instance(dev_info);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb = (struct ACB *)ddi_get_soft_state(arcmsr_soft_state,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson instance);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (cmd) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case DDI_DETACH:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_enter(&acb->acb_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->timeout_id != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_exit(&acb->acb_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) untimeout(acb->timeout_id);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_enter(&acb->acb_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->timeout_id = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_pcidev_disattach(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Remove interrupt set up by ddi_add_intr */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_remove_intr(dev_info, 0, acb->iblock_cookie);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* unbind mapping object to handle */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) ddi_dma_unbind_handle(acb->ccbs_pool_handle);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Free ccb pool memory */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_mem_free(&acb->ccbs_acc_handle);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Free DMA handle */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_free_handle(&acb->ccbs_pool_handle);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_regs_map_free(&acb->reg_mu_acc_handle0);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (scsi_hba_detach(dev_info) != DDI_SUCCESS)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: Unable to detach instance cleanly "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "(should not happen)",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* free scsi_hba_transport from scsi_hba_tran_alloc */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson scsi_hba_tran_free(acb->scsi_hba_transport);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_remove_minor_node(dev_info, NULL);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_prop_remove_all(dev_info);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_exit(&acb->acb_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_destroy(&acb->acb_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_destroy(&acb->postq_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_destroy(&acb->workingQ_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_destroy(&acb->ioctl_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pci_config_teardown(&acb->pci_acc_handle);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_set_driver_private(dev_info, NULL);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_soft_state_free(arcmsr_soft_state, instance);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pm_destroy_components(dev_info);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_SUCCESS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case DDI_SUSPEND:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case DDI_PM_SUSPEND:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_enter(&acb->acb_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->timeout_id != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags |= ACB_F_SCSISTOPADAPTER;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_exit(&acb->acb_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) untimeout(acb->timeout_id);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_enter(&acb->acb_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->timeout_id = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* disable all outbound interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) arcmsr_disable_allintr(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* stop adapter background rebuild */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->adapter_type == ACB_ADAPTER_TYPE_A) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_stop_hba_bgrb(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_flush_hba_cache(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_stop_hbb_bgrb(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_flush_hbb_cache(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_exit(&acb->acb_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_SUCCESS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson default:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Function: arcmsr_tran_tgt_init
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Description: Called when initializing a target device instance. If
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * no per-target initialization is required, the HBA
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * may leave tran_tgt_init to NULL
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Input:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * dev_info_t *host_dev_info,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * dev_info_t *target_dev_info,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * scsi_hba_tran_t *tran,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * struct scsi_device *sd
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Return: DDI_SUCCESS if success, else return DDI_FAILURE
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * entry point enables the HBA to allocate and/or initialize any per-
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * target resources.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * It also enables the HBA to qualify the device's address as valid and
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * supportable for that particular HBA.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * By returning DDI_FAILURE, the instance of the target driver for that
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * device will not be probed or attached.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * This entry point is not required, and if none is supplied,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * the framework will attempt to probe and attach all possible instances
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * of the appropriate target drivers.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_tran_tgt_init(dev_info_t *host_dev_info, dev_info_t *target_dev_info,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson scsi_hba_tran_t *hosttran, struct scsi_device *sd) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#ifndef __lock_lint
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson _NOTE(ARGUNUSED(hosttran, target_dev_info))
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#endif
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint16_t target;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t lun;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson target = sd->sd_address.a_target;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson lun = sd->sd_address.a_lun;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((target >= ARCMSR_MAX_TARGETID) || (lun >= ARCMSR_MAX_TARGETLUN)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: (target %d, lun %d) exceeds "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "maximum supported values (%d, %d)",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(host_dev_info),
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson target, lun, ARCMSR_MAX_TARGETID, ARCMSR_MAX_TARGETLUN);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_SUCCESS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Function: arcmsr_tran_getcap(9E)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Description: Get the capability named, and returnits value.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Return Values: current value of capability, ifdefined
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * -1 ifcapability is not defined
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * ------------------------------------------------------
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Common Capability Strings Array
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * ------------------------------------------------------
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_DMA_MAX 0
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_MSG_OUT 1
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_DISCONNECT 2
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_SYNCHRONOUS 3
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_WIDE_XFER 4
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_PARITY 5
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_INITIATOR_ID 6
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_UNTAGGED_QING 7
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_TAGGED_QING 8
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_ARQ 9
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_LINKED_CMDS 10 a
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_SECTOR_SIZE 11 b
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_TOTAL_SECTORS 12 c
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_GEOMETRY 13 d
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_RESET_NOTIFICATION 14 e
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_QFULL_RETRIES 15 f
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_QFULL_RETRY_INTERVAL 16 10
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_SCSI_VERSION 17 11
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_INTERCONNECT_TYPE 18 12
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define SCSI_CAP_LUN_RESET 19 13
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_tran_getcap(struct scsi_address *ap, char *cap, int whom) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int capability = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ACB *acb =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (struct ACB *)ap->a_hba_tran->tran_hba_private;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (cap == NULL || whom == 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_enter(&arcmsr_global_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (scsi_hba_lookup_capstr(cap)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_MSG_OUT:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_DISCONNECT:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_SYNCHRONOUS:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_WIDE_XFER:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_TAGGED_QING:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_UNTAGGED_QING:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_PARITY:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_ARQ:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson capability = acb->tgt_scsi_opts[ap->a_target];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_SECTOR_SIZE:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson capability = ARCMSR_DEV_SECTOR_SIZE;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_DMA_MAX:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Limit to 16MB max transfer */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson capability = ARCMSR_MAX_XFER_LEN;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_INITIATOR_ID:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson capability = ARCMSR_SCSI_INITIATOR_ID;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_GEOMETRY:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* head , track , cylinder */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson capability = (255 << 16) | 63;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson default:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson capability = -1;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_exit(&arcmsr_global_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (capability);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Function: arcmsr_tran_setcap(9E)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Description: Set the specific capability.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Return Values: 1 - capability exists and can be set to new value
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * 0 - capability could not be set to new value
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * -1 - no such capability
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_tran_setcap(struct scsi_address *ap, char *cap, int value,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int whom) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#ifndef __lock_lint
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson _NOTE(ARGUNUSED(value))
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#endif
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int supported = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ACB *acb =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (struct ACB *)ap->a_hba_tran->tran_hba_private;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (cap == NULL || whom == 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (-1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_enter(&arcmsr_global_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (supported = scsi_hba_lookup_capstr(cap)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_DISCONNECT: /* 2 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_SYNCHRONOUS: /* 3 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_TAGGED_QING: /* 8 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_WIDE_XFER: /* 4 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_ARQ: /* 9 auto request sense */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_TOTAL_SECTORS: /* c */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->tgt_scsi_opts[ap->a_target] |= supported;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson supported = 1;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_UNTAGGED_QING: /* 7 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_INITIATOR_ID: /* 6 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_DMA_MAX: /* 0 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_MSG_OUT: /* 1 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_PARITY: /* 5 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_LINKED_CMDS: /* a */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_RESET_NOTIFICATION: /* e */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSI_CAP_SECTOR_SIZE: /* b */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson supported = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson default:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson supported = -1;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_exit(&arcmsr_global_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (supported);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_free_ccb(struct CCB *ccb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ACB *acb = ccb->acb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->startdone = ARCMSR_CCB_DONE;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->ccb_flags = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_enter(&acb->workingQ_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->ccbworkingQ[acb->workingccb_doneindex] = ccb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->workingccb_doneindex++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->workingccb_doneindex %= ARCMSR_MAX_FREECCB_NUM;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_exit(&acb->workingQ_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Function: arcmsr_tran_init_pkt
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Return Values: pointer to scsi_pkt, or NULL
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Description: simultaneously allocate both a scsi_pkt(9S) structure and
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * DMA resources for that pkt.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Called by kernel on behalf of a target driver
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * calling scsi_init_pkt(9F).
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Refer to tran_init_pkt(9E) man page
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Context: Can be called from different kernel process threads.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Can be called by interrupt thread.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Allocates SCSI packet and DMA resources
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic struct
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonscsi_pkt *arcmsr_tran_init_pkt(struct scsi_address *ap,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson register struct scsi_pkt *pkt, struct buf *bp, int cmdlen, int statuslen,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int tgtlen, int flags, int (*callback)(), caddr_t arg) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *ccb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ARCMSR_CDB *arcmsr_cdb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ACB *acb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int old_pkt_flag = 1;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb = (struct ACB *)ap->a_hba_tran->tran_hba_private;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (pkt == NULL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* get free CCB */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb = arcmsr_get_freeccb(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb == (struct CCB *)NULL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (NULL);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->pkt != NULL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * If kmem_flags are turned on, expect to
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * see a message
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: invalid pkt",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (NULL);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt = scsi_hba_pkt_alloc(acb->dev_info, ap, cmdlen,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson statuslen, tgtlen, sizeof (struct scsi_pkt),
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson callback, arg);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (pkt == NULL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: scsi pkt allocation failed",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_free_ccb(ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (NULL);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Initialize CCB */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt = pkt;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dma_handle = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* record how many sg are needed to xfer on this pkt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_ncookies = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* record how many sg we got from this window */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_cookie = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* record how many windows have partial dma map set */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_nwin = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* record current sg window position */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_curwin = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dma_len = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dma_offset = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->resid_dmacookie.dmac_size = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * we will still use this point for we want to fake some
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * information in tran_start
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->bp = bp;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Initialize arcmsr_cdb */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bzero(arcmsr_cdb, sizeof (struct ARCMSR_CDB));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_cdb->Bus = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_cdb->Function = 1;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_cdb->LUN = ap->a_lun;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_cdb->TargetID = ap->a_target;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_cdb->CdbLength = (uint8_t)cmdlen;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_cdb->Context = (unsigned long)arcmsr_cdb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Fill in the rest of the structure */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_ha_private = ccb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_address = *ap;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_comp = (void (*)())NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_flags = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_time = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_resid = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_statistics = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_reason = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson old_pkt_flag = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb = (struct CCB *)pkt->pkt_ha_private;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * you cannot update CdbLength with cmdlen here, it would
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * cause a data compare error
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->startdone = ARCMSR_CCB_UNBUILD;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Second step : dma allocation/move */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (bp && bp->b_bcount != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * system had a lot of data trunk need to xfer, from...20 byte
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * to 819200 byte.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * arcmsr_dma_alloc will get pkt_dma_handle (not null) until
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * this lot of data trunk xfer done this mission will be done
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * by some of continue READ or WRITE scsi command, till this
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * lot of data trunk xfer completed.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * arcmsr_dma_move do the action repeatedly, and use the same
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * ccb till this lot of data trunk xfer complete notice.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * when after the arcmsr_tran_init_pkt returns the solaris
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * kernel is by your pkt_resid and its b_bcount to give you
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * which type of scsi command descriptor to implement the
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * length of folowing arcmsr_tran_start scsi cdb (data length)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Each transfer should be aligned on a 512 byte boundary
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->pkt_dma_handle == NULL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (arcmsr_dma_alloc(acb, pkt, bp, flags,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson callback) == DDI_FAILURE) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * the HBA driver is unable to allocate DMA
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * resources, it must free the allocated
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * scsi_pkt(9S) before returning
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: dma allocation "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "failure ",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (old_pkt_flag == 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: dma "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "allocation failed to free scsi "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "hba pkt ",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_free_ccb(ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson scsi_hba_pkt_free(ap, pkt);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return ((struct scsi_pkt *)NULL);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* DMA resources to next DMA window, for old pkt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (arcmsr_dma_move(acb, pkt, bp) == -1) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: dma move "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "failed ",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return ((struct scsi_pkt *)NULL);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_resid = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (pkt);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Function name: arcmsr_dma_alloc
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Return Values: 0 if successful, -1 if failure
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Description: allocate DMA resources
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Context: Can only be called from arcmsr_tran_init_pkt()
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * register struct scsi_address *ap = &((pkt)->pkt_address);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_dma_alloc(struct ACB *acb, struct scsi_pkt *pkt,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct buf *bp, int flags, int (*callback)()) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *ccb = pkt->pkt_ha_private;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int alloc_result, map_method, dma_flags;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int resid = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int total_ccb_xferlen = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int (*cb)(caddr_t);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t i;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * at this point the PKT SCSI CDB is empty, and dma xfer length
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * is bp->b_bcount
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (bp->b_flags & B_READ) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->ccb_flags &= ~CCB_FLAG_DMAWRITE;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dma_flags = DDI_DMA_READ;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->ccb_flags |= CCB_FLAG_DMAWRITE;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dma_flags = DDI_DMA_WRITE;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (flags & PKT_CONSISTENT) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->ccb_flags |= CCB_FLAG_DMACONSISTENT;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dma_flags |= DDI_DMA_CONSISTENT;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (flags & PKT_DMA_PARTIAL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dma_flags |= DDI_DMA_PARTIAL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dma_flags |= DDI_DMA_REDZONE;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cb = (callback == NULL_FUNC) ? DDI_DMA_DONTWAIT : DDI_DMA_SLEEP;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((alloc_result = ddi_dma_alloc_handle(acb->dev_info,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &arcmsr_dma_attr, cb, 0, &ccb->pkt_dma_handle))
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson != DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (alloc_result) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case DDI_DMA_BADATTR:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * If the system does not support physical DMA,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * the return value from ddi_dma_alloc_handle
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * will be DDI_DMA_BADATTR
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: dma allocate returned "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "'bad attribute'",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bioerror(bp, EFAULT);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case DDI_DMA_NORESOURCES:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: dma allocate returned "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "'no resources'",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bioerror(bp, 0);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson default:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: dma allocate returned "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "'unknown failure'",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson map_method = ddi_dma_buf_bind_handle(ccb->pkt_dma_handle, bp,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dma_flags, cb, 0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &ccb->pkt_dmacookies[0], /* SG List pointer */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &ccb->pkt_ncookies); /* number of sgl cookies */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (map_method) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case DDI_DMA_PARTIAL_MAP:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * When your main memory size larger then 4G
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * DDI_DMA_PARTIAL_MAP will be touched.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * We've already set DDI_DMA_PARTIAL in dma_flags,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * so if it's now missing, there's something screwy
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * happening. We plow on....
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((dma_flags & DDI_DMA_PARTIAL) == 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: dma partial mapping lost "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "...impossible case!",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_dma_numwin(ccb->pkt_dma_handle, &ccb->pkt_nwin) ==
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_FAILURE) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: ddi_dma_numwin() failed",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_dma_getwin(ccb->pkt_dma_handle, ccb->pkt_curwin,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &ccb->pkt_dma_offset, &ccb->pkt_dma_len,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &ccb->pkt_dmacookies[0], &ccb->pkt_ncookies) ==
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_FAILURE) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: ddi_dma_getwin failed",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson i = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* first cookie is accessed from ccb->pkt_dmacookies[0] */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson total_ccb_xferlen = ccb->pkt_dmacookies[0].dmac_size;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson for (;;) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson i++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (i == ARCMSR_MAX_SG_ENTRIES ||
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson i == ccb->pkt_ncookies ||
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson total_ccb_xferlen == ARCMSR_MAX_XFER_LEN) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * next cookie will be retrieved from
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * ccb->pkt_dmacookies[i]
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_nextcookie(ccb->pkt_dma_handle,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &ccb->pkt_dmacookies[i]);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson total_ccb_xferlen += ccb->pkt_dmacookies[i].dmac_size;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_cookie = i;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->arcmsr_cdb.sgcount = i;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (total_ccb_xferlen > 512) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson resid = total_ccb_xferlen % 512;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (resid != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson i--;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson total_ccb_xferlen -= resid;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* modify last sg length */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dmacookies[i].dmac_size =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dmacookies[i].dmac_size - resid;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->resid_dmacookie.dmac_size = resid;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->resid_dmacookie.dmac_laddress =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dmacookies[i].dmac_laddress +
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dmacookies[i].dmac_size;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->total_dmac_size = total_ccb_xferlen;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->ccb_flags |= CCB_FLAG_DMAVALID;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_resid = bp->b_bcount - ccb->total_dmac_size;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_SUCCESS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case DDI_DMA_MAPPED:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_nwin = 1; /* all mapped, so only one window */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dma_len = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dma_offset = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson i = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* first cookie is accessed from ccb->pkt_dmacookies[0] */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson total_ccb_xferlen = ccb->pkt_dmacookies[0].dmac_size;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson for (;;) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson i++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (i == ARCMSR_MAX_SG_ENTRIES ||
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson i == ccb->pkt_ncookies ||
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson total_ccb_xferlen == ARCMSR_MAX_XFER_LEN) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * next cookie will be retrieved from
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * ccb->pkt_dmacookies[i]
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_nextcookie(ccb->pkt_dma_handle,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &ccb->pkt_dmacookies[i]);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson total_ccb_xferlen += ccb->pkt_dmacookies[i].dmac_size;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_cookie = i;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->arcmsr_cdb.sgcount = i;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (total_ccb_xferlen > 512) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson resid = total_ccb_xferlen % 512;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (resid != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson i--;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson total_ccb_xferlen -= resid;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* modify last sg length */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dmacookies[i].dmac_size =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dmacookies[i].dmac_size - resid;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->resid_dmacookie.dmac_size = resid;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->resid_dmacookie.dmac_laddress =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dmacookies[i].dmac_laddress +
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dmacookies[i].dmac_size;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->total_dmac_size = total_ccb_xferlen;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->ccb_flags |= CCB_FLAG_DMAVALID;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_resid = bp->b_bcount - ccb->total_dmac_size;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_SUCCESS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case DDI_DMA_NORESOURCES:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: dma map got 'no resources'",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bioerror(bp, ENOMEM);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case DDI_DMA_NOMAPPING:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: dma map got 'no mapping'",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bioerror(bp, EFAULT);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case DDI_DMA_TOOBIG:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: dma map got 'too big'",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bioerror(bp, EINVAL);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case DDI_DMA_INUSE:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: dma map got 'in use' "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "(should not happen)",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson default:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: dma map got 'unknown failure 0x%x' "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "(should not happen)",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info), i);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_dump_scsi_cdb(&pkt->pkt_address, pkt);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_free_handle(&ccb->pkt_dma_handle);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dma_handle = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->ccb_flags &= ~CCB_FLAG_DMAVALID;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Function name: arcmsr_dma_move
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Return Values: 0 if successful, -1 if failure
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Description: move DMA resources to next DMA window
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Context: Can only be called from arcmsr_tran_init_pkt()
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_dma_move(struct ACB *acb, struct scsi_pkt *pkt,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct buf *bp) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *ccb = pkt->pkt_ha_private;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t i = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int resid = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int total_ccb_xferlen = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->resid_dmacookie.dmac_size != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson total_ccb_xferlen += ccb->resid_dmacookie.dmac_size;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dmacookies[i].dmac_size =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->resid_dmacookie.dmac_size;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dmacookies[i].dmac_laddress =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->resid_dmacookie.dmac_laddress;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson i++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->resid_dmacookie.dmac_size = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * If there are no more cookies remaining in this window,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * move to the next window.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->pkt_cookie == ccb->pkt_ncookies) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * only dma map "partial" arrive here
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((ccb->pkt_curwin == ccb->pkt_nwin) &&
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (ccb->pkt_nwin == 1)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: dma partial set, but only "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "one window allocated",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_SUCCESS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* At last window, cannot move */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (++ccb->pkt_curwin >= ccb->pkt_nwin) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: dma partial set, numwin exceeded",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_dma_getwin(ccb->pkt_dma_handle, ccb->pkt_curwin,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &ccb->pkt_dma_offset, &ccb->pkt_dma_len,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &ccb->pkt_dmacookies[i], &ccb->pkt_ncookies) ==
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_FAILURE) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: dma partial set, "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "ddi_dma_getwin failure",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* reset cookie pointer */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_cookie = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * only dma map "all" arrive here
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * We still have more cookies in this window,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * get the next one
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * access the pkt_dma_handle remain cookie record at
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * ccb->pkt_dmacookies array
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_nextcookie(ccb->pkt_dma_handle,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &ccb->pkt_dmacookies[i]);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Get remaining cookies in this window, up to our maximum */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson total_ccb_xferlen += ccb->pkt_dmacookies[i].dmac_size;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* retrieve and store cookies, start at ccb->pkt_dmacookies[0] */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson for (;;) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson i++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* handled cookies count level indicator */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_cookie++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (i == ARCMSR_MAX_SG_ENTRIES ||
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_cookie == ccb->pkt_ncookies ||
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson total_ccb_xferlen == ARCMSR_MAX_XFER_LEN) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_nextcookie(ccb->pkt_dma_handle,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &ccb->pkt_dmacookies[i]);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson total_ccb_xferlen += ccb->pkt_dmacookies[i].dmac_size;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->arcmsr_cdb.sgcount = i;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (total_ccb_xferlen > 512) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson resid = total_ccb_xferlen % 512;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (resid != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson i--;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson total_ccb_xferlen -= resid;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* modify last sg length */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dmacookies[i].dmac_size =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dmacookies[i].dmac_size - resid;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->resid_dmacookie.dmac_size = resid;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->resid_dmacookie.dmac_laddress =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dmacookies[i].dmac_laddress +
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dmacookies[i].dmac_size;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->total_dmac_size += total_ccb_xferlen;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_resid = bp->b_bcount - ccb->total_dmac_size;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_SUCCESS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Function name: arcmsr_tran_destroy_pkt
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Return Values: none
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Description: Called by kernel on behalf of a target driver
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * calling scsi_destroy_pkt(9F).
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Refer to tran_destroy_pkt(9E) man page
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Context: Can be called from different kernel process threads.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Can be called by interrupt thread.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_tran_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *ccb = pkt->pkt_ha_private;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((ccb != NULL) && (ccb->pkt == pkt)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ACB *acb = ccb->acb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->ccb_flags & CCB_FLAG_DMAVALID) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_dma_unbind_handle(ccb->pkt_dma_handle)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson != DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: ddi_dma_unbind_handle() failed",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_free_handle(&ccb->pkt_dma_handle);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dma_handle = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_free_ccb(ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson scsi_hba_pkt_free(ap, pkt);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Function name: arcmsr_tran_dmafree()
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Return Values: none
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Description: free dvma resources
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Context: Can be called from different kernel process threads.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Can be called by interrupt thread.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_tran_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *ccb = pkt->pkt_ha_private;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->ccb_flags & CCB_FLAG_DMAVALID) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->ccb_flags &= ~CCB_FLAG_DMAVALID;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_dma_unbind_handle(ccb->pkt_dma_handle)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson != DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: ddi_dma_unbind_handle() failed "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "(target %d lun %d)",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(ccb->acb->dev_info),
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ap->a_target, ap->a_lun);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_free_handle(&ccb->pkt_dma_handle);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dma_handle = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Function name: arcmsr_tran_sync_pkt()
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Return Values: none
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Description: sync dma
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Context: Can be called from different kernel process threads.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Can be called by interrupt thread.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_tran_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *ccb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb = pkt->pkt_ha_private;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->ccb_flags & CCB_FLAG_DMAVALID) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_dma_sync(ccb->pkt_dma_handle,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dma_offset, ccb->pkt_dma_len,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (ccb->ccb_flags & CCB_FLAG_DMAWRITE) ?
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson != DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: sync pkt failed "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "for target %d lun %d",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(ccb->acb->dev_info),
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ap->a_target, ap->a_lun);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic uint8_t
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_hba_wait_msgint_ready(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t i;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t retries = 0x00;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson do {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson for (i = 0; i < 100; i++) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->outbound_intstatus) &
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* clear interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->outbound_intstatus,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MU_OUTBOUND_MESSAGE0_INT);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (TRUE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson drv_usecwait(10000);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_in_panic()) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* clear interrupts */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->outbound_intstatus,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MU_OUTBOUND_MESSAGE0_INT);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (TRUE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } /* max 1 second */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } while (retries++ < 20); /* max 20 seconds */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (FALSE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic uint8_t
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_hbb_wait_msgint_ready(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t i;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t retries = 0x00;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson do {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson for (i = 0; i < 100; i++) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->iop2drv_doorbell) &
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* clear interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->iop2drv_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_INT_CLEAR_PATTERN);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->drv2iop_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_DRV2IOP_END_OF_INTERRUPT);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (TRUE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson drv_usecwait(10000);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_in_panic()) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* clear interrupts */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->iop2drv_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_INT_CLEAR_PATTERN);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->drv2iop_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_DRV2IOP_END_OF_INTERRUPT);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (TRUE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } /* max 1 second */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } while (retries++ < 20); /* max 20 seconds */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (FALSE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_flush_hba_cache(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int retry_count = 30;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* enlarge wait flush adapter cache time: 10 minutes */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0, &phbamu->inbound_msgaddr0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson do {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (arcmsr_hba_wait_msgint_ready(acb)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retry_count--;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } while (retry_count != 0);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_flush_hbb_cache(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int retry_count = 30;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* enlarge wait flush adapter cache time: 10 minutes */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->drv2iop_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_FLUSH_CACHE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson do {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (arcmsr_hbb_wait_msgint_ready(acb)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retry_count--;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } while (retry_count != 0);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_ccb_complete(struct CCB *ccb, int flag) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ACB *acb = ccb->acb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct scsi_pkt *pkt = ccb->pkt;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (flag == 1) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->ccboutstandingcount--;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson STATE_SENT_CMD | STATE_GOT_STATUS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((ccb->ccb_flags & CCB_FLAG_DMACONSISTENT) &&
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (pkt->pkt_state & STATE_XFERRED_DATA)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) ddi_dma_sync(ccb->pkt_dma_handle,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dma_offset, ccb->pkt_dma_len,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_DMA_SYNC_FORCPU);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (pkt->pkt_comp) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (*pkt->pkt_comp)(pkt);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_report_sense_info(struct CCB *ccb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct scsi_pkt *pkt = ccb->pkt;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct scsi_arq_status *arq_status;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arq_status = (struct scsi_arq_status *)(intptr_t)(pkt->pkt_scbp);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bzero((caddr_t)arq_status, sizeof (struct scsi_arq_status));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arq_status->sts_rqpkt_reason = CMD_CMPLT;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arq_status->sts_rqpkt_state = (STATE_GOT_BUS | STATE_GOT_TARGET |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson STATE_SENT_CMD | STATE_XFERRED_DATA | STATE_GOT_STATUS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arq_status->sts_rqpkt_statistics = pkt->pkt_statistics;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arq_status->sts_rqpkt_resid = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_reason = CMD_CMPLT;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* auto rqsense took place */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_state = (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson STATE_GOT_STATUS | STATE_ARQ_DONE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (&arq_status->sts_sensedata != NULL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct SENSE_DATA *cdb_sensedata;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct scsi_extended_sense *sts_sensedata;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cdb_sensedata =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (struct SENSE_DATA *)ccb->arcmsr_cdb.SenseData;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata = &arq_status->sts_sensedata;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_code = cdb_sensedata->ErrorCode;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* must eq CLASS_EXTENDED_SENSE (0x07) */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_class = cdb_sensedata->ErrorClass;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_valid = cdb_sensedata->Valid;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_segnum = cdb_sensedata->SegmentNumber;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_key = cdb_sensedata->SenseKey;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_ili = cdb_sensedata->IncorrectLength;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_eom = cdb_sensedata->EndOfMedia;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_filmk = cdb_sensedata->FileMark;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_info_1 = cdb_sensedata->Information[0];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_info_2 = cdb_sensedata->Information[1];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_info_3 = cdb_sensedata->Information[2];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_info_4 = cdb_sensedata->Information[3];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_add_len =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cdb_sensedata->AdditionalSenseLength;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_cmd_info[0] =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cdb_sensedata->CommandSpecificInformation[0];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_cmd_info[1] =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cdb_sensedata->CommandSpecificInformation[1];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_cmd_info[2] =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cdb_sensedata->CommandSpecificInformation[2];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_cmd_info[3] =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cdb_sensedata->CommandSpecificInformation[3];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_add_code =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cdb_sensedata->AdditionalSenseCode;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_qual_code =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cdb_sensedata->AdditionalSenseCodeQualifier;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_fru_code =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cdb_sensedata->FieldReplaceableUnitCode;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_abort_hba_allcmd(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->inbound_msgaddr0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_INBOUND_MESG0_ABORT_CMD);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!arcmsr_hba_wait_msgint_ready(acb)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: timeout while waiting for 'abort all "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "outstanding commands'",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_abort_hbb_allcmd(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->drv2iop_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_ABORT_CMD);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!arcmsr_hbb_wait_msgint_ready(acb)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: timeout while waiting for 'abort all "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "outstanding commands'",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_report_ccb_state(struct ACB *acb,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *ccb, uint32_t flag_ccb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int id, lun;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson id = ccb->pkt->pkt_address.a_target;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson lun = ccb->pkt->pkt_address.a_lun;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR) == 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->devstate[id][lun] == ARECA_RAID_GONE) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->devstate[id][lun] = ARECA_RAID_GOOD;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_reason = CMD_CMPLT;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_state |= STATE_XFERRED_DATA;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_ccb_complete(ccb, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (ccb->arcmsr_cdb.DeviceStatus) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_DEV_SELECT_TIMEOUT:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->devstate[id][lun] == ARECA_RAID_GOOD) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: raid volume was kicked out ",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->devstate[id][lun] = ARECA_RAID_GONE;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_reason = CMD_TIMEOUT;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_statistics |= STAT_TIMEOUT;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_ccb_complete(ccb, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_DEV_ABORTED:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_DEV_INIT_FAIL:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: isr got "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "'ARCMSR_DEV_ABORTED' 'ARCMSR_DEV_INIT_FAIL'",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT, "arcmsr%d: raid volume was kicked "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "out", ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->devstate[id][lun] = ARECA_RAID_GONE;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_reason = CMD_DEV_GONE;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_statistics |= STAT_TERMINATED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_ccb_complete(ccb, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCSISTAT_CHECK_CONDITION:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->devstate[id][lun] = ARECA_RAID_GOOD;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_report_sense_info(ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_ccb_complete(ccb, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson default:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: target %d lun %d "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "isr received CMD_DONE with unknown "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "DeviceStatus (0x%x)",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info), id, lun,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->arcmsr_cdb.DeviceStatus);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT, "arcmsr%d: raid volume was kicked "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "out ", ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->devstate[id][lun] = ARECA_RAID_GONE;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* unknown error or crc error just for retry */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_reason = CMD_TRAN_ERR;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_statistics |= STAT_TERMINATED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_ccb_complete(ccb, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_drain_donequeue(struct ACB *acb, uint32_t flag_ccb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *ccb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* check if command completed without error */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb = (struct CCB *)(acb->vir2phy_offset +
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (flag_ccb << 5)); /* frame must be aligned on 32 byte boundary */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->startdone == ARCMSR_CCB_ABORTED) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: isr got aborted command "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "while draining doneq",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_reason = CMD_ABORTED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_statistics |= STAT_ABORTED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_ccb_complete(ccb, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->startdone == ARCMSR_CCB_RESET) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: isr got command reset "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "while draining doneq",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_reason = CMD_RESET;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_statistics |= STAT_BUS_RESET;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_ccb_complete(ccb, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: isr got an illegal ccb command "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "done while draining doneq",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_report_ccb_state(acb, ccb, flag_ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_done4abort_postqueue(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int i = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t flag_ccb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (acb->adapter_type) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_A:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t outbound_intstatus;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* clear and abort all outbound posted Q */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson outbound_intstatus = CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->outbound_intstatus) & acb->outbound_int_enable;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* clear interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->outbound_intstatus, outbound_intstatus);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while (((flag_ccb = CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->outbound_queueport)) != 0xFFFFFFFF) &&
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_drain_donequeue(acb, flag_ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_B:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* clear all outbound posted Q */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* clear doorbell interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->iop2drv_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_DOORBELL_INT_CLEAR_PATTERN);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson for (i = 0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((flag_ccb = phbbmu->done_qbuffer[i]) != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu->done_qbuffer[i] = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_drain_donequeue(acb, flag_ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu->post_qbuffer[i] = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } /* drain reply FIFO */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu->doneq_index = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu->postq_index = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Routine Description: Reset 80331 iop.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Arguments:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Return Value: Nothing.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_iop_reset(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *ccb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t intmask_org;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int i = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->ccboutstandingcount > 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* disable all outbound interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson intmask_org = arcmsr_disable_allintr(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* talk to iop 331 outstanding command aborted */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->adapter_type == ACB_ADAPTER_TYPE_A) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_abort_hba_allcmd(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_abort_hbb_allcmd(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* clear and abort all outbound posted Q */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_done4abort_postqueue(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb = acb->pccb_pool[i];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->startdone == ARCMSR_CCB_START) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->startdone = ARCMSR_CCB_RESET;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_reason = CMD_RESET;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_statistics |= STAT_BUS_RESET;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_ccb_complete(ccb, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* enable all outbound interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_enable_allintr(acb, intmask_org);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * You can access the DMA address through the #defines:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * dmac_address for 32-bit addresses and dmac_laddress for 64-bit addresses.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * These macros are defined as follows:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define dmac_laddress _dmu._dmac_ll
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #ifdef _LONG_LONG_HTOL
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define dmac_notused _dmu._dmac_la[0]
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define dmac_address _dmu._dmac_la[1]
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #else
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define dmac_address _dmu._dmac_la[0]
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #define dmac_notused _dmu._dmac_la[1]
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * #endif
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*ARGSUSED*/
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_build_ccb(struct CCB *ccb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct scsi_pkt *pkt = ccb->pkt;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ARCMSR_CDB *arcmsr_cdb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson char *psge;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t address_lo, address_hi;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int arccdbsize = 0x30;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t sgcount;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson psge = (char *)&arcmsr_cdb->sgu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* return the current time in seconds */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->ccb_time = (time_t)(pkt->pkt_time + ddi_get_time());
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bcopy((caddr_t)pkt->pkt_cdbp, arcmsr_cdb->Cdb,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_cdb->CdbLength);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sgcount = ccb->arcmsr_cdb.sgcount;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (sgcount) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int length, i;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int cdb_sgcount = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int total_xfer_length = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* map stor port SG list to our iop SG List. */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson for (i = 0; i < sgcount; i++) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Get physaddr of the current data pointer */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson length = ccb->pkt_dmacookies[i].dmac_size;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson total_xfer_length += length;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson address_lo = dma_addr_lo32(
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dmacookies[i].dmac_laddress);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson address_hi = dma_addr_hi32(
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dmacookies[i].dmac_laddress);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (address_hi == 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct SG32ENTRY *dma_sg;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dma_sg = (struct SG32ENTRY *)(intptr_t)psge;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dma_sg->address = address_lo;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dma_sg->length = length;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson psge += sizeof (struct SG32ENTRY);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arccdbsize += sizeof (struct SG32ENTRY);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int sg64s_size = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int tmplength = length;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int64_t span4G, length0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct SG64ENTRY *dma_sg;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*LINTED*/
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while (1) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dma_sg =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (struct SG64ENTRY *)(intptr_t)psge;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson span4G =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (int64_t)address_lo + tmplength;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dma_sg->addresshigh = address_hi;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dma_sg->address = address_lo;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (span4G > 0x100000000ULL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* see if we cross 4G */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson length0 = 0x100000000ULL -
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson address_lo;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dma_sg->length =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (uint32_t)length0 |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson IS_SG64_ADDR;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson address_hi = address_hi + 1;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson address_lo = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson tmplength = tmplength-
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (int32_t)length0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sg64s_size +=
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct SG64ENTRY);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson psge +=
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct SG64ENTRY);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cdb_sgcount++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dma_sg->length = tmplength |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson IS_SG64_ADDR;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sg64s_size +=
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct SG64ENTRY);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson psge +=
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct SG64ENTRY);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arccdbsize += sg64s_size;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cdb_sgcount++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_cdb->sgcount = (uint8_t)cdb_sgcount;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_cdb->DataLength = total_xfer_length;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (arccdbsize > 256) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_cdb->DataLength = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->ccb_flags & CCB_FLAG_DMAWRITE)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * arcmsr_post_ccb - Send a protocol specific ARC send postcard to a AIOC.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * handle: Handle of registered ARC protocol driver
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * adapter_id: AIOC unique identifier(integer)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * pPOSTCARD_SEND: Pointer to ARC send postcard
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * This routine posts a ARC send postcard to the request post FIFO of a
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * specific ARC adapter.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_post_ccb(struct ACB *acb, struct CCB *ccb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t cdb_shifted_phyaddr = ccb->cdb_shifted_phyaddr;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct scsi_pkt *pkt = ccb->pkt;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ARCMSR_CDB *arcmsr_cdb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Use correct offset and size for syncing */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_dma_sync(acb->ccbs_pool_handle, 0, acb->dma_sync_size,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_DMA_SYNC_FORDEV) == DDI_FAILURE)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->ccboutstandingcount++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->startdone = ARCMSR_CCB_START;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (acb->adapter_type) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_A:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->inbound_queueport,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cdb_shifted_phyaddr |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_CCBPOST_FLAG_SGL_BSIZE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->inbound_queueport, cdb_shifted_phyaddr);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (pkt->pkt_flags & FLAG_NOINTR)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_polling_hba_ccbdone(acb, ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_B:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int ending_index, index;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_enter(&acb->postq_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson index = phbbmu->postq_index;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ending_index = ((index+1)%ARCMSR_MAX_HBB_POSTQUEUE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu->post_qbuffer[ending_index] = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu->post_qbuffer[index] =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (cdb_shifted_phyaddr|ARCMSR_CCBPOST_FLAG_SGL_BSIZE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu->post_qbuffer[index] = cdb_shifted_phyaddr;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson index++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* if last index number set it to 0 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson index %= ARCMSR_MAX_HBB_POSTQUEUE;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu->postq_index = index;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->drv2iop_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_DRV2IOP_CDB_POSTED);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_exit(&acb->postq_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (pkt->pkt_flags & FLAG_NOINTR)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_polling_hbb_ccbdone(acb, ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_SUCCESS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic struct QBUFFER *
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_get_iop_rqbuffer(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct QBUFFER *qb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (acb->adapter_type) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_A:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson qb = (struct QBUFFER *)&phbamu->message_rbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_B:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson qb = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (qb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic struct QBUFFER *
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_get_iop_wqbuffer(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct QBUFFER *qbuffer = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (acb->adapter_type) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_A:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson qbuffer = (struct QBUFFER *)&phbamu->message_wbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_B:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson qbuffer =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (qbuffer);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_iop_message_read(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (acb->adapter_type) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_A:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* let IOP know the data has been read */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->inbound_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_B:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* let IOP know the data has been read */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->drv2iop_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_DRV2IOP_DATA_READ_OK);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_iop_message_wrote(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (acb->adapter_type) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_A:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * push inbound doorbell tell iop, driver data write ok
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * and wait reply on next hwinterrupt for next Qbuffer post
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->inbound_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_B:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * push inbound doorbell tell iop, driver data was writen
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * successfully, then await reply on next hwinterrupt for
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * next Qbuffer post
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->drv2iop_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_DRV2IOP_DATA_WRITE_OK);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_post_ioctldata2iop(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t *pQbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct QBUFFER *pwbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t *iop_data;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int32_t allxfer_len = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pwbuffer = arcmsr_get_iop_wqbuffer(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_data = (uint8_t *)pwbuffer->data;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while ((acb->wqbuf_firstidx != acb->wqbuf_lastidx) &&
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (allxfer_len < 124)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pQbuffer = &acb->wqbuffer[acb->wqbuf_firstidx];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) memcpy(iop_data, pQbuffer, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->wqbuf_firstidx++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* if last index number set it to 0 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->wqbuf_firstidx %= ARCMSR_MAX_QBUFFER;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_data++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson allxfer_len++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pwbuffer->data_len = allxfer_len;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * push inbound doorbell and wait reply at hwinterrupt
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * routine for next Qbuffer post
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop_message_wrote(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_stop_hba_bgrb(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->inbound_msgaddr0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_INBOUND_MESG0_STOP_BGRB);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!arcmsr_hba_wait_msgint_ready(acb))
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: timeout while waiting for background "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "rebuild completion",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_stop_hbb_bgrb(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->drv2iop_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_STOP_BGRB);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!arcmsr_hbb_wait_msgint_ready(acb))
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: timeout while waiting for background "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "rebuild completion",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_iop_message_xfer(struct ACB *acb, struct scsi_pkt *pkt) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CMD_MESSAGE_FIELD *pcmdmessagefld;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *ccb = pkt->pkt_ha_private;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct buf *bp = ccb->bp;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t *pQbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int retvalue = 0, transfer_len = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson char *buffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t controlcode;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* 4 bytes: Areca io control code */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson controlcode = (uint32_t)pkt->pkt_cdbp[5] << 24 |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (uint32_t)pkt->pkt_cdbp[6] << 16 |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (uint32_t)pkt->pkt_cdbp[7] << 8 |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (uint32_t)pkt->pkt_cdbp[8];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (bp->b_flags & (B_PHYS | B_PAGEIO))
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bp_mapin(bp);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson buffer = bp->b_un.b_addr;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson transfer_len = bp->b_bcount;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (transfer_len > sizeof (struct CMD_MESSAGE_FIELD)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retvalue = ARCMSR_MESSAGE_FAIL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto message_out;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pcmdmessagefld = (struct CMD_MESSAGE_FIELD *)(intptr_t)buffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (controlcode) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_MESSAGE_READ_RQBUFFER:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson unsigned long *ver_addr;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t *ptmpQbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int32_t allxfer_len = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ver_addr = kmem_zalloc(MSGDATABUFLEN, KM_SLEEP);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!ver_addr) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retvalue = ARCMSR_MESSAGE_FAIL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto message_out;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ptmpQbuffer = (uint8_t *)ver_addr;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while ((acb->rqbuf_firstidx != acb->rqbuf_lastidx) &&
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (allxfer_len < (MSGDATABUFLEN - 1))) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pQbuffer = &acb->rqbuffer[acb->rqbuf_firstidx];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) memcpy(ptmpQbuffer, pQbuffer, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->rqbuf_firstidx++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->rqbuf_firstidx %= ARCMSR_MAX_QBUFFER;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ptmpQbuffer++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson allxfer_len++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct QBUFFER *prbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t *iop_data;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int32_t iop_len;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson prbuffer = arcmsr_get_iop_rqbuffer(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_data = (uint8_t *)prbuffer->data;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_len = (int32_t)prbuffer->data_len;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while (iop_len > 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pQbuffer = &acb->rqbuffer[acb->rqbuf_lastidx];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) memcpy(pQbuffer, iop_data, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->rqbuf_lastidx++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->rqbuf_lastidx %= ARCMSR_MAX_QBUFFER;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_data++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_len--;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop_message_read(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) memcpy(pcmdmessagefld->messagedatabuffer,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (uint8_t *)ver_addr, allxfer_len);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pcmdmessagefld->cmdmessage.Length = allxfer_len;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pcmdmessagefld->cmdmessage.ReturnCode =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_RETURNCODE_OK;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson kmem_free(ver_addr, MSGDATABUFLEN);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_MESSAGE_WRITE_WQBUFFER:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson unsigned long *ver_addr;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int32_t my_empty_len, user_len, wqbuf_firstidx, wqbuf_lastidx;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t *ptmpuserbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ver_addr = kmem_zalloc(MSGDATABUFLEN, KM_SLEEP);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!ver_addr) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retvalue = ARCMSR_MESSAGE_FAIL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto message_out;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ptmpuserbuffer = (uint8_t *)ver_addr;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson user_len = pcmdmessagefld->cmdmessage.Length;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson user_len);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson wqbuf_lastidx = acb->wqbuf_lastidx;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson wqbuf_firstidx = acb->wqbuf_firstidx;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (wqbuf_lastidx != wqbuf_firstidx) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct scsi_arq_status *arq_status;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_post_ioctldata2iop(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arq_status =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (struct scsi_arq_status *)(intptr_t)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (pkt->pkt_scbp);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bzero((caddr_t)arq_status,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct scsi_arq_status));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arq_status->sts_rqpkt_reason = CMD_CMPLT;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arq_status->sts_rqpkt_state = (STATE_GOT_BUS |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson STATE_GOT_TARGET |STATE_SENT_CMD |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson STATE_XFERRED_DATA | STATE_GOT_STATUS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arq_status->sts_rqpkt_statistics = pkt->pkt_statistics;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arq_status->sts_rqpkt_resid = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (&arq_status->sts_sensedata != NULL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct scsi_extended_sense *sts_sensedata;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata = &arq_status->sts_sensedata;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* has error report sensedata */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_code = 0x0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_valid = 0x01;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_key = KEY_ILLEGAL_REQUEST;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* AdditionalSenseLength */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_add_len = 0x0A;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* AdditionalSenseCode */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_add_code = 0x20;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retvalue = ARCMSR_MESSAGE_FAIL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson my_empty_len = (wqbuf_firstidx-wqbuf_lastidx - 1) &
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (ARCMSR_MAX_QBUFFER - 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (my_empty_len >= user_len) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while (user_len > 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pQbuffer =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &acb->wqbuffer[acb->wqbuf_lastidx];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) memcpy(pQbuffer,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ptmpuserbuffer, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->wqbuf_lastidx++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->wqbuf_lastidx %=
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MAX_QBUFFER;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ptmpuserbuffer++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson user_len--;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->acb_flags &
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ACB_F_MESSAGE_WQBUFFER_CLEARED) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags &=
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_post_ioctldata2iop(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct scsi_arq_status *arq_status;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* has error report sensedata */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arq_status =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (struct scsi_arq_status *)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (intptr_t)(pkt->pkt_scbp);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bzero((caddr_t)arq_status,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct scsi_arq_status));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arq_status->sts_rqpkt_reason = CMD_CMPLT;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arq_status->sts_rqpkt_state = (STATE_GOT_BUS |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson STATE_GOT_TARGET |STATE_SENT_CMD |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson STATE_XFERRED_DATA | STATE_GOT_STATUS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arq_status->sts_rqpkt_statistics =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_statistics;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arq_status->sts_rqpkt_resid = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (&arq_status->sts_sensedata != NULL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct scsi_extended_sense
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *sts_sensedata;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &arq_status->sts_sensedata;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* has error report sensedata */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_code = 0x0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_valid = 0x01;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_key =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson KEY_ILLEGAL_REQUEST;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* AdditionalSenseLength */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_add_len = 0x0A;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* AdditionalSenseCode */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sts_sensedata->es_add_code = 0x20;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retvalue = ARCMSR_MESSAGE_FAIL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson kmem_free(ver_addr, MSGDATABUFLEN);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_MESSAGE_CLEAR_RQBUFFER:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pQbuffer = acb->rqbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop_message_read(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->rqbuf_firstidx = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->rqbuf_lastidx = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pcmdmessagefld->cmdmessage.ReturnCode =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_RETURNCODE_OK;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_MESSAGE_CLEAR_WQBUFFER:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pQbuffer = acb->wqbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop_message_read(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ACB_F_MESSAGE_WQBUFFER_READ);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->wqbuf_firstidx = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->wqbuf_lastidx = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pcmdmessagefld->cmdmessage.ReturnCode =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_RETURNCODE_OK;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop_message_read(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ACB_F_MESSAGE_RQBUFFER_CLEARED |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ACB_F_MESSAGE_WQBUFFER_READ);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->rqbuf_firstidx = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->rqbuf_lastidx = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->wqbuf_firstidx = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->wqbuf_lastidx = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pQbuffer = acb->rqbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) memset(pQbuffer, 0, sizeof (struct QBUFFER));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pQbuffer = acb->wqbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) memset(pQbuffer, 0, sizeof (struct QBUFFER));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pcmdmessagefld->cmdmessage.ReturnCode =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_RETURNCODE_OK;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_MESSAGE_REQUEST_RETURN_CODE_3F:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pcmdmessagefld->cmdmessage.ReturnCode =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_RETURNCODE_3F;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Not supported - ARCMSR_MESSAGE_SAY_HELLO
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_MESSAGE_SAY_GOODBYE:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop_parking(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->adapter_type == ACB_ADAPTER_TYPE_A) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_flush_hba_cache(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_flush_hbb_cache(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson default:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retvalue = ARCMSR_MESSAGE_FAIL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonmessage_out:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (retvalue);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_cb_ioctl(dev_t dev, int ioctl_cmd, intptr_t arg, int mode,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cred_t *credp, int *rvalp) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#ifndef __lock_lint
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson _NOTE(ARGUNUSED(rvalp))
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson#endif
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ACB *acb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CMD_MESSAGE_FIELD *pktioctlfld;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int retvalue = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int instance = getminor(dev);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (instance < 0)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (ENXIO);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (secpolicy_sys_config(credp, B_FALSE) != 0)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (EPERM);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb = ddi_get_soft_state(arcmsr_soft_state, instance);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb == NULL)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (ENXIO);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pktioctlfld = kmem_zalloc(sizeof (struct CMD_MESSAGE_FIELD),
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson KM_SLEEP);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (pktioctlfld == NULL)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (ENXIO);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * if we got here, we either are a 64-bit app in a 64-bit kernel
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * or a 32-bit app in a 32-bit kernel. Either way, we can just
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * copy in the args without any special conversions.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_enter(&acb->ioctl_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_copyin((void *)arg, pktioctlfld,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct CMD_MESSAGE_FIELD), mode) != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retvalue = ENXIO;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto ioctl_out;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (memcmp(pktioctlfld->cmdmessage.Signature, "ARCMSR", 6) != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* validity check */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retvalue = ENXIO;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto ioctl_out;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (ioctl_cmd) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_MESSAGE_READ_RQBUFFER:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson unsigned long *ver_addr;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t *pQbuffer, *ptmpQbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int32_t allxfer_len = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ver_addr = kmem_zalloc(MSGDATABUFLEN, KM_SLEEP);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ver_addr == NULL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retvalue = ENXIO;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto ioctl_out;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ptmpQbuffer = (uint8_t *)ver_addr;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while ((acb->rqbuf_firstidx != acb->rqbuf_lastidx) &&
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (allxfer_len < (MSGDATABUFLEN - 1))) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* copy READ QBUFFER to srb */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pQbuffer = &acb->rqbuffer[acb->rqbuf_firstidx];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) memcpy(ptmpQbuffer, pQbuffer, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->rqbuf_firstidx++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* if last index number set it to 0 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->rqbuf_firstidx %= ARCMSR_MAX_QBUFFER;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ptmpQbuffer++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson allxfer_len++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct QBUFFER *prbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t *pQbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t *iop_data;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int32_t iop_len;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson prbuffer = arcmsr_get_iop_rqbuffer(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_data = (uint8_t *)prbuffer->data;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_len = (int32_t)prbuffer->data_len;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * this iop data does no chance to make me overflow
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * again here, so just do it
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while (iop_len > 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pQbuffer = &acb->rqbuffer[acb->rqbuf_lastidx];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) memcpy(pQbuffer, iop_data, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->rqbuf_lastidx++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* if last index number set it to 0 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->rqbuf_lastidx %= ARCMSR_MAX_QBUFFER;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_data++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_len--;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* let IOP know data has been read */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop_message_read(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) memcpy(pktioctlfld->messagedatabuffer,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (uint8_t *)ver_addr, allxfer_len);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pktioctlfld->cmdmessage.Length = allxfer_len;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pktioctlfld->cmdmessage.ReturnCode =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_RETURNCODE_OK;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_copyout(pktioctlfld, (void *)arg,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct CMD_MESSAGE_FIELD), mode) != 0)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retvalue = ENXIO;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson kmem_free(ver_addr, MSGDATABUFLEN);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_MESSAGE_WRITE_WQBUFFER:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson unsigned long *ver_addr;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int32_t my_empty_len, user_len;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int32_t wqbuf_firstidx, wqbuf_lastidx;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t *pQbuffer, *ptmpuserbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ver_addr = kmem_zalloc(MSGDATABUFLEN, KM_SLEEP);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ver_addr == NULL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retvalue = ENXIO;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto ioctl_out;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ptmpuserbuffer = (uint8_t *)ver_addr;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson user_len = pktioctlfld->cmdmessage.Length;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) memcpy(ptmpuserbuffer,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pktioctlfld->messagedatabuffer, user_len);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * check ifdata xfer length of this request will overflow
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * my array qbuffer
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson wqbuf_lastidx = acb->wqbuf_lastidx;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson wqbuf_firstidx = acb->wqbuf_firstidx;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (wqbuf_lastidx != wqbuf_firstidx) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_post_ioctldata2iop(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pktioctlfld->cmdmessage.ReturnCode =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_RETURNCODE_ERROR;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson my_empty_len = (wqbuf_firstidx - wqbuf_lastidx - 1)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson & (ARCMSR_MAX_QBUFFER - 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (my_empty_len >= user_len) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while (user_len > 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* copy srb data to wqbuffer */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pQbuffer =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &acb->wqbuffer[acb->wqbuf_lastidx];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) memcpy(pQbuffer,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ptmpuserbuffer, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->wqbuf_lastidx++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* iflast index number set it to 0 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->wqbuf_lastidx %=
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MAX_QBUFFER;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ptmpuserbuffer++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson user_len--;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* post first Qbuffer */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->acb_flags &
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ACB_F_MESSAGE_WQBUFFER_CLEARED) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags &=
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_post_ioctldata2iop(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pktioctlfld->cmdmessage.ReturnCode =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_RETURNCODE_OK;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pktioctlfld->cmdmessage.ReturnCode =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_RETURNCODE_ERROR;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_copyout(pktioctlfld, (void *)arg,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct CMD_MESSAGE_FIELD), mode) != 0)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retvalue = ENXIO;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson kmem_free(ver_addr, MSGDATABUFLEN);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_MESSAGE_CLEAR_RQBUFFER:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t *pQbuffer = acb->rqbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop_message_read(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->rqbuf_firstidx = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->rqbuf_lastidx = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bzero(pQbuffer, ARCMSR_MAX_QBUFFER);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* report success */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pktioctlfld->cmdmessage.ReturnCode =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_RETURNCODE_OK;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_copyout(pktioctlfld, (void *)arg,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct CMD_MESSAGE_FIELD), mode) != 0)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retvalue = ENXIO;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_MESSAGE_CLEAR_WQBUFFER:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t *pQbuffer = acb->wqbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop_message_read(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ACB_F_MESSAGE_WQBUFFER_READ);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->wqbuf_firstidx = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->wqbuf_lastidx = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bzero(pQbuffer, ARCMSR_MAX_QBUFFER);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* report success */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pktioctlfld->cmdmessage.ReturnCode =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_RETURNCODE_OK;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_copyout(pktioctlfld, (void *)arg,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct CMD_MESSAGE_FIELD), mode) != 0)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retvalue = ENXIO;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t *pQbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop_message_read(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ACB_F_MESSAGE_RQBUFFER_CLEARED |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ACB_F_MESSAGE_WQBUFFER_READ);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->rqbuf_firstidx = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->rqbuf_lastidx = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->wqbuf_firstidx = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->wqbuf_lastidx = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pQbuffer = acb->rqbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bzero(pQbuffer, sizeof (struct QBUFFER));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pQbuffer = acb->wqbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bzero(pQbuffer, sizeof (struct QBUFFER));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* report success */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pktioctlfld->cmdmessage.ReturnCode =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_RETURNCODE_OK;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_copyout(pktioctlfld, (void *)arg,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct CMD_MESSAGE_FIELD), mode) != 0)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retvalue = ENXIO;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_MESSAGE_REQUEST_RETURN_CODE_3F:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pktioctlfld->cmdmessage.ReturnCode =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_RETURNCODE_3F;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_copyout(pktioctlfld, (void *)arg,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct CMD_MESSAGE_FIELD), mode) != 0)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retvalue = ENXIO;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Not supported: ARCMSR_MESSAGE_SAY_HELLO */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_MESSAGE_SAY_GOODBYE:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop_parking(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->adapter_type == ACB_ADAPTER_TYPE_A) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_flush_hba_cache(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_flush_hbb_cache(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson default:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retvalue = ENOTTY;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonioctl_out:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson kmem_free(pktioctlfld, sizeof (struct CMD_MESSAGE_FIELD));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_exit(&acb->ioctl_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (retvalue);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic struct CCB *
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_get_freeccb(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *ccb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int workingccb_startindex, workingccb_doneindex;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_enter(&acb->workingQ_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson workingccb_doneindex = acb->workingccb_doneindex;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson workingccb_startindex = acb->workingccb_startindex;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb = acb->ccbworkingQ[workingccb_startindex];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson workingccb_startindex++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson workingccb_startindex %= ARCMSR_MAX_FREECCB_NUM;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (workingccb_doneindex != workingccb_startindex) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->workingccb_startindex = workingccb_startindex;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb = NULL;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_exit(&acb->workingQ_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_seek_cmd2abort(struct ACB *acb,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct scsi_pkt *abortpkt) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *ccb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t intmask_org = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int i = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->num_aborts++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (abortpkt == NULL) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * if abortpkt is NULL, the upper layer needs us
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * to abort all commands
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->ccboutstandingcount != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* disable all outbound interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson intmask_org = arcmsr_disable_allintr(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* clear and abort all outbound posted Q */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_done4abort_postqueue(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* talk to iop 331 outstanding command aborted */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->adapter_type == ACB_ADAPTER_TYPE_A) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_abort_hba_allcmd(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_abort_hbb_allcmd(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb = acb->pccb_pool[i];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->startdone == ARCMSR_CCB_START) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * this ccb will complete at
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * hwinterrupt
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->startdone = ARCMSR_CCB_ABORTED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_reason = CMD_ABORTED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_statistics |=
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson STAT_ABORTED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_ccb_complete(ccb, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * enable outbound Post Queue, outbound
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * doorbell Interrupt
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_enable_allintr(acb, intmask_org);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_SUCCESS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * It is the upper layer do abort command this lock
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * just prior to calling us.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * First determine if we currently own this command.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Start by searching the device queue. If not found
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * at all, and the system wanted us to just abort the
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * command returnsuccess.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->ccboutstandingcount != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb = acb->pccb_pool[i];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->startdone == ARCMSR_CCB_START) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->pkt == abortpkt) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->startdone =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_CCB_ABORTED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto abort_outstanding_cmd;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonabort_outstanding_cmd:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* disable all outbound interrupts */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson intmask_org = arcmsr_disable_allintr(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->adapter_type == ACB_ADAPTER_TYPE_A) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_polling_hba_ccbdone(acb, ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_polling_hbb_ccbdone(acb, ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* enable outbound Post Queue, outbound doorbell Interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_enable_allintr(acb, intmask_org);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_SUCCESS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_pcidev_disattach(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *ccb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int i = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* disable all outbound interrupts */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) arcmsr_disable_allintr(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* stop adapter background rebuild */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->adapter_type == ACB_ADAPTER_TYPE_A) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_stop_hba_bgrb(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_flush_hba_cache(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_stop_hbb_bgrb(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_flush_hbb_cache(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* abort all outstanding commands */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags |= ACB_F_SCSISTOPADAPTER;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags &= ~ACB_F_IOP_INITED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->ccboutstandingcount != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* clear and abort all outbound posted Q */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_done4abort_postqueue(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* talk to iop 331 outstanding command aborted */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->adapter_type == ACB_ADAPTER_TYPE_A) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_abort_hba_allcmd(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_abort_hbb_allcmd(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb = acb->pccb_pool[i];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->startdone == ARCMSR_CCB_START) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->startdone = ARCMSR_CCB_ABORTED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_reason = CMD_ABORTED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_statistics |= STAT_ABORTED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_ccb_complete(ccb, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/* get firmware miscellaneous data */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_get_hba_config(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson char *acb_firm_model;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson char *acb_firm_version;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson char *iop_firm_model;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson char *iop_firm_version;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int count;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb_firm_model = acb->firm_model;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb_firm_version = acb->firm_version;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* firm_model, 15 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_firm_model = (char *)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (&phbamu->msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* firm_version, 17 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_firm_version =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (char *)(&phbamu->msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0, &phbamu->inbound_msgaddr0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_INBOUND_MESG0_GET_CONFIG);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!arcmsr_hba_wait_msgint_ready(acb))
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: timeout while waiting for adapter firmware "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "miscellaneous data",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson count = 8;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while (count) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *acb_firm_model =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_READ8(acb->reg_mu_acc_handle0, iop_firm_model);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb_firm_model++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_firm_model++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson count--;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson count = 16;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while (count) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *acb_firm_version =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_READ8(acb->reg_mu_acc_handle0, iop_firm_version);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb_firm_version++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_firm_version++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson count--;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT, "arcmsr%d: ARECA RAID FIRMWARE VERSION %s",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info), acb->firm_version);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* firm_request_len, 1 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->firm_request_len = CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->msgcode_rwbuffer[1]);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* firm_numbers_queue, 2 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->firm_numbers_queue = CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->msgcode_rwbuffer[2]);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* firm_sdram_size, 3 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->firm_sdram_size = CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->msgcode_rwbuffer[3]);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* firm_ide_channels, 4 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->firm_ide_channels = CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->msgcode_rwbuffer[4]);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/* get firmware miscellaneous data */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_get_hbb_config(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson char *acb_firm_model;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson char *acb_firm_version;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson char *iop_firm_model;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson char *iop_firm_version;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int count;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb_firm_model = acb->firm_model;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb_firm_version = acb->firm_version;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* firm_model, 15 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_firm_model = (char *)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (&phbbmu->hbb_rwbuffer->msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* firm_version, 17 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_firm_version = (char *)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (&phbbmu->hbb_rwbuffer->msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->drv2iop_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_GET_CONFIG);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!arcmsr_hbb_wait_msgint_ready(acb))
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: timeout while waiting for adapter firmware "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "miscellaneous data",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson count = 8;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while (count) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *acb_firm_model = CHIP_REG_READ8(acb->reg_mu_acc_handle1,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_firm_model);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb_firm_model++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_firm_model++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson count--;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson count = 16;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while (count) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *acb_firm_version = CHIP_REG_READ8(acb->reg_mu_acc_handle1,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_firm_version);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb_firm_version++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_firm_version++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson count--;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT, "arcmsr%d: ARECA RAID FIRMWARE VERSION %s",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info), acb->firm_version);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* firm_request_len, 1 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->firm_request_len = CHIP_REG_READ32(acb->reg_mu_acc_handle1,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_rwbuffer->msgcode_rwbuffer[1]);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* firm_numbers_queue, 2 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->firm_numbers_queue = CHIP_REG_READ32(acb->reg_mu_acc_handle1,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_rwbuffer->msgcode_rwbuffer[2]);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* firm_sdram_size, 3 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->firm_sdram_size = CHIP_REG_READ32(acb->reg_mu_acc_handle1,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_rwbuffer->msgcode_rwbuffer[3]);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* firm_ide_channels, 4 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->firm_ide_channels = CHIP_REG_READ32(acb->reg_mu_acc_handle1,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_rwbuffer->msgcode_rwbuffer[4]);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/* start background rebuild */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_start_hba_bgrb(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags |= ACB_F_MSG_START_BGRB;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!arcmsr_hba_wait_msgint_ready(acb))
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: timeout while waiting for background "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "rebuild to start",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_start_hbb_bgrb(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags |= ACB_F_MSG_START_BGRB;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->drv2iop_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_START_BGRB);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!arcmsr_hbb_wait_msgint_ready(acb))
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: timeout while waiting for background "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "rebuild to start",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_polling_hba_ccbdone(struct ACB *acb, struct CCB *poll_ccb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *ccb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t flag_ccb, outbound_intstatus;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t poll_ccb_done = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t poll_count = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonpolling_ccb_retry:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson poll_count++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson outbound_intstatus = CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->outbound_intstatus) & acb->outbound_int_enable;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0, &phbamu->outbound_intstatus,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson outbound_intstatus); /* clear interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Use correct offset and size for syncing */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_dma_sync(acb->ccbs_pool_handle, 0, acb->dma_sync_size,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_DMA_SYNC_FORKERNEL) != DDI_SUCCESS)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*LINTED*/
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while (1) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((flag_ccb = CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->outbound_queueport)) == 0xFFFFFFFF) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (poll_ccb_done) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* chip FIFO no ccb for completion already */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson drv_usecwait(25000);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (poll_count > 100) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto polling_ccb_retry;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* check ifcommand done with no error */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb = (struct CCB *)(acb->vir2phy_offset +
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (flag_ccb << 5)); /* frame must be 32 bytes aligned */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson poll_ccb_done = (ccb == poll_ccb) ? 1 : 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((ccb->acb != acb) ||
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (ccb->startdone != ARCMSR_CCB_START)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->startdone == ARCMSR_CCB_ABORTED) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_reason = CMD_ABORTED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_statistics |= STAT_ABORTED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_ccb_complete(ccb, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson continue;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: polling op got "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "unexpected ccb command done",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson continue;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_report_ccb_state(acb, ccb, flag_ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } /* drain reply FIFO */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_polling_hbb_ccbdone(struct ACB *acb,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *poll_ccb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *ccb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t flag_ccb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t poll_ccb_done = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t poll_count = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int index;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonpolling_ccb_retry:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson poll_count++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* clear doorbell interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->iop2drv_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_DOORBELL_INT_CLEAR_PATTERN);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Use correct offset and size for syncing */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_dma_sync(acb->ccbs_pool_handle, 0, acb->dma_sync_size,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_DMA_SYNC_FORKERNEL) != DDI_SUCCESS)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*LINTED*/
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while (1) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson index = phbbmu->doneq_index;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((flag_ccb = phbbmu->done_qbuffer[index]) == 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (poll_ccb_done) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* chip FIFO no ccb for completion already */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson drv_usecwait(25000);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (poll_count > 100)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson goto polling_ccb_retry;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu->done_qbuffer[index] = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson index++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* if last index number set it to 0 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson index %= ARCMSR_MAX_HBB_POSTQUEUE;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu->doneq_index = index;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* check if command done with no error */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* frame must be 32 bytes aligned */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb = (struct CCB *)(acb->vir2phy_offset +
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (flag_ccb << 5));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson poll_ccb_done = (ccb == poll_ccb) ? 1 : 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->startdone == ARCMSR_CCB_ABORTED) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_reason = CMD_ABORTED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_statistics |= STAT_ABORTED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_ccb_complete(ccb, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson continue;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: polling op got"
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "unexpect ccb command done",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson continue;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_report_ccb_state(acb, ccb, flag_ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } /* drain reply FIFO */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Function: arcmsr_tran_start(9E)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Description: Transport the command in pktp to the target device.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * The command is not finished when this returns, only
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * sent to the target; arcmsr_interrupt will call
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * (*pktp->pkt_comp)(pktp) when the target device has done.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson *
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Input: struct scsi_address *ap, struct scsi_pkt *pktp
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Output: TRAN_ACCEPT if pkt is OK and not driver not busy
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * TRAN_BUSY if driver is
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * TRAN_BADPKT if pkt is invalid
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_tran_start(struct scsi_address *ap, struct scsi_pkt *pkt) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ACB *acb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *ccb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int target = ap->a_target;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int lun = ap->a_lun;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb = (struct ACB *)ap->a_hba_tran->tran_hba_private;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb = pkt->pkt_ha_private;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((ccb->ccb_flags & CCB_FLAG_DMAVALID) &&
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (ccb->ccb_flags & DDI_DMA_CONSISTENT))
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) ddi_dma_sync(ccb->pkt_dma_handle, ccb->pkt_dma_offset,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dma_len, DDI_DMA_SYNC_FORDEV);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb->startdone == ARCMSR_CCB_UNBUILD)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_build_ccb(ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->acb_flags & ACB_F_BUS_RESET) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: bus reset returned busy",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_reason = CMD_RESET;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_statistics |= STAT_BUS_RESET;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson STATE_SENT_CMD | STATE_GOT_STATUS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((ccb->ccb_flags & CCB_FLAG_DMACONSISTENT) &&
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (pkt->pkt_state & STATE_XFERRED_DATA))
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) ddi_dma_sync(ccb->pkt_dma_handle,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dma_offset, ccb->pkt_dma_len,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_DMA_SYNC_FORCPU);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (pkt->pkt_comp)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (*pkt->pkt_comp)(pkt);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (TRAN_ACCEPT);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->devstate[target][lun] == ARECA_RAID_GONE) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t block_cmd;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson block_cmd = pkt->pkt_cdbp[0] & 0x0f;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (block_cmd == 0x08 || block_cmd == 0x0a) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: block read/write command while raid"
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "volume missing (cmd %02x for target %d lun %d)",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info),
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson block_cmd, target, lun);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_reason = CMD_TIMEOUT;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_statistics |= CMD_TIMEOUT;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson STATE_SENT_CMD | STATE_GOT_STATUS);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((ccb->ccb_flags & CCB_FLAG_DMACONSISTENT) &&
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (pkt->pkt_state & STATE_XFERRED_DATA))
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) ddi_dma_sync(ccb->pkt_dma_handle,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt_dma_offset, ccb->pkt_dma_len,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_DMA_SYNC_FORCPU);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (pkt->pkt_comp)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (*pkt->pkt_comp)(pkt);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (TRAN_ACCEPT);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* IMPORTANT: Target 16 is a virtual device for iop message transfer */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (target == 16) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct buf *bp = ccb->bp;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t scsicmd = pkt->pkt_cdbp[0];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (scsicmd) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCMD_INQUIRY: {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (lun != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_reason = CMD_TIMEOUT;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_statistics |= STAT_TIMEOUT;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_ccb_complete(ccb, 0);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (TRAN_ACCEPT);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (bp && bp->b_un.b_addr && bp->b_bcount) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t inqdata[36];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* The EVDP and pagecode is not supported */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (pkt->pkt_cdbp[1] || pkt->pkt_cdbp[2]) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson inqdata[1] = 0xFF;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson inqdata[2] = 0x00;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Periph Qualifier & Periph Dev Type */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson inqdata[0] = DTYPE_PROCESSOR;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* rem media bit & Dev Type Modifier */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson inqdata[1] = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* ISO, ECMA, & ANSI versions */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson inqdata[2] = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* length of additional data */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson inqdata[4] = 31;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Vendor Identification */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bcopy("Areca ",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &inqdata[8], VIDLEN);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Product Identification */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bcopy("RAID controller ",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &inqdata[16], PIDLEN);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Product Revision */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bcopy(&inqdata[32],
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "R001", REVLEN);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (bp->b_flags & (B_PHYS | B_PAGEIO))
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bp_mapin(bp);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) memcpy(bp->b_un.b_addr,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson inqdata, sizeof (inqdata));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_state |= STATE_XFERRED_DATA;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_ccb_complete(ccb, 0);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (TRAN_ACCEPT);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCMD_WRITE_BUFFER:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case SCMD_READ_BUFFER: {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (arcmsr_iop_message_xfer(acb, pkt)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* error just for retry */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_reason = CMD_TRAN_ERR;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_statistics |= STAT_TERMINATED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_state |= STATE_XFERRED_DATA;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_ccb_complete(ccb, 0);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (TRAN_ACCEPT);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson default:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb->pkt->pkt_state |= STATE_XFERRED_DATA;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_ccb_complete(ccb, 0);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (TRAN_ACCEPT);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->ccboutstandingcount >= ARCMSR_MAX_OUTSTANDING_CMD) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: too many outstanding commands (%d > %d)",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info),
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->ccboutstandingcount,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MAX_OUTSTANDING_CMD);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (TRAN_BUSY);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else if (arcmsr_post_ccb(acb, ccb) == DDI_FAILURE) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: post failure, ccboutstandingcount = %d",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info),
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->ccboutstandingcount);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (TRAN_BUSY);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (TRAN_ACCEPT);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Function: arcmsr_tran_abort(9E)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * SCSA interface routine to abort pkt(s) in progress.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Aborts the pkt specified. If NULL pkt, aborts ALL pkts.
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Output: Return 1 if success
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Return 0 if failure
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_tran_abort(struct scsi_address *ap, struct scsi_pkt *abortpkt) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ACB *acb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int return_code;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb = (struct ACB *)ap->a_hba_tran->tran_hba_private;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: tran_abort called for target %d lun %d",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info), ap->a_target, ap->a_lun);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while (acb->ccboutstandingcount != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson drv_usecwait(10000);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_enter(&acb->acb_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return_code = arcmsr_seek_cmd2abort(acb, abortpkt);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_exit(&acb->acb_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (return_code != DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: abort command failed for target %d lun %d",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info),
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ap->a_target, ap->a_lun);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (0);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Function: arcmsr_tran_reset(9E)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * SCSA interface routine to perform scsi resets on either
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * a specified target or the bus (default).
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Output: Return 1 if success
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Return 0 if failure
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_tran_reset(struct scsi_address *ap, int level) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ACB *acb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int return_code = 1;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int retry = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Are we in the middle of dumping core? */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_in_panic())
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (return_code);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb = (struct ACB *)ap->a_hba_tran->tran_hba_private;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: tran reset (level 0x%x) called "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "for target %d lun %d",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info), level,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ap->a_target, ap->a_lun);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_enter(&acb->acb_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while ((acb->ccboutstandingcount > 0) && (retry < 400)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) arcmsr_interrupt((caddr_t)acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson drv_usecwait(25000);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson retry++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (level) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case RESET_ALL: /* level 1 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->num_resets++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags |= ACB_F_BUS_RESET;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop_reset(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags &= ~ACB_F_BUS_RESET;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return_code = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case RESET_TARGET: /* level 0 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: target reset not supported",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return_code = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson default:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return_code = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson mutex_exit(&acb->acb_mutex);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (return_code);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_log(struct ACB *acb, int level, char *fmt, ...) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson char buf[256];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson va_list ap;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson va_start(ap, fmt);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) vsprintf(buf, fmt, ap);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson va_end(ap);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson scsi_log(acb ? acb->dev_info : NULL, "arcmsr", level, "%s", buf);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_iop2drv_data_wrote_handle(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct QBUFFER *prbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t *pQbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t *iop_data;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int my_empty_len, iop_len;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int rqbuf_firstidx, rqbuf_lastidx;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* check this iop data if overflow my rqbuffer */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson rqbuf_lastidx = acb->rqbuf_lastidx;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson rqbuf_firstidx = acb->rqbuf_firstidx;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson prbuffer = arcmsr_get_iop_rqbuffer(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_data = (uint8_t *)prbuffer->data;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_len = prbuffer->data_len;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson my_empty_len = (rqbuf_firstidx-rqbuf_lastidx - 1) &
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (ARCMSR_MAX_QBUFFER - 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (my_empty_len >= iop_len) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while (iop_len > 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pQbuffer = &acb->rqbuffer[rqbuf_lastidx];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) memcpy(pQbuffer, iop_data, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson rqbuf_lastidx++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* if last index number set it to 0 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson rqbuf_lastidx %= ARCMSR_MAX_QBUFFER;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_data++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_len--;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->rqbuf_lastidx = rqbuf_lastidx;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop_message_read(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* signature, let IOP know data has been read */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_iop2drv_data_read_handle(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * check if there are any mail packages from user space program
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * in my post bag, now is the time to send them into Areca's firmware
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->wqbuf_firstidx != acb->wqbuf_lastidx) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t *pQbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct QBUFFER *pwbuffer;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint8_t *iop_data;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int allxfer_len = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pwbuffer = arcmsr_get_iop_wqbuffer(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_data = (uint8_t *)pwbuffer->data;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while ((acb->wqbuf_firstidx != acb->wqbuf_lastidx) &&
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (allxfer_len < 124)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pQbuffer = &acb->wqbuffer[acb->wqbuf_firstidx];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) memcpy(iop_data, pQbuffer, 1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->wqbuf_firstidx++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* if last index number set it to 0 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->wqbuf_firstidx %= ARCMSR_MAX_QBUFFER;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson iop_data++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson allxfer_len++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pwbuffer->data_len = allxfer_len;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * push inbound doorbell, tell iop driver data write ok
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * await reply on next hwinterrupt for next Qbuffer post
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop_message_wrote(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->wqbuf_firstidx == acb->wqbuf_lastidx)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_hba_doorbell_isr(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t outbound_doorbell;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Maybe here we need to check wrqbuffer_lock is locked or not
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * DOORBELL: ding! dong!
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * check if there are any mail need to pack from firmware
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson outbound_doorbell = CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->outbound_doorbell);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* clear doorbell interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->outbound_doorbell, outbound_doorbell);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop2drv_data_wrote_handle(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop2drv_data_read_handle(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_hba_postqueue_isr(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t flag_ccb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* areca cdb command done */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Use correct offset and size for syncing */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) ddi_dma_sync(acb->ccbs_pool_handle, 0, acb->dma_sync_size,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_DMA_SYNC_FORKERNEL);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while ((flag_ccb = CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->outbound_queueport)) != 0xFFFFFFFF) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* check if command done with no error */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_drain_donequeue(acb, flag_ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } /* drain reply FIFO */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_hbb_postqueue_isr(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int index;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t flag_ccb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* areca cdb command done */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson index = phbbmu->doneq_index;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson while ((flag_ccb = phbbmu->done_qbuffer[index]) != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu->done_qbuffer[index] = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson index++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* if last index number set it to 0 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson index %= ARCMSR_MAX_HBB_POSTQUEUE;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu->doneq_index = index;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* check if command done with no error */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_drain_donequeue(acb, flag_ccb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } /* drain reply FIFO */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic uint_t
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_handle_hba_isr(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t outbound_intstatus;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson outbound_intstatus = CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->outbound_intstatus) & acb->outbound_int_enable;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!outbound_intstatus)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* it must be a shared irq */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_INTR_UNCLAIMED);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0, &phbamu->outbound_intstatus,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson outbound_intstatus); /* clear interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* MU doorbell interrupts */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_hba_doorbell_isr(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* MU post queue interrupts */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_hba_postqueue_isr(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * The following block is commented out pending confirmation from
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Areca whether it is or is not truly required
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* MU message interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * if (outbound_intstatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * arcmsr_hba_message_isr(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_INTR_CLAIMED);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic uint_t
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_handle_hbb_isr(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t outbound_doorbell;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson outbound_doorbell = CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->iop2drv_doorbell) & acb->outbound_int_enable;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!outbound_doorbell)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* it must be a shared irq */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_INTR_UNCLAIMED);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* clear doorbell interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->iop2drv_doorbell, ~outbound_doorbell);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* wait a cycle */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->iop2drv_doorbell);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->drv2iop_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_DRV2IOP_END_OF_INTERRUPT);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* MU ioctl transfer doorbell interrupts */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop2drv_data_wrote_handle(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_iop2drv_data_read_handle(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* MU post queue interrupts */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_hbb_postqueue_isr(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * The following block is commented out pending confirmation from
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * Areca whether it is or is not truly required
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* MU message interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * if (outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * arcmsr_hbb_message_isr(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_INTR_CLAIMED);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic uint_t
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_interrupt(caddr_t arg) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct ACB *acb = (struct ACB *)(intptr_t)arg;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (acb->adapter_type) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_A:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (arcmsr_handle_hba_isr(acb));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_B:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (arcmsr_handle_hbb_isr(acb));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson default:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: unknown adapter type (%d)",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info), acb->adapter_type);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_INTR_UNCLAIMED);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_wait_firmware_ready(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t firmware_state;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson firmware_state = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (acb->adapter_type) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_A:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson do {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson firmware_state =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->outbound_msgaddr1);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } while ((firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson == 0);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_B:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson do {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson firmware_state =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->iop2drv_doorbell);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } while ((firmware_state & ARCMSR_MESSAGE_FIRMWARE_OK) == 0);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->drv2iop_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_DRV2IOP_END_OF_INTERRUPT);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_clear_doorbell_queue_buffer(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (acb->adapter_type) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_A:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t outbound_doorbell;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* empty doorbell Qbuffer if door bell rung */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson outbound_doorbell = CHIP_REG_READ32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->outbound_doorbell);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* clear doorbell interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->outbound_doorbell, outbound_doorbell);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->inbound_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_B:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* clear interrupt and message state */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->iop2drv_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_INT_CLEAR_PATTERN);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->drv2iop_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_DRV2IOP_DATA_READ_OK);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* let IOP know data has been read */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic uint32_t
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_iop_confirm(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson unsigned long ccb_phyaddr;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t ccb_phyaddr_hi32;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * here we need to tell iop 331 about our freeccb.HighPart
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * if freeccb.HighPart is non-zero
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb_phyaddr = (unsigned long)acb->ccb_cookie.dmac_address;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb_phyaddr_hi32 = (uint32_t)((ccb_phyaddr >> 16) >> 16);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (acb->adapter_type) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_A:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ccb_phyaddr_hi32 != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBA_msgUnit *phbamu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbamu = (struct HBA_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->msgcode_rwbuffer[0],
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_SIGNATURE_SET_CONFIG);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->msgcode_rwbuffer[1], ccb_phyaddr_hi32);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbamu->inbound_msgaddr0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_INBOUND_MESG0_SET_CONFIG);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!arcmsr_hba_wait_msgint_ready(acb)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: timeout setting ccb high "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "physical address",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (FALSE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* if adapter is type B, set window of "post command queue" */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case ACB_ADAPTER_TYPE_B:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t post_queue_phyaddr;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu->postq_index = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu->doneq_index = 0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->drv2iop_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_SET_POST_WINDOW);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!arcmsr_hbb_wait_msgint_ready(acb)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: timeout setting post command "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "queue window",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (FALSE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson post_queue_phyaddr = ccb_phyaddr +
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MAX_FREECCB_NUM *
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct CCB)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson + ARCOFFSET(struct HBB_msgUnit, post_qbuffer);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* driver "set config" signature */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle1,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_rwbuffer->msgcode_rwbuffer[0],
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_SIGNATURE_SET_CONFIG);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* normal should be zero */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle1,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_rwbuffer->msgcode_rwbuffer[1],
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb_phyaddr_hi32);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* postQ size (256+8)*4 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle1,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_rwbuffer->msgcode_rwbuffer[2],
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson post_queue_phyaddr);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* doneQ size (256+8)*4 */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle1,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_rwbuffer->msgcode_rwbuffer[3],
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson post_queue_phyaddr+1056);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* ccb maxQ size must be --> [(256+8)*4] */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle1,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_rwbuffer->msgcode_rwbuffer[4], 1056);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->drv2iop_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_SET_CONFIG);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!arcmsr_hbb_wait_msgint_ready(acb)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: timeout setting command queue window",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (FALSE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->drv2iop_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_START_DRIVER_MODE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!arcmsr_hbb_wait_msgint_ready(acb)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: timeout in 'start driver mode'",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (FALSE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson break;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (TRUE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson * ONLY used for Adapter type B
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_enable_eoi_mode(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson CHIP_REG_WRITE32(acb->reg_mu_acc_handle0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &phbbmu->hbb_doorbell->drv2iop_doorbell,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_MESSAGE_ACTIVE_EOI_MODE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!arcmsr_hbb_wait_msgint_ready(acb))
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d (Adapter type B): "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "'iop enable eoi mode' timeout ",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson/* start background rebuild */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic void
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_iop_init(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t intmask_org;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* disable all outbound interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson intmask_org = arcmsr_disable_allintr(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_wait_firmware_ready(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (void) arcmsr_iop_confirm(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* start background rebuild */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->adapter_type == ACB_ADAPTER_TYPE_A) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_get_hba_config(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_start_hba_bgrb(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_get_hbb_config(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_start_hbb_bgrb(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* empty doorbell Qbuffer if door bell rang */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_clear_doorbell_queue_buffer(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (acb->adapter_type == ACB_ADAPTER_TYPE_B)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_enable_eoi_mode(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* enable outbound Post Queue, outbound doorbell Interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_enable_allintr(acb, intmask_org);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags |= ACB_F_IOP_INITED;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonstatic int
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPhersonarcmsr_initialize(struct ACB *acb) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *pccb_tmp;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson size_t allocated_length;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint16_t wval;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t wlval;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint_t intmask_org, count;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson caddr_t arcmsr_ccbs_area;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson unsigned long ccb_phyaddr;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int32_t dma_sync_size;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson int i, id, lun;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->irq = pci_config_get8(acb->pci_acc_handle,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ARCMSR_PCI2PCI_PRIMARY_INTERRUPT_LINE_REG);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson wlval = pci_config_get32(acb->pci_acc_handle, 0);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson wval = (uint16_t)((wlval >> 16) & 0xffff);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (wval == PCI_DEVICE_ID_ARECA_1201) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t *iop_mu_regs_map0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t *iop_mu_regs_map1;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct CCB *freeccb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson struct HBB_msgUnit *phbbmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->adapter_type = ACB_ADAPTER_TYPE_B; /* marvell */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dma_sync_size = (ARCMSR_MAX_FREECCB_NUM*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct CCB) + 0x20) +
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct HBB_msgUnit);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* Allocate memory for the ccb */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((i = ddi_dma_alloc_handle(acb->dev_info,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &arcmsr_ccb_attr, DDI_DMA_SLEEP, NULL,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &acb->ccbs_pool_handle)) != DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (i) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case DDI_DMA_BADATTR:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: ddi_dma_alloc_handle got "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "DDI_DMA_BADATTR",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case DDI_DMA_NORESOURCES:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "ddi_dma_alloc_handle got "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "DDI_DMA_NORESOURCES ",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: ddi_dma_alloc_handle got DDI_FAILURE",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_dma_mem_alloc(acb->ccbs_pool_handle, dma_sync_size,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &acb->dev_acc_attr, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_DMA_SLEEP, NULL, (caddr_t *)&arcmsr_ccbs_area,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &allocated_length, &acb->ccbs_acc_handle)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson != DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_CONT,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: ddi_dma_mem_alloc failed ",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_free_handle(&acb->ccbs_pool_handle);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_dma_addr_bind_handle(acb->ccbs_pool_handle, NULL,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (caddr_t)arcmsr_ccbs_area, dma_sync_size,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson NULL, &acb->ccb_cookie, &count) != DDI_DMA_MAPPED) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: ddi_dma_addr_bind_handle failed",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_mem_free(&acb->ccbs_acc_handle);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_free_handle(&acb->ccbs_pool_handle);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bzero(arcmsr_ccbs_area, dma_sync_size);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson freeccb = (struct CCB *)(intptr_t)arcmsr_ccbs_area;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->pmu = (struct msgUnit *)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &freeccb[ARCMSR_MAX_FREECCB_NUM];
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu = (struct HBB_msgUnit *)acb->pmu;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* setup device register */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_regs_map_setup(acb->dev_info, 1,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (caddr_t *)&iop_mu_regs_map0, 0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct HBB_DOORBELL), &acb->dev_acc_attr,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &acb->reg_mu_acc_handle0) != DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: unable to map PCI device "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "base0 address registers",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* ARCMSR_DRV2IOP_DOORBELL */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu->hbb_doorbell =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (struct HBB_DOORBELL *)iop_mu_regs_map0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_regs_map_setup(acb->dev_info, 2,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (caddr_t *)&iop_mu_regs_map1, 0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct HBB_RWBUFFER), &acb->dev_acc_attr,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &acb->reg_mu_acc_handle1) != DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: unable to map PCI device "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "base1 address registers",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* ARCMSR_MSGCODE_RWBUFFER */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson phbbmu->hbb_rwbuffer =
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (struct HBB_RWBUFFER *)iop_mu_regs_map1;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson } else {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson uint32_t *iop_mu_regs_map0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->adapter_type = ACB_ADAPTER_TYPE_A; /* intel */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson dma_sync_size = ARCMSR_MAX_FREECCB_NUM*
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct CCB) + 0x20;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_regs_map_setup(acb->dev_info, 1,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (caddr_t *)&iop_mu_regs_map0, 0,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson sizeof (struct HBA_msgUnit), &acb->dev_acc_attr,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &acb->reg_mu_acc_handle0) != DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_log(NULL, CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: unable to map registers",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if ((i = ddi_dma_alloc_handle(acb->dev_info, &arcmsr_ccb_attr,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_DMA_SLEEP, NULL, &acb->ccbs_pool_handle)) !=
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson switch (i) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case DDI_DMA_BADATTR:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: ddi_dma_alloc_handle "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "got DDI_DMA_BADATTR",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson case DDI_DMA_NORESOURCES:
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "ddi_dma_alloc_handle got "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "DDI_DMA_NORESOURCES",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "arcmsr%d: ddi_dma_alloc_handle failed",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_dma_mem_alloc(acb->ccbs_pool_handle, dma_sync_size,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &acb->dev_acc_attr, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_DMA_SLEEP, NULL, (caddr_t *)&arcmsr_ccbs_area,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &allocated_length, &acb->ccbs_acc_handle)
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson != DDI_SUCCESS) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: ddi_dma_mem_alloc failed",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_free_handle(&acb->ccbs_pool_handle);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (ddi_dma_addr_bind_handle(acb->ccbs_pool_handle, NULL,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (caddr_t)arcmsr_ccbs_area, dma_sync_size, DDI_DMA_RDWR |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &acb->ccb_cookie,
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson &count) != DDI_DMA_MAPPED) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: ddi_dma_addr_bind_handle "
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson "failed",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_mem_free(&acb->ccbs_acc_handle);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_free_handle(&acb->ccbs_pool_handle);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson bzero(arcmsr_ccbs_area, dma_sync_size);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* ioport base */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->pmu = (struct msgUnit *)(intptr_t)iop_mu_regs_map0;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* here we can not access pci configuration again */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED |
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ACB_F_MESSAGE_RQBUFFER_CLEARED | ACB_F_MESSAGE_WQBUFFER_READ);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* physical address of acb->pccb_pool */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb_phyaddr = acb->ccb_cookie.dmac_address;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (((unsigned long)arcmsr_ccbs_area & 0x1F) != 0) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* ccb address must 32 (0x20) boundary */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_ccbs_area = (caddr_t)((unsigned long)arcmsr_ccbs_area +
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (0x20 - ((unsigned long)arcmsr_ccbs_area & 0x1F)));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb_phyaddr = (unsigned long)ccb_phyaddr +
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (0x20 - ((unsigned long)ccb_phyaddr & 0x1F));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pccb_tmp = (struct CCB *)(intptr_t)arcmsr_ccbs_area;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pccb_tmp->cdb_shifted_phyaddr = ccb_phyaddr >> 5;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pccb_tmp->acb = acb;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->ccbworkingQ[i] = acb->pccb_pool[i] = pccb_tmp;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ccb_phyaddr = ccb_phyaddr + sizeof (struct CCB);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson pccb_tmp++;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->vir2phy_offset = (unsigned long)pccb_tmp -
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson (unsigned long)ccb_phyaddr;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* disable all outbound interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson intmask_org = arcmsr_disable_allintr(acb);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson if (!arcmsr_iop_confirm(acb)) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson cmn_err(CE_WARN, "arcmsr%d: arcmsr_iop_confirm error",
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_get_instance(acb->dev_info));
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_mem_free(&acb->ccbs_acc_handle);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson ddi_dma_free_handle(&acb->ccbs_pool_handle);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (DDI_FAILURE);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson for (id = 0; id < ARCMSR_MAX_TARGETID; id++) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson for (lun = 0; lun < ARCMSR_MAX_TARGETLUN; lun++) {
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson acb->devstate[id][lun] = ARECA_RAID_GONE;
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson }
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson /* enable outbound Post Queue, outbound doorbell Interrupt */
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson arcmsr_enable_allintr(acb, intmask_org);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson return (0);
508aff1a85ed04f187fd074799bcaefd630490f1James C. McPherson}