Home | History | Annotate | Line # | Download | only in pci
mpii.c revision 1.3
      1  1.3  kardel /* $NetBSD: mpii.c,v 1.3 2013/08/09 19:51:29 kardel Exp $ */
      2  1.1  bouyer /*	OpenBSD: mpii.c,v 1.51 2012/04/11 13:29:14 naddy Exp 	*/
      3  1.1  bouyer /*
      4  1.1  bouyer  * Copyright (c) 2010 Mike Belopuhov <mkb (at) crypt.org.ru>
      5  1.1  bouyer  * Copyright (c) 2009 James Giannoules
      6  1.1  bouyer  * Copyright (c) 2005 - 2010 David Gwynne <dlg (at) openbsd.org>
      7  1.1  bouyer  * Copyright (c) 2005 - 2010 Marco Peereboom <marco (at) openbsd.org>
      8  1.1  bouyer  *
      9  1.1  bouyer  * Permission to use, copy, modify, and distribute this software for any
     10  1.1  bouyer  * purpose with or without fee is hereby granted, provided that the above
     11  1.1  bouyer  * copyright notice and this permission notice appear in all copies.
     12  1.1  bouyer  *
     13  1.1  bouyer  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     14  1.1  bouyer  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     15  1.1  bouyer  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     16  1.1  bouyer  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     17  1.1  bouyer  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     18  1.1  bouyer  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     19  1.1  bouyer  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     20  1.1  bouyer  */
     21  1.1  bouyer 
     22  1.1  bouyer #include <sys/cdefs.h>
     23  1.3  kardel __KERNEL_RCSID(0, "$NetBSD: mpii.c,v 1.3 2013/08/09 19:51:29 kardel Exp $");
     24  1.1  bouyer 
     25  1.1  bouyer #include "bio.h"
     26  1.1  bouyer 
     27  1.1  bouyer #include <sys/param.h>
     28  1.1  bouyer #include <sys/systm.h>
     29  1.1  bouyer #include <sys/buf.h>
     30  1.1  bouyer #include <sys/device.h>
     31  1.1  bouyer #include <sys/ioctl.h>
     32  1.1  bouyer #include <sys/malloc.h>
     33  1.1  bouyer #include <sys/kernel.h>
     34  1.1  bouyer #include <sys/mutex.h>
     35  1.1  bouyer #include <sys/condvar.h>
     36  1.1  bouyer #include <sys/dkio.h>
     37  1.1  bouyer #include <sys/tree.h>
     38  1.1  bouyer 
     39  1.1  bouyer #include <dev/pci/pcireg.h>
     40  1.1  bouyer #include <dev/pci/pcivar.h>
     41  1.1  bouyer #include <dev/pci/pcidevs.h>
     42  1.1  bouyer 
     43  1.1  bouyer #include <dev/scsipi/scsipi_all.h>
     44  1.1  bouyer #include <dev/scsipi/scsi_all.h>
     45  1.1  bouyer #include <dev/scsipi/scsiconf.h>
     46  1.1  bouyer 
     47  1.1  bouyer #include <dev/biovar.h>
     48  1.1  bouyer #include <dev/sysmon/sysmonvar.h>
     49  1.1  bouyer #include <sys/envsys.h>
     50  1.1  bouyer 
     51  1.1  bouyer #define MPII_DOORBELL			(0x00)
     52  1.1  bouyer /* doorbell read bits */
     53  1.1  bouyer #define MPII_DOORBELL_STATE		(0xf<<28) /* ioc state */
     54  1.1  bouyer #define  MPII_DOORBELL_STATE_RESET	(0x0<<28)
     55  1.1  bouyer #define  MPII_DOORBELL_STATE_READY	(0x1<<28)
     56  1.1  bouyer #define  MPII_DOORBELL_STATE_OPER	(0x2<<28)
     57  1.1  bouyer #define  MPII_DOORBELL_STATE_FAULT	(0x4<<28)
     58  1.1  bouyer #define  MPII_DOORBELL_INUSE		(0x1<<27) /* doorbell used */
     59  1.1  bouyer #define MPII_DOORBELL_WHOINIT		(0x7<<24) /* last to reset ioc */
     60  1.1  bouyer #define  MPII_DOORBELL_WHOINIT_NOONE	(0x0<<24) /* not initialized */
     61  1.1  bouyer #define  MPII_DOORBELL_WHOINIT_SYSBIOS	(0x1<<24) /* system bios */
     62  1.1  bouyer #define  MPII_DOORBELL_WHOINIT_ROMBIOS	(0x2<<24) /* rom bios */
     63  1.1  bouyer #define  MPII_DOORBELL_WHOINIT_PCIPEER	(0x3<<24) /* pci peer */
     64  1.1  bouyer #define  MPII_DOORBELL_WHOINIT_DRIVER	(0x4<<24) /* host driver */
     65  1.1  bouyer #define  MPII_DOORBELL_WHOINIT_MANUFACT	(0x5<<24) /* manufacturing */
     66  1.1  bouyer #define MPII_DOORBELL_FAULT		(0xffff<<0) /* fault code */
     67  1.1  bouyer /* doorbell write bits */
     68  1.1  bouyer #define MPII_DOORBELL_FUNCTION_SHIFT	(24)
     69  1.1  bouyer #define MPII_DOORBELL_FUNCTION_MASK	(0xff << MPII_DOORBELL_FUNCTION_SHIFT)
     70  1.1  bouyer #define MPII_DOORBELL_FUNCTION(x)	\
     71  1.1  bouyer     (((x) << MPII_DOORBELL_FUNCTION_SHIFT) & MPII_DOORBELL_FUNCTION_MASK)
     72  1.1  bouyer #define MPII_DOORBELL_DWORDS_SHIFT	16
     73  1.1  bouyer #define MPII_DOORBELL_DWORDS_MASK	(0xff << MPII_DOORBELL_DWORDS_SHIFT)
     74  1.1  bouyer #define MPII_DOORBELL_DWORDS(x)		\
     75  1.1  bouyer     (((x) << MPII_DOORBELL_DWORDS_SHIFT) & MPII_DOORBELL_DWORDS_MASK)
     76  1.1  bouyer #define MPII_DOORBELL_DATA_MASK		(0xffff)
     77  1.1  bouyer 
     78  1.1  bouyer #define MPII_WRITESEQ			(0x04)
     79  1.1  bouyer #define  MPII_WRITESEQ_KEY_VALUE_MASK	(0x0000000f) /* key value */
     80  1.1  bouyer #define  MPII_WRITESEQ_FLUSH		(0x00)
     81  1.1  bouyer #define  MPII_WRITESEQ_1		(0x0f)
     82  1.1  bouyer #define  MPII_WRITESEQ_2		(0x04)
     83  1.1  bouyer #define  MPII_WRITESEQ_3		(0x0b)
     84  1.1  bouyer #define  MPII_WRITESEQ_4		(0x02)
     85  1.1  bouyer #define  MPII_WRITESEQ_5		(0x07)
     86  1.1  bouyer #define  MPII_WRITESEQ_6		(0x0d)
     87  1.1  bouyer 
     88  1.1  bouyer #define MPII_HOSTDIAG			(0x08)
     89  1.1  bouyer #define  MPII_HOSTDIAG_BDS_MASK		(0x00001800) /* boot device select */
     90  1.1  bouyer #define   MPII_HOSTDIAG_BDS_DEFAULT 	(0<<11)	/* default address map, flash */
     91  1.1  bouyer #define   MPII_HOSTDIAG_BDS_HCDW	(1<<11)	/* host code and data window */
     92  1.1  bouyer #define  MPII_HOSTDIAG_CLEARFBS		(1<<10) /* clear flash bad sig */
     93  1.1  bouyer #define  MPII_HOSTDIAG_FORCE_HCB_ONBOOT (1<<9)	/* force host controlled boot */
     94  1.1  bouyer #define  MPII_HOSTDIAG_HCB_MODE		(1<<8)	/* host controlled boot mode */
     95  1.1  bouyer #define  MPII_HOSTDIAG_DWRE		(1<<7) 	/* diag reg write enabled */
     96  1.1  bouyer #define  MPII_HOSTDIAG_FBS		(1<<6) 	/* flash bad sig */
     97  1.1  bouyer #define  MPII_HOSTDIAG_RESET_HIST	(1<<5) 	/* reset history */
     98  1.1  bouyer #define  MPII_HOSTDIAG_DIAGWR_EN	(1<<4) 	/* diagnostic write enabled */
     99  1.1  bouyer #define  MPII_HOSTDIAG_RESET_ADAPTER	(1<<2) 	/* reset adapter */
    100  1.1  bouyer #define  MPII_HOSTDIAG_HOLD_IOC_RESET	(1<<1) 	/* hold ioc in reset */
    101  1.1  bouyer #define  MPII_HOSTDIAG_DIAGMEM_EN	(1<<0) 	/* diag mem enable */
    102  1.1  bouyer 
    103  1.1  bouyer #define MPII_DIAGRWDATA			(0x10)
    104  1.1  bouyer 
    105  1.1  bouyer #define MPII_DIAGRWADDRLOW		(0x14)
    106  1.1  bouyer 
    107  1.1  bouyer #define MPII_DIAGRWADDRHIGH		(0x18)
    108  1.1  bouyer 
    109  1.1  bouyer #define MPII_INTR_STATUS		(0x30)
    110  1.1  bouyer #define  MPII_INTR_STATUS_SYS2IOCDB	(1<<31) /* ioc written to by host */
    111  1.1  bouyer #define  MPII_INTR_STATUS_RESET		(1<<30) /* physical ioc reset */
    112  1.1  bouyer #define  MPII_INTR_STATUS_REPLY		(1<<3)	/* reply message interrupt */
    113  1.1  bouyer #define  MPII_INTR_STATUS_IOC2SYSDB	(1<<0) 	/* ioc write to doorbell */
    114  1.1  bouyer 
    115  1.1  bouyer #define MPII_INTR_MASK			(0x34)
    116  1.1  bouyer #define  MPII_INTR_MASK_RESET		(1<<30) /* ioc reset intr mask */
    117  1.1  bouyer #define  MPII_INTR_MASK_REPLY		(1<<3) 	/* reply message intr mask */
    118  1.1  bouyer #define  MPII_INTR_MASK_DOORBELL	(1<<0) 	/* doorbell interrupt mask */
    119  1.1  bouyer 
    120  1.1  bouyer #define MPII_DCR_DATA			(0x38)
    121  1.1  bouyer 
    122  1.1  bouyer #define MPII_DCR_ADDRESS		(0x3c)
    123  1.1  bouyer 
    124  1.1  bouyer #define MPII_REPLY_FREE_HOST_INDEX	(0x48)
    125  1.1  bouyer 
    126  1.1  bouyer #define MPII_REPLY_POST_HOST_INDEX	(0x6c)
    127  1.1  bouyer 
    128  1.1  bouyer #define MPII_HCB_SIZE			(0x74)
    129  1.1  bouyer 
    130  1.1  bouyer #define MPII_HCB_ADDRESS_LOW		(0x78)
    131  1.1  bouyer #define MPII_HCB_ADDRESS_HIGH		(0x7c)
    132  1.1  bouyer 
    133  1.1  bouyer #define MPII_REQ_DESCR_POST_LOW		(0xc0)
    134  1.1  bouyer #define MPII_REQ_DESCR_POST_HIGH	(0xc4)
    135  1.1  bouyer 
    136  1.1  bouyer /*
    137  1.1  bouyer  * Scatter Gather Lists
    138  1.1  bouyer  */
    139  1.1  bouyer 
    140  1.1  bouyer #define MPII_SGE_FL_LAST		(0x1<<31) /* last element in segment */
    141  1.1  bouyer #define MPII_SGE_FL_EOB			(0x1<<30) /* last element of buffer */
    142  1.1  bouyer #define MPII_SGE_FL_TYPE		(0x3<<28) /* element type */
    143  1.1  bouyer  #define MPII_SGE_FL_TYPE_SIMPLE	(0x1<<28) /* simple element */
    144  1.1  bouyer  #define MPII_SGE_FL_TYPE_CHAIN		(0x3<<28) /* chain element */
    145  1.1  bouyer  #define MPII_SGE_FL_TYPE_XACTCTX	(0x0<<28) /* transaction context */
    146  1.1  bouyer #define MPII_SGE_FL_LOCAL		(0x1<<27) /* local address */
    147  1.1  bouyer #define MPII_SGE_FL_DIR			(0x1<<26) /* direction */
    148  1.1  bouyer  #define MPII_SGE_FL_DIR_OUT		(0x1<<26)
    149  1.1  bouyer  #define MPII_SGE_FL_DIR_IN		(0x0<<26)
    150  1.1  bouyer #define MPII_SGE_FL_SIZE		(0x1<<25) /* address size */
    151  1.1  bouyer  #define MPII_SGE_FL_SIZE_32		(0x0<<25)
    152  1.1  bouyer  #define MPII_SGE_FL_SIZE_64		(0x1<<25)
    153  1.1  bouyer #define MPII_SGE_FL_EOL			(0x1<<24) /* end of list */
    154  1.1  bouyer 
    155  1.1  bouyer struct mpii_sge {
    156  1.1  bouyer 	u_int32_t		sg_hdr;
    157  1.1  bouyer 	u_int32_t		sg_lo_addr;
    158  1.1  bouyer 	u_int32_t		sg_hi_addr;
    159  1.1  bouyer } __packed;
    160  1.1  bouyer 
    161  1.1  bouyer struct mpii_fw_tce {
    162  1.1  bouyer 	u_int8_t		reserved1;
    163  1.1  bouyer 	u_int8_t		context_size;
    164  1.1  bouyer 	u_int8_t		details_length;
    165  1.1  bouyer 	u_int8_t		flags;
    166  1.1  bouyer 
    167  1.1  bouyer 	u_int32_t		reserved2;
    168  1.1  bouyer 
    169  1.1  bouyer 	u_int32_t		image_offset;
    170  1.1  bouyer 
    171  1.1  bouyer 	u_int32_t		image_size;
    172  1.1  bouyer } __packed;
    173  1.1  bouyer 
    174  1.1  bouyer /*
    175  1.1  bouyer  * Messages
    176  1.1  bouyer  */
    177  1.1  bouyer 
    178  1.1  bouyer /* functions */
    179  1.1  bouyer #define MPII_FUNCTION_SCSI_IO_REQUEST			(0x00)
    180  1.1  bouyer #define MPII_FUNCTION_SCSI_TASK_MGMT			(0x01)
    181  1.1  bouyer #define MPII_FUNCTION_IOC_INIT				(0x02)
    182  1.1  bouyer #define MPII_FUNCTION_IOC_FACTS				(0x03)
    183  1.1  bouyer #define MPII_FUNCTION_CONFIG				(0x04)
    184  1.1  bouyer #define MPII_FUNCTION_PORT_FACTS			(0x05)
    185  1.1  bouyer #define MPII_FUNCTION_PORT_ENABLE			(0x06)
    186  1.1  bouyer #define MPII_FUNCTION_EVENT_NOTIFICATION		(0x07)
    187  1.1  bouyer #define MPII_FUNCTION_EVENT_ACK				(0x08)
    188  1.1  bouyer #define MPII_FUNCTION_FW_DOWNLOAD			(0x09)
    189  1.1  bouyer #define MPII_FUNCTION_TARGET_CMD_BUFFER_POST		(0x0a)
    190  1.1  bouyer #define MPII_FUNCTION_TARGET_ASSIST			(0x0b)
    191  1.1  bouyer #define MPII_FUNCTION_TARGET_STATUS_SEND		(0x0c)
    192  1.1  bouyer #define MPII_FUNCTION_TARGET_MODE_ABORT			(0x0d)
    193  1.1  bouyer #define MPII_FUNCTION_FW_UPLOAD				(0x12)
    194  1.1  bouyer 
    195  1.1  bouyer #define MPII_FUNCTION_RAID_ACTION			(0x15)
    196  1.1  bouyer #define MPII_FUNCTION_RAID_SCSI_IO_PASSTHROUGH		(0x16)
    197  1.1  bouyer 
    198  1.1  bouyer #define MPII_FUNCTION_TOOLBOX				(0x17)
    199  1.1  bouyer 
    200  1.1  bouyer #define MPII_FUNCTION_SCSI_ENCLOSURE_PROCESSOR		(0x18)
    201  1.1  bouyer 
    202  1.1  bouyer #define MPII_FUNCTION_SMP_PASSTHROUGH			(0x1a)
    203  1.1  bouyer #define MPII_FUNCTION_SAS_IO_UNIT_CONTROL		(0x1b)
    204  1.1  bouyer #define MPII_FUNCTION_SATA_PASSTHROUGH			(0x1c)
    205  1.1  bouyer 
    206  1.1  bouyer #define MPII_FUNCTION_DIAG_BUFFER_POST			(0x1d)
    207  1.1  bouyer #define MPII_FUNCTION_DIAG_RELEASE			(0x1e)
    208  1.1  bouyer 
    209  1.1  bouyer #define MPII_FUNCTION_TARGET_CMD_BUF_BASE_POST		(0x24)
    210  1.1  bouyer #define MPII_FUNCTION_TARGET_CMD_BUF_LIST_POST		(0x25)
    211  1.1  bouyer 
    212  1.1  bouyer #define MPII_FUNCTION_IOC_MESSAGE_UNIT_RESET		(0x40)
    213  1.1  bouyer #define MPII_FUNCTION_IO_UNIT_RESET			(0x41)
    214  1.1  bouyer #define MPII_FUNCTION_HANDSHAKE				(0x42)
    215  1.1  bouyer 
    216  1.1  bouyer /* Common IOCStatus values for all replies */
    217  1.1  bouyer #define MPII_IOCSTATUS_MASK				(0x7fff)
    218  1.1  bouyer #define  MPII_IOCSTATUS_SUCCESS				(0x0000)
    219  1.1  bouyer #define  MPII_IOCSTATUS_INVALID_FUNCTION		(0x0001)
    220  1.1  bouyer #define  MPII_IOCSTATUS_BUSY				(0x0002)
    221  1.1  bouyer #define  MPII_IOCSTATUS_INVALID_SGL			(0x0003)
    222  1.1  bouyer #define  MPII_IOCSTATUS_INTERNAL_ERROR			(0x0004)
    223  1.1  bouyer #define  MPII_IOCSTATUS_INVALID_VPID			(0x0005)
    224  1.1  bouyer #define  MPII_IOCSTATUS_INSUFFICIENT_RESOURCES		(0x0006)
    225  1.1  bouyer #define  MPII_IOCSTATUS_INVALID_FIELD			(0x0007)
    226  1.1  bouyer #define  MPII_IOCSTATUS_INVALID_STATE			(0x0008)
    227  1.1  bouyer #define  MPII_IOCSTATUS_OP_STATE_NOT_SUPPORTED		(0x0009)
    228  1.1  bouyer /* Config IOCStatus values */
    229  1.1  bouyer #define  MPII_IOCSTATUS_CONFIG_INVALID_ACTION		(0x0020)
    230  1.1  bouyer #define  MPII_IOCSTATUS_CONFIG_INVALID_TYPE		(0x0021)
    231  1.1  bouyer #define  MPII_IOCSTATUS_CONFIG_INVALID_PAGE		(0x0022)
    232  1.1  bouyer #define  MPII_IOCSTATUS_CONFIG_INVALID_DATA		(0x0023)
    233  1.1  bouyer #define  MPII_IOCSTATUS_CONFIG_NO_DEFAULTS		(0x0024)
    234  1.1  bouyer #define  MPII_IOCSTATUS_CONFIG_CANT_COMMIT		(0x0025)
    235  1.1  bouyer /* SCSIIO Reply initiator values */
    236  1.1  bouyer #define  MPII_IOCSTATUS_SCSI_RECOVERED_ERROR		(0x0040)
    237  1.1  bouyer #define  MPII_IOCSTATUS_SCSI_INVALID_DEVHANDLE		(0x0042)
    238  1.1  bouyer #define  MPII_IOCSTATUS_SCSI_DEVICE_NOT_THERE		(0x0043)
    239  1.1  bouyer #define  MPII_IOCSTATUS_SCSI_DATA_OVERRUN		(0x0044)
    240  1.1  bouyer #define  MPII_IOCSTATUS_SCSI_DATA_UNDERRUN		(0x0045)
    241  1.1  bouyer #define  MPII_IOCSTATUS_SCSI_IO_DATA_ERROR		(0x0046)
    242  1.1  bouyer #define  MPII_IOCSTATUS_SCSI_PROTOCOL_ERROR		(0x0047)
    243  1.1  bouyer #define  MPII_IOCSTATUS_SCSI_TASK_TERMINATED		(0x0048)
    244  1.1  bouyer #define  MPII_IOCSTATUS_SCSI_RESIDUAL_MISMATCH		(0x0049)
    245  1.1  bouyer #define  MPII_IOCSTATUS_SCSI_TASK_MGMT_FAILED		(0x004a)
    246  1.1  bouyer #define  MPII_IOCSTATUS_SCSI_IOC_TERMINATED		(0x004b)
    247  1.1  bouyer #define  MPII_IOCSTATUS_SCSI_EXT_TERMINATED		(0x004c)
    248  1.1  bouyer /* For use by SCSI Initiator and SCSI Target end-to-end data protection */
    249  1.1  bouyer #define  MPII_IOCSTATUS_EEDP_GUARD_ERROR		(0x004d)
    250  1.1  bouyer #define  MPII_IOCSTATUS_EEDP_REF_TAG_ERROR		(0x004e)
    251  1.1  bouyer #define  MPII_IOCSTATUS_EEDP_APP_TAG_ERROR		(0x004f)
    252  1.1  bouyer /* SCSI (SPI & FCP) target values */
    253  1.1  bouyer #define  MPII_IOCSTATUS_TARGET_INVALID_IO_INDEX		(0x0062)
    254  1.1  bouyer #define  MPII_IOCSTATUS_TARGET_ABORTED			(0x0063)
    255  1.1  bouyer #define  MPII_IOCSTATUS_TARGET_NO_CONN_RETRYABLE	(0x0064)
    256  1.1  bouyer #define  MPII_IOCSTATUS_TARGET_NO_CONNECTION		(0x0065)
    257  1.1  bouyer #define  MPII_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH	(0x006a)
    258  1.1  bouyer #define  MPII_IOCSTATUS_TARGET_DATA_OFFSET_ERROR	(0x006d)
    259  1.1  bouyer #define  MPII_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA	(0x006e)
    260  1.1  bouyer #define  MPII_IOCSTATUS_TARGET_IU_TOO_SHORT		(0x006f)
    261  1.1  bouyer #define  MPII_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT		(0x0070)
    262  1.1  bouyer #define  MPII_IOCSTATUS_TARGET_NAK_RECEIVED		(0x0071)
    263  1.1  bouyer /* Serial Attached SCSI values */
    264  1.1  bouyer #define  MPII_IOCSTATUS_SAS_SMP_REQUEST_FAILED		(0x0090)
    265  1.1  bouyer #define  MPII_IOCSTATUS_SAS_SMP_DATA_OVERRUN		(0x0091)
    266  1.1  bouyer /* Diagnostic Tools values */
    267  1.1  bouyer #define  MPII_IOCSTATUS_DIAGNOSTIC_RELEASED		(0x00a0)
    268  1.1  bouyer 
    269  1.1  bouyer #define MPII_REP_IOCLOGINFO_TYPE			(0xf<<28)
    270  1.1  bouyer #define MPII_REP_IOCLOGINFO_TYPE_NONE			(0x0<<28)
    271  1.1  bouyer #define MPII_REP_IOCLOGINFO_TYPE_SCSI			(0x1<<28)
    272  1.1  bouyer #define MPII_REP_IOCLOGINFO_TYPE_FC			(0x2<<28)
    273  1.1  bouyer #define MPII_REP_IOCLOGINFO_TYPE_SAS			(0x3<<28)
    274  1.1  bouyer #define MPII_REP_IOCLOGINFO_TYPE_ISCSI			(0x4<<28)
    275  1.1  bouyer #define MPII_REP_IOCLOGINFO_DATA			(0x0fffffff)
    276  1.1  bouyer 
    277  1.1  bouyer /* event notification types */
    278  1.1  bouyer #define MPII_EVENT_NONE					(0x00)
    279  1.1  bouyer #define MPII_EVENT_LOG_DATA				(0x01)
    280  1.1  bouyer #define MPII_EVENT_STATE_CHANGE				(0x02)
    281  1.1  bouyer #define MPII_EVENT_HARD_RESET_RECEIVED			(0x05)
    282  1.1  bouyer #define MPII_EVENT_EVENT_CHANGE				(0x0a)
    283  1.1  bouyer #define MPII_EVENT_TASK_SET_FULL			(0x0e)
    284  1.1  bouyer #define MPII_EVENT_SAS_DEVICE_STATUS_CHANGE		(0x0f)
    285  1.1  bouyer #define MPII_EVENT_IR_OPERATION_STATUS			(0x14)
    286  1.1  bouyer #define MPII_EVENT_SAS_DISCOVERY			(0x16)
    287  1.1  bouyer #define MPII_EVENT_SAS_BROADCAST_PRIMITIVE		(0x17)
    288  1.1  bouyer #define MPII_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE	(0x18)
    289  1.1  bouyer #define MPII_EVENT_SAS_INIT_TABLE_OVERFLOW		(0x19)
    290  1.1  bouyer #define MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST		(0x1c)
    291  1.1  bouyer #define MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE	(0x1d)
    292  1.1  bouyer #define MPII_EVENT_IR_VOLUME				(0x1e)
    293  1.1  bouyer #define MPII_EVENT_IR_PHYSICAL_DISK			(0x1f)
    294  1.1  bouyer #define MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST		(0x20)
    295  1.1  bouyer #define MPII_EVENT_LOG_ENTRY_ADDED			(0x21)
    296  1.1  bouyer 
    297  1.1  bouyer /* messages */
    298  1.1  bouyer 
    299  1.1  bouyer #define MPII_WHOINIT_NOONE				(0x00)
    300  1.1  bouyer #define MPII_WHOINIT_SYSTEM_BIOS			(0x01)
    301  1.1  bouyer #define MPII_WHOINIT_ROM_BIOS				(0x02)
    302  1.1  bouyer #define MPII_WHOINIT_PCI_PEER				(0x03)
    303  1.1  bouyer #define MPII_WHOINIT_HOST_DRIVER			(0x04)
    304  1.1  bouyer #define MPII_WHOINIT_MANUFACTURER			(0x05)
    305  1.1  bouyer 
    306  1.1  bouyer /* default messages */
    307  1.1  bouyer 
    308  1.1  bouyer struct mpii_msg_request {
    309  1.1  bouyer 	u_int8_t		reserved1;
    310  1.1  bouyer 	u_int8_t		reserved2;
    311  1.1  bouyer 	u_int8_t		chain_offset;
    312  1.1  bouyer 	u_int8_t		function;
    313  1.1  bouyer 
    314  1.1  bouyer 	u_int8_t		reserved3;
    315  1.1  bouyer 	u_int8_t		reserved4;
    316  1.1  bouyer 	u_int8_t		reserved5;
    317  1.1  bouyer 	u_int8_t		msg_flags;
    318  1.1  bouyer 
    319  1.1  bouyer 	u_int8_t		vp_id;
    320  1.1  bouyer 	u_int8_t		vf_id;
    321  1.1  bouyer 	u_int16_t		reserved6;
    322  1.1  bouyer } __packed;
    323  1.1  bouyer 
    324  1.1  bouyer struct mpii_msg_reply {
    325  1.1  bouyer 	u_int16_t		reserved1;
    326  1.1  bouyer 	u_int8_t		msg_length;
    327  1.1  bouyer 	u_int8_t		function;
    328  1.1  bouyer 
    329  1.1  bouyer 	u_int16_t		reserved2;
    330  1.1  bouyer 	u_int8_t		reserved3;
    331  1.1  bouyer 	u_int8_t		msg_flags;
    332  1.1  bouyer 
    333  1.1  bouyer 	u_int8_t		vp_id;
    334  1.1  bouyer 	u_int8_t		vf_if;
    335  1.1  bouyer 	u_int16_t		reserved4;
    336  1.1  bouyer 
    337  1.1  bouyer 	u_int16_t		reserved5;
    338  1.1  bouyer 	u_int16_t		ioc_status;
    339  1.1  bouyer 
    340  1.1  bouyer 	u_int32_t		ioc_loginfo;
    341  1.1  bouyer } __packed;
    342  1.1  bouyer 
    343  1.1  bouyer /* ioc init */
    344  1.1  bouyer 
    345  1.1  bouyer struct mpii_msg_iocinit_request {
    346  1.1  bouyer 	u_int8_t		whoinit;
    347  1.1  bouyer 	u_int8_t		reserved1;
    348  1.1  bouyer 	u_int8_t		chain_offset;
    349  1.1  bouyer 	u_int8_t		function;
    350  1.1  bouyer 
    351  1.1  bouyer 	u_int16_t		reserved2;
    352  1.1  bouyer 	u_int8_t		reserved3;
    353  1.1  bouyer 	u_int8_t		msg_flags;
    354  1.1  bouyer 
    355  1.1  bouyer 	u_int8_t		vp_id;
    356  1.1  bouyer 	u_int8_t		vf_id;
    357  1.1  bouyer 	u_int16_t		reserved4;
    358  1.1  bouyer 
    359  1.1  bouyer 	u_int8_t		msg_version_min;
    360  1.1  bouyer 	u_int8_t		msg_version_maj;
    361  1.1  bouyer 	u_int8_t		hdr_version_unit;
    362  1.1  bouyer 	u_int8_t		hdr_version_dev;
    363  1.1  bouyer 
    364  1.1  bouyer 	u_int32_t		reserved5;
    365  1.1  bouyer 
    366  1.1  bouyer 	u_int32_t		reserved6;
    367  1.1  bouyer 
    368  1.1  bouyer 	u_int16_t		reserved7;
    369  1.1  bouyer 	u_int16_t		system_request_frame_size;
    370  1.1  bouyer 
    371  1.1  bouyer 	u_int16_t		reply_descriptor_post_queue_depth;
    372  1.1  bouyer 	u_int16_t		reply_free_queue_depth;
    373  1.1  bouyer 
    374  1.1  bouyer 	u_int32_t		sense_buffer_address_high;
    375  1.1  bouyer 
    376  1.1  bouyer 	u_int32_t		system_reply_address_high;
    377  1.1  bouyer 
    378  1.1  bouyer 	u_int64_t		system_request_frame_base_address;
    379  1.1  bouyer 
    380  1.1  bouyer 	u_int64_t		reply_descriptor_post_queue_address;
    381  1.1  bouyer 
    382  1.1  bouyer 	u_int64_t		reply_free_queue_address;
    383  1.1  bouyer 
    384  1.1  bouyer 	u_int64_t		timestamp;
    385  1.1  bouyer } __packed;
    386  1.1  bouyer 
    387  1.1  bouyer struct mpii_msg_iocinit_reply {
    388  1.1  bouyer 	u_int8_t		whoinit;
    389  1.1  bouyer 	u_int8_t		reserved1;
    390  1.1  bouyer 	u_int8_t		msg_length;
    391  1.1  bouyer 	u_int8_t		function;
    392  1.1  bouyer 
    393  1.1  bouyer 	u_int16_t		reserved2;
    394  1.1  bouyer 	u_int8_t		reserved3;
    395  1.1  bouyer 	u_int8_t		msg_flags;
    396  1.1  bouyer 
    397  1.1  bouyer 	u_int8_t		vp_id;
    398  1.1  bouyer 	u_int8_t		vf_id;
    399  1.1  bouyer 	u_int16_t		reserved4;
    400  1.1  bouyer 
    401  1.1  bouyer 	u_int16_t		reserved5;
    402  1.1  bouyer 	u_int16_t		ioc_status;
    403  1.1  bouyer 
    404  1.1  bouyer 	u_int32_t		ioc_loginfo;
    405  1.1  bouyer } __packed;
    406  1.1  bouyer 
    407  1.1  bouyer struct mpii_msg_iocfacts_request {
    408  1.1  bouyer 	u_int16_t		reserved1;
    409  1.1  bouyer 	u_int8_t		chain_offset;
    410  1.1  bouyer 	u_int8_t		function;
    411  1.1  bouyer 
    412  1.1  bouyer 	u_int16_t		reserved2;
    413  1.1  bouyer 	u_int8_t		reserved3;
    414  1.1  bouyer 	u_int8_t		msg_flags;
    415  1.1  bouyer 
    416  1.1  bouyer 	u_int8_t		vp_id;
    417  1.1  bouyer 	u_int8_t		vf_id;
    418  1.1  bouyer 	u_int16_t		reserved4;
    419  1.1  bouyer } __packed;
    420  1.1  bouyer 
    421  1.1  bouyer struct mpii_msg_iocfacts_reply {
    422  1.1  bouyer 	u_int8_t		msg_version_min;
    423  1.1  bouyer 	u_int8_t		msg_version_maj;
    424  1.1  bouyer 	u_int8_t		msg_length;
    425  1.1  bouyer 	u_int8_t		function;
    426  1.1  bouyer 
    427  1.1  bouyer 	u_int8_t		header_version_dev;
    428  1.1  bouyer 	u_int8_t		header_version_unit;
    429  1.1  bouyer 	u_int8_t		ioc_number;
    430  1.1  bouyer 	u_int8_t		msg_flags;
    431  1.1  bouyer 
    432  1.1  bouyer 	u_int8_t		vp_id;
    433  1.1  bouyer 	u_int8_t		vf_id;
    434  1.1  bouyer 	u_int16_t		reserved1;
    435  1.1  bouyer 
    436  1.1  bouyer 	u_int16_t		ioc_exceptions;
    437  1.1  bouyer #define MPII_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL	(1<<0)
    438  1.1  bouyer #define MPII_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID	(1<<1)
    439  1.1  bouyer #define MPII_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL		(1<<2)
    440  1.1  bouyer #define MPII_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL	(1<<3)
    441  1.1  bouyer #define MPII_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED	(1<<4)
    442  1.1  bouyer #define MPII_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAC	(1<<8)
    443  1.1  bouyer 	/* XXX JPG BOOT_STATUS in bits[7:5] */
    444  1.1  bouyer 	/* XXX JPG all these #defines need to be fixed up */
    445  1.1  bouyer 	u_int16_t		ioc_status;
    446  1.1  bouyer 
    447  1.1  bouyer 	u_int32_t		ioc_loginfo;
    448  1.1  bouyer 
    449  1.1  bouyer 	u_int8_t		max_chain_depth;
    450  1.1  bouyer 	u_int8_t		whoinit;
    451  1.1  bouyer 	u_int8_t		number_of_ports;
    452  1.1  bouyer 	u_int8_t		reserved2;
    453  1.1  bouyer 
    454  1.1  bouyer 	u_int16_t		request_credit;
    455  1.1  bouyer 	u_int16_t		product_id;
    456  1.1  bouyer 
    457  1.1  bouyer 	u_int32_t		ioc_capabilities;
    458  1.1  bouyer #define MPII_IOCFACTS_CAPABILITY_EVENT_REPLAY           (1<<13)
    459  1.1  bouyer #define MPII_IOCFACTS_CAPABILITY_INTEGRATED_RAID        (1<<12)
    460  1.1  bouyer #define MPII_IOCFACTS_CAPABILITY_TLR                    (1<<11)
    461  1.1  bouyer #define MPII_IOCFACTS_CAPABILITY_MULTICAST              (1<<8)
    462  1.1  bouyer #define MPII_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET   (1<<7)
    463  1.1  bouyer #define MPII_IOCFACTS_CAPABILITY_EEDP                   (1<<6)
    464  1.1  bouyer #define MPII_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER        (1<<4)
    465  1.1  bouyer #define MPII_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER      (1<<3)
    466  1.1  bouyer #define MPII_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (1<<2)
    467  1.1  bouyer 
    468  1.1  bouyer 	u_int8_t		fw_version_dev;
    469  1.1  bouyer 	u_int8_t		fw_version_unit;
    470  1.1  bouyer 	u_int8_t		fw_version_min;
    471  1.1  bouyer 	u_int8_t		fw_version_maj;
    472  1.1  bouyer 
    473  1.1  bouyer 	u_int16_t		ioc_request_frame_size;
    474  1.1  bouyer 	u_int16_t		reserved3;
    475  1.1  bouyer 
    476  1.1  bouyer 	u_int16_t		max_initiators;
    477  1.1  bouyer 	u_int16_t		max_targets;
    478  1.1  bouyer 
    479  1.1  bouyer 	u_int16_t		max_sas_expanders;
    480  1.1  bouyer 	u_int16_t		max_enclosures;
    481  1.1  bouyer 
    482  1.1  bouyer 	u_int16_t		protocol_flags;
    483  1.1  bouyer 	u_int16_t		high_priority_credit;
    484  1.1  bouyer 
    485  1.1  bouyer 	u_int16_t		max_reply_descriptor_post_queue_depth;
    486  1.1  bouyer 	u_int8_t		reply_frame_size;
    487  1.1  bouyer 	u_int8_t		max_volumes;
    488  1.1  bouyer 
    489  1.1  bouyer 	u_int16_t		max_dev_handle;
    490  1.1  bouyer 	u_int16_t		max_persistent_entries;
    491  1.1  bouyer 
    492  1.1  bouyer 	u_int32_t		reserved4;
    493  1.1  bouyer } __packed;
    494  1.1  bouyer 
    495  1.1  bouyer struct mpii_msg_portfacts_request {
    496  1.1  bouyer 	u_int16_t		reserved1;
    497  1.1  bouyer 	u_int8_t		chain_offset;
    498  1.1  bouyer 	u_int8_t		function;
    499  1.1  bouyer 
    500  1.1  bouyer 	u_int16_t		reserved2;
    501  1.1  bouyer 	u_int8_t		port_number;
    502  1.1  bouyer 	u_int8_t		msg_flags;
    503  1.1  bouyer 
    504  1.1  bouyer 	u_int8_t		vp_id;
    505  1.1  bouyer 	u_int8_t		vf_id;
    506  1.1  bouyer 	u_int16_t		reserved3;
    507  1.1  bouyer } __packed;
    508  1.1  bouyer 
    509  1.1  bouyer struct mpii_msg_portfacts_reply {
    510  1.1  bouyer 	u_int16_t		reserved1;
    511  1.1  bouyer 	u_int8_t		msg_length;
    512  1.1  bouyer 	u_int8_t		function;
    513  1.1  bouyer 
    514  1.1  bouyer 	u_int16_t		reserved2;
    515  1.1  bouyer 	u_int8_t		port_number;
    516  1.1  bouyer 	u_int8_t		msg_flags;
    517  1.1  bouyer 
    518  1.1  bouyer 	u_int8_t		vp_id;
    519  1.1  bouyer 	u_int8_t		vf_id;
    520  1.1  bouyer 	u_int16_t		reserved3;
    521  1.1  bouyer 
    522  1.1  bouyer 	u_int16_t		reserved4;
    523  1.1  bouyer 	u_int16_t		ioc_status;
    524  1.1  bouyer 
    525  1.1  bouyer 	u_int32_t		ioc_loginfo;
    526  1.1  bouyer 
    527  1.1  bouyer 	u_int8_t		reserved5;
    528  1.1  bouyer 	u_int8_t		port_type;
    529  1.1  bouyer #define MPII_PORTFACTS_PORTTYPE_INACTIVE		(0x00)
    530  1.1  bouyer #define MPII_PORTFACTS_PORTTYPE_FC			(0x10)
    531  1.1  bouyer #define MPII_PORTFACTS_PORTTYPE_ISCSI			(0x20)
    532  1.1  bouyer #define MPII_PORTFACTS_PORTTYPE_SAS_PHYSICAL		(0x30)
    533  1.1  bouyer #define MPII_PORTFACTS_PORTTYPE_SAS_VIRTUAL		(0x31)
    534  1.1  bouyer 	u_int16_t		reserved6;
    535  1.1  bouyer 
    536  1.1  bouyer 	u_int16_t		max_posted_cmd_buffers;
    537  1.1  bouyer 	u_int16_t		reserved7;
    538  1.1  bouyer } __packed;
    539  1.1  bouyer 
    540  1.1  bouyer struct mpii_msg_portenable_request {
    541  1.1  bouyer 	u_int16_t		reserved1;
    542  1.1  bouyer 	u_int8_t		chain_offset;
    543  1.1  bouyer 	u_int8_t		function;
    544  1.1  bouyer 
    545  1.1  bouyer 	u_int8_t		reserved2;
    546  1.1  bouyer 	u_int8_t		port_flags;
    547  1.1  bouyer 	u_int8_t		reserved3;
    548  1.1  bouyer 	u_int8_t		msg_flags;
    549  1.1  bouyer 
    550  1.1  bouyer 	u_int8_t		vp_id;
    551  1.1  bouyer 	u_int8_t		vf_id;
    552  1.1  bouyer 	u_int16_t		reserved4;
    553  1.1  bouyer } __packed;
    554  1.1  bouyer 
    555  1.1  bouyer struct mpii_msg_portenable_reply {
    556  1.1  bouyer 	u_int16_t		reserved1;
    557  1.1  bouyer 	u_int8_t		msg_length;
    558  1.1  bouyer 	u_int8_t		function;
    559  1.1  bouyer 
    560  1.1  bouyer 	u_int8_t		reserved2;
    561  1.1  bouyer 	u_int8_t		port_flags;
    562  1.1  bouyer 	u_int8_t		reserved3;
    563  1.1  bouyer 	u_int8_t		msg_flags;
    564  1.1  bouyer 
    565  1.1  bouyer 	u_int8_t		vp_id;
    566  1.1  bouyer 	u_int8_t		vf_id;
    567  1.1  bouyer 	u_int16_t		reserved4;
    568  1.1  bouyer 
    569  1.1  bouyer 	u_int16_t		reserved5;
    570  1.1  bouyer 	u_int16_t		ioc_status;
    571  1.1  bouyer 
    572  1.1  bouyer 	u_int32_t		ioc_loginfo;
    573  1.1  bouyer } __packed;
    574  1.1  bouyer 
    575  1.1  bouyer struct mpii_msg_event_request {
    576  1.1  bouyer 	u_int16_t		reserved1;
    577  1.1  bouyer 	u_int8_t		chain_offset;
    578  1.1  bouyer 	u_int8_t		function;
    579  1.1  bouyer 
    580  1.1  bouyer 	u_int16_t		reserved2;
    581  1.1  bouyer 	u_int8_t		reserved3;
    582  1.1  bouyer 	u_int8_t		msg_flags;
    583  1.1  bouyer 
    584  1.1  bouyer 	u_int8_t		vp_id;
    585  1.1  bouyer 	u_int8_t		vf_id;
    586  1.1  bouyer 	u_int16_t		reserved4;
    587  1.1  bouyer 
    588  1.1  bouyer 	u_int32_t		reserved5;
    589  1.1  bouyer 
    590  1.1  bouyer 	u_int32_t		reserved6;
    591  1.1  bouyer 
    592  1.1  bouyer 	u_int32_t		event_masks[4];
    593  1.1  bouyer 
    594  1.1  bouyer 	u_int16_t		sas_broadcase_primitive_masks;
    595  1.1  bouyer 	u_int16_t		reserved7;
    596  1.1  bouyer 
    597  1.1  bouyer 	u_int32_t		reserved8;
    598  1.1  bouyer } __packed;
    599  1.1  bouyer 
    600  1.1  bouyer struct mpii_msg_event_reply {
    601  1.1  bouyer 	u_int16_t		event_data_length;
    602  1.1  bouyer 	u_int8_t		msg_length;
    603  1.1  bouyer 	u_int8_t		function;
    604  1.1  bouyer 
    605  1.1  bouyer 	u_int16_t		reserved1;
    606  1.1  bouyer 	u_int8_t		ack_required;
    607  1.1  bouyer #define MPII_EVENT_ACK_REQUIRED				(0x01)
    608  1.1  bouyer 	u_int8_t		msg_flags;
    609  1.1  bouyer #define MPII_EVENT_FLAGS_REPLY_KEPT			(1<<7)
    610  1.1  bouyer 
    611  1.1  bouyer 	u_int8_t		vp_id;
    612  1.1  bouyer 	u_int8_t		vf_id;
    613  1.1  bouyer 	u_int16_t		reserved2;
    614  1.1  bouyer 
    615  1.1  bouyer 	u_int16_t		reserved3;
    616  1.1  bouyer 	u_int16_t		ioc_status;
    617  1.1  bouyer 
    618  1.1  bouyer 	u_int32_t		ioc_loginfo;
    619  1.1  bouyer 
    620  1.1  bouyer 	u_int16_t		event;
    621  1.1  bouyer 	u_int16_t		reserved4;
    622  1.1  bouyer 
    623  1.1  bouyer 	u_int32_t		event_context;
    624  1.1  bouyer 
    625  1.1  bouyer 	/* event data follows */
    626  1.1  bouyer } __packed;
    627  1.1  bouyer 
    628  1.1  bouyer struct mpii_msg_eventack_request {
    629  1.1  bouyer 	u_int16_t		reserved1;
    630  1.1  bouyer 	u_int8_t		chain_offset;
    631  1.1  bouyer 	u_int8_t		function;
    632  1.1  bouyer 
    633  1.1  bouyer 	u_int8_t		reserved2[3];
    634  1.1  bouyer 	u_int8_t		msg_flags;
    635  1.1  bouyer 
    636  1.1  bouyer 	u_int8_t		vp_id;
    637  1.1  bouyer 	u_int8_t		vf_id;
    638  1.1  bouyer 	u_int16_t		reserved3;
    639  1.1  bouyer 
    640  1.1  bouyer 	u_int16_t		event;
    641  1.1  bouyer 	u_int16_t		reserved4;
    642  1.1  bouyer 
    643  1.1  bouyer 	u_int32_t		event_context;
    644  1.1  bouyer } __packed;
    645  1.1  bouyer 
    646  1.1  bouyer struct mpii_msg_eventack_reply {
    647  1.1  bouyer 	u_int16_t		reserved1;
    648  1.1  bouyer 	u_int8_t		msg_length;
    649  1.1  bouyer 	u_int8_t		function;
    650  1.1  bouyer 
    651  1.1  bouyer 	u_int8_t		reserved2[3];
    652  1.1  bouyer 	u_int8_t		msg_flags;
    653  1.1  bouyer 
    654  1.1  bouyer 	u_int8_t		vp_id;
    655  1.1  bouyer 	u_int8_t		vf_id;
    656  1.1  bouyer 	u_int16_t		reserved3;
    657  1.1  bouyer 
    658  1.1  bouyer 	u_int16_t		reserved4;
    659  1.1  bouyer 	u_int16_t		ioc_status;
    660  1.1  bouyer 
    661  1.1  bouyer 	u_int32_t		ioc_loginfo;
    662  1.1  bouyer } __packed;
    663  1.1  bouyer 
    664  1.1  bouyer struct mpii_msg_fwupload_request {
    665  1.1  bouyer 	u_int8_t		image_type;
    666  1.1  bouyer #define MPII_FWUPLOAD_IMAGETYPE_IOC_FW			(0x00)
    667  1.1  bouyer #define MPII_FWUPLOAD_IMAGETYPE_NV_FW			(0x01)
    668  1.1  bouyer #define MPII_FWUPLOAD_IMAGETYPE_NV_BACKUP		(0x05)
    669  1.1  bouyer #define MPII_FWUPLOAD_IMAGETYPE_NV_MANUFACTURING	(0x06)
    670  1.1  bouyer #define MPII_FWUPLOAD_IMAGETYPE_NV_CONFIG_1		(0x07)
    671  1.1  bouyer #define MPII_FWUPLOAD_IMAGETYPE_NV_CONFIG_2		(0x08)
    672  1.1  bouyer #define MPII_FWUPLOAD_IMAGETYPE_NV_MEGARAID		(0x09)
    673  1.1  bouyer #define MPII_FWUPLOAD_IMAGETYPE_NV_COMPLETE		(0x0a)
    674  1.1  bouyer #define MPII_FWUPLOAD_IMAGETYPE_COMMON_BOOT_BLOCK	(0x0b)
    675  1.1  bouyer 	u_int8_t		reserved1;
    676  1.1  bouyer 	u_int8_t		chain_offset;
    677  1.1  bouyer 	u_int8_t		function;
    678  1.1  bouyer 
    679  1.1  bouyer 	u_int8_t		reserved2[3];
    680  1.1  bouyer 	u_int8_t		msg_flags;
    681  1.1  bouyer 
    682  1.1  bouyer 	u_int8_t		vp_id;
    683  1.1  bouyer 	u_int8_t		vf_id;
    684  1.1  bouyer 	u_int16_t		reserved3;
    685  1.1  bouyer 
    686  1.1  bouyer 	u_int32_t		reserved4;
    687  1.1  bouyer 
    688  1.1  bouyer 	u_int32_t		reserved5;
    689  1.1  bouyer 
    690  1.1  bouyer 	struct mpii_fw_tce	tce;
    691  1.1  bouyer 
    692  1.1  bouyer 	/* followed by an sgl */
    693  1.1  bouyer } __packed;
    694  1.1  bouyer 
    695  1.1  bouyer struct mpii_msg_fwupload_reply {
    696  1.1  bouyer 	u_int8_t		image_type;
    697  1.1  bouyer 	u_int8_t		reserved1;
    698  1.1  bouyer 	u_int8_t		msg_length;
    699  1.1  bouyer 	u_int8_t		function;
    700  1.1  bouyer 
    701  1.1  bouyer 	u_int8_t		reserved2[3];
    702  1.1  bouyer 	u_int8_t		msg_flags;
    703  1.1  bouyer 
    704  1.1  bouyer 	u_int8_t		vp_id;
    705  1.1  bouyer 	u_int8_t		vf_id;
    706  1.1  bouyer 	u_int16_t		reserved3;
    707  1.1  bouyer 
    708  1.1  bouyer 	u_int16_t		reserved4;
    709  1.1  bouyer 	u_int16_t		ioc_status;
    710  1.1  bouyer 
    711  1.1  bouyer 	u_int32_t		ioc_loginfo;
    712  1.1  bouyer 
    713  1.1  bouyer 	u_int32_t		actual_image_size;
    714  1.1  bouyer } __packed;
    715  1.1  bouyer 
    716  1.1  bouyer struct mpii_msg_scsi_io {
    717  1.1  bouyer 	u_int16_t		dev_handle;
    718  1.1  bouyer 	u_int8_t		chain_offset;
    719  1.1  bouyer 	u_int8_t		function;
    720  1.1  bouyer 
    721  1.1  bouyer 	u_int16_t		reserved1;
    722  1.1  bouyer 	u_int8_t		reserved2;
    723  1.1  bouyer 	u_int8_t		msg_flags;
    724  1.1  bouyer 
    725  1.1  bouyer 	u_int8_t		vp_id;
    726  1.1  bouyer 	u_int8_t		vf_id;
    727  1.1  bouyer 	u_int16_t		reserved3;
    728  1.1  bouyer 
    729  1.1  bouyer 	u_int32_t		sense_buffer_low_address;
    730  1.1  bouyer 
    731  1.1  bouyer 	u_int16_t		sgl_flags;
    732  1.1  bouyer 	u_int8_t		sense_buffer_length;
    733  1.1  bouyer 	u_int8_t		reserved4;
    734  1.1  bouyer 
    735  1.1  bouyer 	u_int8_t		sgl_offset0;
    736  1.1  bouyer 	u_int8_t		sgl_offset1;
    737  1.1  bouyer 	u_int8_t		sgl_offset2;
    738  1.1  bouyer 	u_int8_t		sgl_offset3;
    739  1.1  bouyer 
    740  1.1  bouyer 	u_int32_t		skip_count;
    741  1.1  bouyer 
    742  1.1  bouyer 	u_int32_t		data_length;
    743  1.1  bouyer 
    744  1.1  bouyer 	u_int32_t		bidirectional_data_length;
    745  1.1  bouyer 
    746  1.1  bouyer 	u_int16_t		io_flags;
    747  1.1  bouyer 	u_int16_t		eedp_flags;
    748  1.1  bouyer 
    749  1.1  bouyer 	u_int32_t		eedp_block_size;
    750  1.1  bouyer 
    751  1.1  bouyer 	u_int32_t		secondary_reference_tag;
    752  1.1  bouyer 
    753  1.1  bouyer 	u_int16_t		secondary_application_tag;
    754  1.1  bouyer 	u_int16_t		application_tag_translation_mask;
    755  1.1  bouyer 
    756  1.1  bouyer 	u_int16_t		lun[4];
    757  1.1  bouyer 
    758  1.1  bouyer /* the following 16 bits are defined in MPI2 as the control field */
    759  1.1  bouyer 	u_int8_t		reserved5;
    760  1.1  bouyer 	u_int8_t		tagging;
    761  1.1  bouyer #define MPII_SCSIIO_ATTR_SIMPLE_Q			(0x0)
    762  1.1  bouyer #define MPII_SCSIIO_ATTR_HEAD_OF_Q			(0x1)
    763  1.1  bouyer #define MPII_SCSIIO_ATTR_ORDERED_Q			(0x2)
    764  1.1  bouyer #define MPII_SCSIIO_ATTR_ACA_Q				(0x4)
    765  1.1  bouyer #define MPII_SCSIIO_ATTR_UNTAGGED			(0x5)
    766  1.1  bouyer #define MPII_SCSIIO_ATTR_NO_DISCONNECT			(0x7)
    767  1.1  bouyer 	u_int8_t		reserved6;
    768  1.1  bouyer 	u_int8_t		direction;
    769  1.1  bouyer #define MPII_SCSIIO_DIR_NONE				(0x0)
    770  1.1  bouyer #define MPII_SCSIIO_DIR_WRITE				(0x1)
    771  1.1  bouyer #define MPII_SCSIIO_DIR_READ				(0x2)
    772  1.1  bouyer 
    773  1.1  bouyer #define	MPII_CDB_LEN					(32)
    774  1.1  bouyer 	u_int8_t		cdb[MPII_CDB_LEN];
    775  1.1  bouyer 
    776  1.1  bouyer 	/* followed by an sgl */
    777  1.1  bouyer } __packed;
    778  1.1  bouyer 
    779  1.1  bouyer struct mpii_msg_scsi_io_error {
    780  1.1  bouyer 	u_int16_t		dev_handle;
    781  1.1  bouyer 	u_int8_t		msg_length;
    782  1.1  bouyer 	u_int8_t		function;
    783  1.1  bouyer 
    784  1.1  bouyer 	u_int16_t		reserved1;
    785  1.1  bouyer 	u_int8_t		reserved2;
    786  1.1  bouyer 	u_int8_t		msg_flags;
    787  1.1  bouyer 
    788  1.1  bouyer 	u_int8_t		vp_id;
    789  1.1  bouyer 	u_int8_t		vf_id;
    790  1.1  bouyer 	u_int16_t		reserved3;
    791  1.1  bouyer 
    792  1.1  bouyer 	u_int8_t		scsi_status;
    793  1.3  kardel 
    794  1.3  kardel #define MPII_SCSIIO_ERR_STATUS_SUCCESS			(0x00)
    795  1.3  kardel #define MPII_SCSIIO_ERR_STATUS_CHECK_COND		(0x02)
    796  1.3  kardel #define MPII_SCSIIO_ERR_STATUS_BUSY			(0x04)
    797  1.3  kardel #define MPII_SCSIIO_ERR_STATUS_INTERMEDIATE		(0x08)
    798  1.3  kardel #define MPII_SCSIIO_ERR_STATUS_INTERMEDIATE_CONDMET	(0x10)
    799  1.3  kardel #define MPII_SCSIIO_ERR_STATUS_RESERVATION_CONFLICT	(0x14)
    800  1.3  kardel #define MPII_SCSIIO_ERR_STATUS_CMD_TERM			(0x22)
    801  1.3  kardel #define MPII_SCSIIO_ERR_STATUS_TASK_SET_FULL		(0x28)
    802  1.3  kardel #define MPII_SCSIIO_ERR_STATUS_ACA_ACTIVE		(0x30)
    803  1.3  kardel #define MPII_SCSIIO_ERR_STATUS_TASK_ABORTED		(0x40)
    804  1.3  kardel 
    805  1.1  bouyer 	u_int8_t		scsi_state;
    806  1.1  bouyer #define MPII_SCSIIO_ERR_STATE_AUTOSENSE_VALID		(1<<0)
    807  1.1  bouyer #define MPII_SCSIIO_ERR_STATE_AUTOSENSE_FAILED		(1<<1)
    808  1.1  bouyer #define MPII_SCSIIO_ERR_STATE_NO_SCSI_STATUS		(1<<2)
    809  1.1  bouyer #define MPII_SCSIIO_ERR_STATE_TERMINATED		(1<<3)
    810  1.1  bouyer #define MPII_SCSIIO_ERR_STATE_RESPONSE_INFO_VALID	(1<<4)
    811  1.1  bouyer #define MPII_SCSIIO_ERR_STATE_QUEUE_TAG_REJECTED	(0xffff)
    812  1.1  bouyer 	u_int16_t		ioc_status;
    813  1.1  bouyer 
    814  1.1  bouyer 	u_int32_t		ioc_loginfo;
    815  1.1  bouyer 
    816  1.1  bouyer 	u_int32_t		transfer_count;
    817  1.1  bouyer 
    818  1.1  bouyer 	u_int32_t		sense_count;
    819  1.1  bouyer 
    820  1.1  bouyer 	u_int32_t		response_info;
    821  1.1  bouyer 
    822  1.1  bouyer 	u_int16_t		task_tag;
    823  1.1  bouyer 	u_int16_t		reserved4;
    824  1.1  bouyer 
    825  1.1  bouyer 	u_int32_t		bidirectional_transfer_count;
    826  1.1  bouyer 
    827  1.1  bouyer 	u_int32_t		reserved5;
    828  1.1  bouyer 
    829  1.1  bouyer 	u_int32_t		reserved6;
    830  1.1  bouyer } __packed;
    831  1.1  bouyer 
    832  1.1  bouyer struct mpii_request_descr {
    833  1.1  bouyer 	u_int8_t		request_flags;
    834  1.1  bouyer #define MPII_REQ_DESCR_TYPE_MASK			(0x0e)
    835  1.1  bouyer #define MPII_REQ_DESCR_SCSI_IO				(0x00)
    836  1.1  bouyer #define MPII_REQ_DESCR_SCSI_TARGET			(0x02)
    837  1.1  bouyer #define MPII_REQ_DESCR_HIGH_PRIORITY			(0x06)
    838  1.1  bouyer #define MPII_REQ_DESCR_DEFAULT				(0x08)
    839  1.1  bouyer 	u_int8_t		vf_id;
    840  1.1  bouyer 	u_int16_t		smid;
    841  1.1  bouyer 
    842  1.1  bouyer 	u_int16_t		lmid;
    843  1.1  bouyer 	u_int16_t		dev_handle;
    844  1.1  bouyer } __packed;
    845  1.1  bouyer 
    846  1.1  bouyer struct mpii_reply_descr {
    847  1.1  bouyer 	u_int8_t		reply_flags;
    848  1.1  bouyer #define MPII_REPLY_DESCR_TYPE_MASK               	(0x0f)
    849  1.1  bouyer #define MPII_REPLY_DESCR_SCSI_IO_SUCCESS         	(0x00)
    850  1.1  bouyer #define MPII_REPLY_DESCR_ADDRESS_REPLY           	(0x01)
    851  1.1  bouyer #define MPII_REPLY_DESCR_TARGET_ASSIST_SUCCESS    	(0x02)
    852  1.1  bouyer #define MPII_REPLY_DESCR_TARGET_COMMAND_BUFFER   	(0x03)
    853  1.1  bouyer #define MPII_REPLY_DESCR_UNUSED                  	(0x0f)
    854  1.1  bouyer 	u_int8_t		vf_id;
    855  1.1  bouyer 	u_int16_t		smid;
    856  1.1  bouyer 
    857  1.1  bouyer 	union {
    858  1.1  bouyer 		u_int32_t	data;
    859  1.1  bouyer 		u_int32_t	frame_addr;	/* Address Reply */
    860  1.1  bouyer 	};
    861  1.1  bouyer } __packed;
    862  1.1  bouyer 
    863  1.1  bouyer struct mpii_request_header {
    864  1.1  bouyer 	u_int16_t		function_dependent1;
    865  1.1  bouyer 	u_int8_t		chain_offset;
    866  1.1  bouyer 	u_int8_t		function;
    867  1.1  bouyer 
    868  1.1  bouyer 	u_int16_t		function_dependent2;
    869  1.1  bouyer 	u_int8_t		function_dependent3;
    870  1.1  bouyer 	u_int8_t		message_flags;
    871  1.1  bouyer 
    872  1.1  bouyer 	u_int8_t		vp_id;
    873  1.1  bouyer 	u_int8_t		vf_id;
    874  1.1  bouyer 	u_int16_t		reserved;
    875  1.1  bouyer } __packed;
    876  1.1  bouyer 
    877  1.1  bouyer struct mpii_msg_scsi_task_request {
    878  1.1  bouyer 	u_int16_t		dev_handle;
    879  1.1  bouyer 	u_int8_t		chain_offset;
    880  1.1  bouyer 	u_int8_t		function;
    881  1.1  bouyer 
    882  1.1  bouyer 	u_int8_t		reserved1;
    883  1.1  bouyer 	u_int8_t		task_type;
    884  1.1  bouyer #define MPII_SCSI_TASK_ABORT_TASK			(0x01)
    885  1.1  bouyer #define MPII_SCSI_TASK_ABRT_TASK_SET			(0x02)
    886  1.1  bouyer #define MPII_SCSI_TASK_TARGET_RESET			(0x03)
    887  1.1  bouyer #define MPII_SCSI_TASK_RESET_BUS			(0x04)
    888  1.1  bouyer #define MPII_SCSI_TASK_LOGICAL_UNIT_RESET		(0x05)
    889  1.1  bouyer 	u_int8_t		reserved2;
    890  1.1  bouyer 	u_int8_t		msg_flags;
    891  1.1  bouyer 
    892  1.1  bouyer 	u_int8_t		vp_id;
    893  1.1  bouyer 	u_int8_t		vf_id;
    894  1.1  bouyer 	u_int16_t		reserved3;
    895  1.1  bouyer 
    896  1.1  bouyer 	u_int16_t		lun[4];
    897  1.1  bouyer 
    898  1.1  bouyer 	u_int32_t		reserved4[7];
    899  1.1  bouyer 
    900  1.1  bouyer 	u_int16_t		task_mid;
    901  1.1  bouyer 	u_int16_t		reserved5;
    902  1.1  bouyer } __packed;
    903  1.1  bouyer 
    904  1.1  bouyer struct mpii_msg_scsi_task_reply {
    905  1.1  bouyer 	u_int16_t		dev_handle;
    906  1.1  bouyer 	u_int8_t		msg_length;
    907  1.1  bouyer 	u_int8_t		function;
    908  1.1  bouyer 
    909  1.1  bouyer 	u_int8_t		response_code;
    910  1.1  bouyer 	u_int8_t		task_type;
    911  1.1  bouyer 	u_int8_t		reserved1;
    912  1.1  bouyer 	u_int8_t		msg_flags;
    913  1.1  bouyer 
    914  1.1  bouyer 	u_int8_t		vp_id;
    915  1.1  bouyer 	u_int8_t		vf_id;
    916  1.1  bouyer 	u_int16_t		reserved2;
    917  1.1  bouyer 
    918  1.1  bouyer 	u_int16_t		reserved3;
    919  1.1  bouyer 	u_int16_t		ioc_status;
    920  1.1  bouyer 
    921  1.1  bouyer 	u_int32_t		ioc_loginfo;
    922  1.1  bouyer 
    923  1.1  bouyer 	u_int32_t		termination_count;
    924  1.1  bouyer } __packed;
    925  1.1  bouyer 
    926  1.1  bouyer struct mpii_msg_sas_oper_request {
    927  1.1  bouyer 	u_int8_t		operation;
    928  1.1  bouyer #define MPII_SAS_OP_CLEAR_PERSISTENT		(0x02)
    929  1.1  bouyer #define MPII_SAS_OP_PHY_LINK_RESET		(0x06)
    930  1.1  bouyer #define MPII_SAS_OP_PHY_HARD_RESET		(0x07)
    931  1.1  bouyer #define MPII_SAS_OP_PHY_CLEAR_ERROR_LOG		(0x08)
    932  1.1  bouyer #define MPII_SAS_OP_SEND_PRIMITIVE		(0x0a)
    933  1.1  bouyer #define MPII_SAS_OP_FORCE_FULL_DISCOVERY	(0x0b)
    934  1.1  bouyer #define MPII_SAS_OP_TRANSMIT_PORT_SELECT	(0x0c)
    935  1.1  bouyer #define MPII_SAS_OP_REMOVE_DEVICE		(0x0d)
    936  1.1  bouyer #define MPII_SAS_OP_LOOKUP_MAPPING		(0x0e)
    937  1.1  bouyer #define MPII_SAS_OP_SET_IOC_PARAM		(0x0f)
    938  1.1  bouyer 	u_int8_t		reserved1;
    939  1.1  bouyer 	u_int8_t		chain_offset;
    940  1.1  bouyer 	u_int8_t		function;
    941  1.1  bouyer 
    942  1.1  bouyer 	u_int16_t		dev_handle;
    943  1.1  bouyer 	u_int8_t		ioc_param;
    944  1.1  bouyer 	u_int8_t		msg_flags;
    945  1.1  bouyer 
    946  1.1  bouyer 	u_int8_t		vp_id;
    947  1.1  bouyer 	u_int8_t		vf_id;
    948  1.1  bouyer 	u_int16_t		reserved2;
    949  1.1  bouyer 
    950  1.1  bouyer 	u_int16_t		reserved3;
    951  1.1  bouyer 	u_int8_t		phy_num;
    952  1.1  bouyer 	u_int8_t		prim_flags;
    953  1.1  bouyer 
    954  1.1  bouyer 	u_int32_t		primitive;
    955  1.1  bouyer 
    956  1.1  bouyer 	u_int8_t		lookup_method;
    957  1.1  bouyer #define MPII_SAS_LOOKUP_METHOD_SAS_ADDR		(0x01)
    958  1.1  bouyer #define MPII_SAS_LOOKUP_METHOD_SAS_ENCL		(0x02)
    959  1.1  bouyer #define MPII_SAS_LOOKUP_METHOD_SAS_DEVNAME	(0x03)
    960  1.1  bouyer 	u_int8_t		reserved4;
    961  1.1  bouyer 	u_int16_t		slot_num;
    962  1.1  bouyer 
    963  1.1  bouyer 	u_int64_t		lookup_addr;
    964  1.1  bouyer 
    965  1.1  bouyer 	u_int32_t		ioc_param_value;
    966  1.1  bouyer 
    967  1.1  bouyer 	u_int64_t		reserved5;
    968  1.1  bouyer } __packed;
    969  1.1  bouyer 
    970  1.1  bouyer struct mpii_msg_sas_oper_reply {
    971  1.1  bouyer 	u_int8_t		operation;
    972  1.1  bouyer 	u_int8_t		reserved1;
    973  1.1  bouyer 	u_int8_t		chain_offset;
    974  1.1  bouyer 	u_int8_t		function;
    975  1.1  bouyer 
    976  1.1  bouyer 	u_int16_t		dev_handle;
    977  1.1  bouyer 	u_int8_t		ioc_param;
    978  1.1  bouyer 	u_int8_t		msg_flags;
    979  1.1  bouyer 
    980  1.1  bouyer 	u_int8_t		vp_id;
    981  1.1  bouyer 	u_int8_t		vf_id;
    982  1.1  bouyer 	u_int16_t		reserved2;
    983  1.1  bouyer 
    984  1.1  bouyer 	u_int16_t		reserved3;
    985  1.1  bouyer 	u_int16_t		ioc_status;
    986  1.1  bouyer 
    987  1.1  bouyer 	u_int32_t		ioc_loginfo;
    988  1.1  bouyer } __packed;
    989  1.1  bouyer 
    990  1.1  bouyer struct mpii_msg_raid_action_request {
    991  1.1  bouyer 	u_int8_t	action;
    992  1.1  bouyer #define MPII_RAID_ACTION_CHANGE_VOL_WRITE_CACHE	(0x17)
    993  1.1  bouyer 	u_int8_t	reserved1;
    994  1.1  bouyer 	u_int8_t	chain_offset;
    995  1.1  bouyer 	u_int8_t	function;
    996  1.1  bouyer 
    997  1.1  bouyer 	u_int16_t	vol_dev_handle;
    998  1.1  bouyer 	u_int8_t	phys_disk_num;
    999  1.1  bouyer 	u_int8_t	msg_flags;
   1000  1.1  bouyer 
   1001  1.1  bouyer 	u_int8_t	vp_id;
   1002  1.1  bouyer 	u_int8_t	vf_if;
   1003  1.1  bouyer 	u_int16_t	reserved2;
   1004  1.1  bouyer 
   1005  1.1  bouyer 	u_int32_t	reserved3;
   1006  1.1  bouyer 
   1007  1.1  bouyer 	u_int32_t	action_data;
   1008  1.1  bouyer #define MPII_RAID_VOL_WRITE_CACHE_MASK			(0x03)
   1009  1.1  bouyer #define MPII_RAID_VOL_WRITE_CACHE_DISABLE		(0x01)
   1010  1.1  bouyer #define MPII_RAID_VOL_WRITE_CACHE_ENABLE		(0x02)
   1011  1.1  bouyer 
   1012  1.1  bouyer 	struct mpii_sge	action_sge;
   1013  1.1  bouyer } __packed;
   1014  1.1  bouyer 
   1015  1.1  bouyer struct mpii_msg_raid_action_reply {
   1016  1.1  bouyer 	u_int8_t	action;
   1017  1.1  bouyer 	u_int8_t	reserved1;
   1018  1.1  bouyer 	u_int8_t	chain_offset;
   1019  1.1  bouyer 	u_int8_t	function;
   1020  1.1  bouyer 
   1021  1.1  bouyer 	u_int16_t	vol_dev_handle;
   1022  1.1  bouyer 	u_int8_t	phys_disk_num;
   1023  1.1  bouyer 	u_int8_t	msg_flags;
   1024  1.1  bouyer 
   1025  1.1  bouyer 	u_int8_t	vp_id;
   1026  1.1  bouyer 	u_int8_t	vf_if;
   1027  1.1  bouyer 	u_int16_t	reserved2;
   1028  1.1  bouyer 
   1029  1.1  bouyer 	u_int16_t	reserved3;
   1030  1.1  bouyer 	u_int16_t	ioc_status;
   1031  1.1  bouyer 
   1032  1.1  bouyer 	u_int32_t	action_data[5];
   1033  1.1  bouyer } __packed;
   1034  1.1  bouyer 
   1035  1.1  bouyer struct mpii_cfg_hdr {
   1036  1.1  bouyer 	u_int8_t		page_version;
   1037  1.1  bouyer 	u_int8_t		page_length;
   1038  1.1  bouyer 	u_int8_t		page_number;
   1039  1.1  bouyer 	u_int8_t		page_type;
   1040  1.1  bouyer #define MPII_CONFIG_REQ_PAGE_TYPE_ATTRIBUTE		(0xf0)
   1041  1.1  bouyer #define MPI2_CONFIG_PAGEATTR_READ_ONLY              	(0x00)
   1042  1.1  bouyer #define MPI2_CONFIG_PAGEATTR_CHANGEABLE             	(0x10)
   1043  1.1  bouyer #define MPI2_CONFIG_PAGEATTR_PERSISTENT             	(0x20)
   1044  1.1  bouyer 
   1045  1.1  bouyer #define MPII_CONFIG_REQ_PAGE_TYPE_MASK			(0x0f)
   1046  1.1  bouyer #define MPII_CONFIG_REQ_PAGE_TYPE_IO_UNIT		(0x00)
   1047  1.1  bouyer #define MPII_CONFIG_REQ_PAGE_TYPE_IOC			(0x01)
   1048  1.1  bouyer #define MPII_CONFIG_REQ_PAGE_TYPE_BIOS			(0x02)
   1049  1.1  bouyer #define MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL		(0x08)
   1050  1.1  bouyer #define MPII_CONFIG_REQ_PAGE_TYPE_MANUFACTURING		(0x09)
   1051  1.1  bouyer #define MPII_CONFIG_REQ_PAGE_TYPE_RAID_PD		(0x0a)
   1052  1.1  bouyer #define MPII_CONFIG_REQ_PAGE_TYPE_EXTENDED		(0x0f)
   1053  1.1  bouyer } __packed;
   1054  1.1  bouyer 
   1055  1.1  bouyer struct mpii_ecfg_hdr {
   1056  1.1  bouyer 	u_int8_t		page_version;
   1057  1.1  bouyer 	u_int8_t		reserved1;
   1058  1.1  bouyer 	u_int8_t		page_number;
   1059  1.1  bouyer 	u_int8_t		page_type;
   1060  1.1  bouyer 
   1061  1.1  bouyer 	u_int16_t		ext_page_length;
   1062  1.1  bouyer 	u_int8_t		ext_page_type;
   1063  1.1  bouyer #define MPII_CONFIG_REQ_PAGE_TYPE_SAS_DEVICE		(0x12)
   1064  1.1  bouyer #define MPII_CONFIG_REQ_PAGE_TYPE_RAID_CONFIG		(0x16)
   1065  1.1  bouyer #define MPII_CONFIG_REQ_PAGE_TYPE_DRIVER_MAPPING	(0x17)
   1066  1.1  bouyer 	u_int8_t		reserved2;
   1067  1.1  bouyer } __packed;
   1068  1.1  bouyer 
   1069  1.1  bouyer struct mpii_msg_config_request {
   1070  1.1  bouyer 	u_int8_t		action;
   1071  1.1  bouyer #define MPII_CONFIG_REQ_ACTION_PAGE_HEADER		(0x00)
   1072  1.1  bouyer #define MPII_CONFIG_REQ_ACTION_PAGE_READ_CURRENT	(0x01)
   1073  1.1  bouyer #define MPII_CONFIG_REQ_ACTION_PAGE_WRITE_CURRENT	(0x02)
   1074  1.1  bouyer #define MPII_CONFIG_REQ_ACTION_PAGE_DEFAULT		(0x03)
   1075  1.1  bouyer #define MPII_CONFIG_REQ_ACTION_PAGE_WRITE_NVRAM		(0x04)
   1076  1.1  bouyer #define MPII_CONFIG_REQ_ACTION_PAGE_READ_DEFAULT	(0x05)
   1077  1.1  bouyer #define MPII_CONFIG_REQ_ACTION_PAGE_READ_NVRAM		(0x06)
   1078  1.1  bouyer 	u_int8_t		sgl_flags;
   1079  1.1  bouyer 	u_int8_t		chain_offset;
   1080  1.1  bouyer 	u_int8_t		function;
   1081  1.1  bouyer 
   1082  1.1  bouyer 	u_int16_t		ext_page_len;
   1083  1.1  bouyer 	u_int8_t		ext_page_type;
   1084  1.1  bouyer #define MPII_CONFIG_REQ_EXTPAGE_TYPE_SAS_IO_UNIT	(0x10)
   1085  1.1  bouyer #define MPII_CONFIG_REQ_EXTPAGE_TYPE_SAS_EXPANDER	(0x11)
   1086  1.1  bouyer #define MPII_CONFIG_REQ_EXTPAGE_TYPE_SAS_DEVICE		(0x12)
   1087  1.1  bouyer #define MPII_CONFIG_REQ_EXTPAGE_TYPE_SAS_PHY		(0x13)
   1088  1.1  bouyer #define MPII_CONFIG_REQ_EXTPAGE_TYPE_LOG		(0x14)
   1089  1.1  bouyer #define MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE            	(0x15)
   1090  1.1  bouyer #define MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG         	(0x16)
   1091  1.1  bouyer #define MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING      	(0x17)
   1092  1.1  bouyer #define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT            	(0x18)
   1093  1.1  bouyer 	u_int8_t		msg_flags;
   1094  1.1  bouyer 
   1095  1.1  bouyer 	u_int8_t		vp_id;
   1096  1.1  bouyer 	u_int8_t		vf_id;
   1097  1.1  bouyer 	u_int16_t		reserved1;
   1098  1.1  bouyer 
   1099  1.1  bouyer 	u_int32_t		reserved2[2];
   1100  1.1  bouyer 
   1101  1.1  bouyer 	struct mpii_cfg_hdr	config_header;
   1102  1.1  bouyer 
   1103  1.1  bouyer 	u_int32_t		page_address;
   1104  1.1  bouyer /* XXX lots of defns here */
   1105  1.1  bouyer 
   1106  1.1  bouyer 	struct mpii_sge		page_buffer;
   1107  1.1  bouyer } __packed;
   1108  1.1  bouyer 
   1109  1.1  bouyer struct mpii_msg_config_reply {
   1110  1.1  bouyer 	u_int8_t		action;
   1111  1.1  bouyer 	u_int8_t		sgl_flags;
   1112  1.1  bouyer 	u_int8_t		msg_length;
   1113  1.1  bouyer 	u_int8_t		function;
   1114  1.1  bouyer 
   1115  1.1  bouyer 	u_int16_t		ext_page_length;
   1116  1.1  bouyer 	u_int8_t		ext_page_type;
   1117  1.1  bouyer 	u_int8_t		msg_flags;
   1118  1.1  bouyer 
   1119  1.1  bouyer 	u_int8_t		vp_id;
   1120  1.1  bouyer 	u_int8_t		vf_id;
   1121  1.1  bouyer 	u_int16_t		reserved1;
   1122  1.1  bouyer 
   1123  1.1  bouyer 	u_int16_t		reserved2;
   1124  1.1  bouyer 	u_int16_t		ioc_status;
   1125  1.1  bouyer 
   1126  1.1  bouyer 	u_int32_t		ioc_loginfo;
   1127  1.1  bouyer 
   1128  1.1  bouyer 	struct mpii_cfg_hdr	config_header;
   1129  1.1  bouyer } __packed;
   1130  1.1  bouyer 
   1131  1.1  bouyer struct mpii_cfg_manufacturing_pg0 {
   1132  1.1  bouyer 	struct mpii_cfg_hdr	config_header;
   1133  1.1  bouyer 
   1134  1.1  bouyer 	char			chip_name[16];
   1135  1.1  bouyer 	char			chip_revision[8];
   1136  1.1  bouyer 	char			board_name[16];
   1137  1.1  bouyer 	char			board_assembly[16];
   1138  1.1  bouyer 	char			board_tracer_number[16];
   1139  1.1  bouyer } __packed;
   1140  1.1  bouyer 
   1141  1.1  bouyer struct mpii_cfg_ioc_pg1 {
   1142  1.1  bouyer 	struct mpii_cfg_hdr     config_header;
   1143  1.1  bouyer 
   1144  1.1  bouyer 	u_int32_t       flags;
   1145  1.1  bouyer 
   1146  1.1  bouyer 	u_int32_t       coalescing_timeout;
   1147  1.1  bouyer #define	MPII_CFG_IOC_1_REPLY_COALESCING			(1<<0)
   1148  1.1  bouyer 
   1149  1.1  bouyer 	u_int8_t        coalescing_depth;
   1150  1.1  bouyer 	u_int8_t        pci_slot_num;
   1151  1.1  bouyer 	u_int8_t        pci_bus_num;
   1152  1.1  bouyer 	u_int8_t        pci_domain_segment;
   1153  1.1  bouyer 
   1154  1.1  bouyer 	u_int32_t       reserved1;
   1155  1.1  bouyer 
   1156  1.1  bouyer 	u_int32_t       reserved2;
   1157  1.1  bouyer } __packed;
   1158  1.1  bouyer 
   1159  1.1  bouyer struct mpii_cfg_ioc_pg3 {
   1160  1.1  bouyer 	struct mpii_cfg_hdr	config_header;
   1161  1.1  bouyer 
   1162  1.1  bouyer 	u_int8_t		no_phys_disks;
   1163  1.1  bouyer 	u_int8_t		reserved[3];
   1164  1.1  bouyer 
   1165  1.1  bouyer 	/* followed by a list of mpii_cfg_raid_physdisk structs */
   1166  1.1  bouyer } __packed;
   1167  1.1  bouyer 
   1168  1.1  bouyer struct mpii_cfg_ioc_pg8 {
   1169  1.1  bouyer 	struct mpii_cfg_hdr	config_header;
   1170  1.1  bouyer 
   1171  1.1  bouyer 	u_int8_t		num_devs_per_enclosure;
   1172  1.1  bouyer 	u_int8_t		reserved1;
   1173  1.1  bouyer 	u_int16_t		reserved2;
   1174  1.1  bouyer 
   1175  1.1  bouyer 	u_int16_t		max_persistent_entries;
   1176  1.1  bouyer 	u_int16_t		max_num_physical_mapped_ids;
   1177  1.1  bouyer 
   1178  1.1  bouyer 	u_int16_t		flags;
   1179  1.1  bouyer #define	MPII_IOC_PG8_FLAGS_DA_START_SLOT_1		(1<<5)
   1180  1.1  bouyer #define MPII_IOC_PG8_FLAGS_RESERVED_TARGETID_0		(1<<4)
   1181  1.1  bouyer #define MPII_IOC_PG8_FLAGS_MAPPING_MODE_MASK		(0x0000000e)
   1182  1.1  bouyer #define MPII_IOC_PG8_FLAGS_DEVICE_PERSISTENCE_MAPPING	(0<<1)
   1183  1.1  bouyer #define MPII_IOC_PG8_FLAGS_ENCLOSURE_SLOT_MAPPING	(1<<1)
   1184  1.1  bouyer #define MPII_IOC_PG8_FLAGS_DISABLE_PERSISTENT_MAPPING	(1<<0)
   1185  1.1  bouyer #define	MPII_IOC_PG8_FLAGS_ENABLE_PERSISTENT_MAPPING	(0<<0)
   1186  1.1  bouyer 	u_int16_t		reserved3;
   1187  1.1  bouyer 
   1188  1.1  bouyer 	u_int16_t		ir_volume_mapping_flags;
   1189  1.1  bouyer #define	MPII_IOC_PG8_IRFLAGS_VOLUME_MAPPING_MODE_MASK	(0x00000003)
   1190  1.1  bouyer #define	MPII_IOC_PG8_IRFLAGS_LOW_VOLUME_MAPPING		(0<<0)
   1191  1.1  bouyer #define	MPII_IOC_PG8_IRFLAGS_HIGH_VOLUME_MAPPING	(1<<0)
   1192  1.1  bouyer 	u_int16_t		reserved4;
   1193  1.1  bouyer 
   1194  1.1  bouyer 	u_int32_t		reserved5;
   1195  1.1  bouyer } __packed;
   1196  1.1  bouyer 
   1197  1.1  bouyer struct mpii_cfg_raid_physdisk {
   1198  1.1  bouyer 	u_int8_t		phys_disk_id;
   1199  1.1  bouyer 	u_int8_t		phys_disk_bus;
   1200  1.1  bouyer 	u_int8_t		phys_disk_ioc;
   1201  1.1  bouyer 	u_int8_t		phys_disk_num;
   1202  1.1  bouyer } __packed;
   1203  1.1  bouyer 
   1204  1.1  bouyer struct mpii_cfg_fc_port_pg0 {
   1205  1.1  bouyer 	struct mpii_cfg_hdr	config_header;
   1206  1.1  bouyer 
   1207  1.1  bouyer 	u_int32_t		flags;
   1208  1.1  bouyer 
   1209  1.1  bouyer 	u_int8_t		mpii_port_nr;
   1210  1.1  bouyer 	u_int8_t		link_type;
   1211  1.1  bouyer 	u_int8_t		port_state;
   1212  1.1  bouyer 	u_int8_t		reserved1;
   1213  1.1  bouyer 
   1214  1.1  bouyer 	u_int32_t		port_id;
   1215  1.1  bouyer 
   1216  1.1  bouyer 	u_int64_t		wwnn;
   1217  1.1  bouyer 
   1218  1.1  bouyer 	u_int64_t		wwpn;
   1219  1.1  bouyer 
   1220  1.1  bouyer 	u_int32_t		supported_service_class;
   1221  1.1  bouyer 
   1222  1.1  bouyer 	u_int32_t		supported_speeds;
   1223  1.1  bouyer 
   1224  1.1  bouyer 	u_int32_t		current_speed;
   1225  1.1  bouyer 
   1226  1.1  bouyer 	u_int32_t		max_frame_size;
   1227  1.1  bouyer 
   1228  1.1  bouyer 	u_int64_t		fabric_wwnn;
   1229  1.1  bouyer 
   1230  1.1  bouyer 	u_int64_t		fabric_wwpn;
   1231  1.1  bouyer 
   1232  1.1  bouyer 	u_int32_t		discovered_port_count;
   1233  1.1  bouyer 
   1234  1.1  bouyer 	u_int32_t		max_initiators;
   1235  1.1  bouyer 
   1236  1.1  bouyer 	u_int8_t		max_aliases_supported;
   1237  1.1  bouyer 	u_int8_t		max_hard_aliases_supported;
   1238  1.1  bouyer 	u_int8_t		num_current_aliases;
   1239  1.1  bouyer 	u_int8_t		reserved2;
   1240  1.1  bouyer } __packed;
   1241  1.1  bouyer 
   1242  1.1  bouyer struct mpii_cfg_fc_port_pg1 {
   1243  1.1  bouyer 	struct mpii_cfg_hdr	config_header;
   1244  1.1  bouyer 
   1245  1.1  bouyer 	u_int32_t		flags;
   1246  1.1  bouyer 
   1247  1.1  bouyer 	u_int64_t		noseepromwwnn;
   1248  1.1  bouyer 
   1249  1.1  bouyer 	u_int64_t		noseepromwwpn;
   1250  1.1  bouyer 
   1251  1.1  bouyer 	u_int8_t		hard_alpa;
   1252  1.1  bouyer 	u_int8_t		link_config;
   1253  1.1  bouyer 	u_int8_t		topology_config;
   1254  1.1  bouyer 	u_int8_t		alt_connector;
   1255  1.1  bouyer 
   1256  1.1  bouyer 	u_int8_t		num_req_aliases;
   1257  1.1  bouyer 	u_int8_t		rr_tov;
   1258  1.1  bouyer 	u_int8_t		initiator_dev_to;
   1259  1.1  bouyer 	u_int8_t		initiator_lo_pend_to;
   1260  1.1  bouyer } __packed;
   1261  1.1  bouyer 
   1262  1.1  bouyer struct mpii_cfg_fc_device_pg0 {
   1263  1.1  bouyer 	struct mpii_cfg_hdr	config_header;
   1264  1.1  bouyer 
   1265  1.1  bouyer 	u_int64_t		wwnn;
   1266  1.1  bouyer 
   1267  1.1  bouyer 	u_int64_t		wwpn;
   1268  1.1  bouyer 
   1269  1.1  bouyer 	u_int32_t		port_id;
   1270  1.1  bouyer 
   1271  1.1  bouyer 	u_int8_t		protocol;
   1272  1.1  bouyer 	u_int8_t		flags;
   1273  1.1  bouyer 	u_int16_t		bb_credit;
   1274  1.1  bouyer 
   1275  1.1  bouyer 	u_int16_t		max_rx_frame_size;
   1276  1.1  bouyer 	u_int8_t		adisc_hard_alpa;
   1277  1.1  bouyer 	u_int8_t		port_nr;
   1278  1.1  bouyer 
   1279  1.1  bouyer 	u_int8_t		fc_ph_low_version;
   1280  1.1  bouyer 	u_int8_t		fc_ph_high_version;
   1281  1.1  bouyer 	u_int8_t		current_target_id;
   1282  1.1  bouyer 	u_int8_t		current_bus;
   1283  1.1  bouyer } __packed;
   1284  1.1  bouyer 
   1285  1.1  bouyer #define MPII_CFG_RAID_VOL_ADDR_HANDLE		(1<<28)
   1286  1.1  bouyer 
   1287  1.1  bouyer struct mpii_cfg_raid_vol_pg0 {
   1288  1.1  bouyer 	struct mpii_cfg_hdr	config_header;
   1289  1.1  bouyer 
   1290  1.1  bouyer 	u_int16_t		volume_handle;
   1291  1.1  bouyer 	u_int8_t		volume_state;
   1292  1.1  bouyer #define MPII_CFG_RAID_VOL_0_STATE_MISSING		(0x00)
   1293  1.1  bouyer #define MPII_CFG_RAID_VOL_0_STATE_FAILED		(0x01)
   1294  1.1  bouyer #define MPII_CFG_RAID_VOL_0_STATE_INITIALIZING		(0x02)
   1295  1.1  bouyer #define MPII_CFG_RAID_VOL_0_STATE_ONLINE		(0x03)
   1296  1.1  bouyer #define MPII_CFG_RAID_VOL_0_STATE_DEGRADED		(0x04)
   1297  1.1  bouyer #define MPII_CFG_RAID_VOL_0_STATE_OPTIMAL		(0x05)
   1298  1.1  bouyer 	u_int8_t		volume_type;
   1299  1.1  bouyer #define MPII_CFG_RAID_VOL_0_TYPE_RAID0			(0x00)
   1300  1.1  bouyer #define MPII_CFG_RAID_VOL_0_TYPE_RAID1E			(0x01)
   1301  1.1  bouyer #define MPII_CFG_RAID_VOL_0_TYPE_RAID1			(0x02)
   1302  1.1  bouyer #define MPII_CFG_RAID_VOL_0_TYPE_RAID10			(0x05)
   1303  1.1  bouyer #define MPII_CFG_RAID_VOL_0_TYPE_UNKNOWN		(0xff)
   1304  1.1  bouyer 
   1305  1.1  bouyer 	u_int32_t		volume_status;
   1306  1.1  bouyer #define MPII_CFG_RAID_VOL_0_STATUS_SCRUB		(1<<20)
   1307  1.1  bouyer #define MPII_CFG_RAID_VOL_0_STATUS_RESYNC		(1<<16)
   1308  1.1  bouyer 
   1309  1.1  bouyer 	u_int16_t		volume_settings;
   1310  1.1  bouyer #define MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_MASK		(0x3<<0)
   1311  1.1  bouyer #define MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_UNCHANGED	(0x0<<0)
   1312  1.1  bouyer #define MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_DISABLED	(0x1<<0)
   1313  1.1  bouyer #define MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_ENABLED	(0x2<<0)
   1314  1.1  bouyer 
   1315  1.1  bouyer 	u_int8_t		hot_spare_pool;
   1316  1.1  bouyer 	u_int8_t		reserved1;
   1317  1.1  bouyer 
   1318  1.1  bouyer 	u_int64_t		max_lba;
   1319  1.1  bouyer 
   1320  1.1  bouyer 	u_int32_t		stripe_size;
   1321  1.1  bouyer 
   1322  1.1  bouyer 	u_int16_t		block_size;
   1323  1.1  bouyer 	u_int16_t		reserved2;
   1324  1.1  bouyer 
   1325  1.1  bouyer 	u_int8_t		phys_disk_types;
   1326  1.1  bouyer 	u_int8_t		resync_rate;
   1327  1.1  bouyer 	u_int16_t		data_scrub_rate;
   1328  1.1  bouyer 
   1329  1.1  bouyer 	u_int8_t		num_phys_disks;
   1330  1.1  bouyer 	u_int16_t		reserved3;
   1331  1.1  bouyer 	u_int8_t		inactive_status;
   1332  1.1  bouyer #define MPII_CFG_RAID_VOL_0_INACTIVE_UNKNOWN		(0x00)
   1333  1.1  bouyer #define MPII_CFG_RAID_VOL_0_INACTIVE_STALE_META		(0x01)
   1334  1.1  bouyer #define MPII_CFG_RAID_VOL_0_INACTIVE_FOREIGN_VOL	(0x02)
   1335  1.1  bouyer #define MPII_CFG_RAID_VOL_0_INACTIVE_NO_RESOURCES	(0x03)
   1336  1.1  bouyer #define MPII_CFG_RAID_VOL_0_INACTIVE_CLONED_VOL		(0x04)
   1337  1.1  bouyer #define MPII_CFG_RAID_VOL_0_INACTIVE_INSUF_META		(0x05)
   1338  1.1  bouyer 
   1339  1.1  bouyer 	/* followed by a list of mpii_cfg_raid_vol_pg0_physdisk structs */
   1340  1.1  bouyer } __packed;
   1341  1.1  bouyer 
   1342  1.1  bouyer struct mpii_cfg_raid_vol_pg0_physdisk {
   1343  1.1  bouyer 	u_int8_t		raid_set_num;
   1344  1.1  bouyer 	u_int8_t		phys_disk_map;
   1345  1.1  bouyer 	u_int8_t		phys_disk_num;
   1346  1.1  bouyer 	u_int8_t		reserved;
   1347  1.1  bouyer } __packed;
   1348  1.1  bouyer 
   1349  1.1  bouyer struct mpii_cfg_raid_vol_pg1 {
   1350  1.1  bouyer 	struct mpii_cfg_hdr	config_header;
   1351  1.1  bouyer 
   1352  1.1  bouyer 	u_int8_t		volume_id;
   1353  1.1  bouyer 	u_int8_t		volume_bus;
   1354  1.1  bouyer 	u_int8_t		volume_ioc;
   1355  1.1  bouyer 	u_int8_t		reserved1;
   1356  1.1  bouyer 
   1357  1.1  bouyer 	u_int8_t		guid[24];
   1358  1.1  bouyer 
   1359  1.1  bouyer 	u_int8_t		name[32];
   1360  1.1  bouyer 
   1361  1.1  bouyer 	u_int64_t		wwid;
   1362  1.1  bouyer 
   1363  1.1  bouyer 	u_int32_t		reserved2;
   1364  1.1  bouyer 
   1365  1.1  bouyer 	u_int32_t		reserved3;
   1366  1.1  bouyer } __packed;
   1367  1.1  bouyer 
   1368  1.1  bouyer #define MPII_CFG_RAID_PHYS_DISK_ADDR_NUMBER		(1<<28)
   1369  1.1  bouyer 
   1370  1.1  bouyer struct mpii_cfg_raid_physdisk_pg0 {
   1371  1.1  bouyer 	struct mpii_cfg_hdr	config_header;
   1372  1.1  bouyer 
   1373  1.1  bouyer 	u_int16_t		dev_handle;
   1374  1.1  bouyer 	u_int8_t		reserved1;
   1375  1.1  bouyer 	u_int8_t		phys_disk_num;
   1376  1.1  bouyer 
   1377  1.1  bouyer 	u_int8_t		enc_id;
   1378  1.1  bouyer 	u_int8_t		enc_bus;
   1379  1.1  bouyer 	u_int8_t		hot_spare_pool;
   1380  1.1  bouyer 	u_int8_t		enc_type;
   1381  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_ENCTYPE_NONE		(0x0)
   1382  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_ENCTYPE_SAFTE		(0x1)
   1383  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_ENCTYPE_SES		(0x2)
   1384  1.1  bouyer 
   1385  1.1  bouyer 	u_int32_t		reserved2;
   1386  1.1  bouyer 
   1387  1.1  bouyer 	u_int8_t		vendor_id[8];
   1388  1.1  bouyer 
   1389  1.1  bouyer 	u_int8_t		product_id[16];
   1390  1.1  bouyer 
   1391  1.1  bouyer 	u_int8_t		product_rev[4];
   1392  1.1  bouyer 
   1393  1.1  bouyer 	u_int8_t		serial[32];
   1394  1.1  bouyer 
   1395  1.1  bouyer 	u_int32_t		reserved3;
   1396  1.1  bouyer 
   1397  1.1  bouyer 	u_int8_t		phys_disk_state;
   1398  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_STATE_NOTCONFIGURED	(0x00)
   1399  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_STATE_NOTCOMPATIBLE	(0x01)
   1400  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_STATE_OFFLINE		(0x02)
   1401  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_STATE_ONLINE		(0x03)
   1402  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_STATE_HOTSPARE		(0x04)
   1403  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_STATE_DEGRADED		(0x05)
   1404  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_STATE_REBUILDING	(0x06)
   1405  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_STATE_OPTIMAL		(0x07)
   1406  1.1  bouyer 	u_int8_t		offline_reason;
   1407  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_OFFLINE_MISSING		(0x01)
   1408  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_OFFLINE_FAILED		(0x03)
   1409  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_OFFLINE_INITIALIZING	(0x04)
   1410  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_OFFLINE_REQUESTED	(0x05)
   1411  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_OFFLINE_FAILEDREQ	(0x06)
   1412  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_OFFLINE_OTHER		(0xff)
   1413  1.1  bouyer 
   1414  1.1  bouyer 	u_int8_t		incompat_reason;
   1415  1.1  bouyer 	u_int8_t		phys_disk_attrs;
   1416  1.1  bouyer 
   1417  1.1  bouyer 	u_int32_t		phys_disk_status;
   1418  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_STATUS_OUTOFSYNC	(1<<0)
   1419  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_0_STATUS_QUIESCED		(1<<1)
   1420  1.1  bouyer 
   1421  1.1  bouyer 	u_int64_t		dev_max_lba;
   1422  1.1  bouyer 
   1423  1.1  bouyer 	u_int64_t		host_max_lba;
   1424  1.1  bouyer 
   1425  1.1  bouyer 	u_int64_t		coerced_max_lba;
   1426  1.1  bouyer 
   1427  1.1  bouyer 	u_int16_t		block_size;
   1428  1.1  bouyer 	u_int16_t		reserved4;
   1429  1.1  bouyer 
   1430  1.1  bouyer 	u_int32_t		reserved5;
   1431  1.1  bouyer } __packed;
   1432  1.1  bouyer 
   1433  1.1  bouyer struct mpii_cfg_raid_physdisk_pg1 {
   1434  1.1  bouyer 	struct mpii_cfg_hdr	config_header;
   1435  1.1  bouyer 
   1436  1.1  bouyer 	u_int8_t		num_phys_disk_paths;
   1437  1.1  bouyer 	u_int8_t		phys_disk_num;
   1438  1.1  bouyer 	u_int16_t		reserved1;
   1439  1.1  bouyer 
   1440  1.1  bouyer 	u_int32_t		reserved2;
   1441  1.1  bouyer 
   1442  1.1  bouyer 	/* followed by mpii_cfg_raid_physdisk_path structs */
   1443  1.1  bouyer } __packed;
   1444  1.1  bouyer 
   1445  1.1  bouyer struct mpii_cfg_raid_physdisk_path {
   1446  1.1  bouyer 	u_int8_t		phys_disk_id;
   1447  1.1  bouyer 	u_int8_t		phys_disk_bus;
   1448  1.1  bouyer 	u_int16_t		reserved1;
   1449  1.1  bouyer 
   1450  1.1  bouyer 	u_int64_t		wwwid;
   1451  1.1  bouyer 
   1452  1.1  bouyer 	u_int64_t		owner_wwid;
   1453  1.1  bouyer 
   1454  1.1  bouyer 	u_int8_t		ownder_id;
   1455  1.1  bouyer 	u_int8_t		reserved2;
   1456  1.1  bouyer 	u_int16_t		flags;
   1457  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_PATH_INVALID	(1<<0)
   1458  1.1  bouyer #define MPII_CFG_RAID_PHYDISK_PATH_BROKEN	(1<<1)
   1459  1.1  bouyer } __packed;
   1460  1.1  bouyer 
   1461  1.1  bouyer #define MPII_CFG_SAS_DEV_ADDR_NEXT		(0<<28)
   1462  1.1  bouyer #define MPII_CFG_SAS_DEV_ADDR_BUS		(1<<28)
   1463  1.1  bouyer #define MPII_CFG_SAS_DEV_ADDR_HANDLE		(2<<28)
   1464  1.1  bouyer 
   1465  1.1  bouyer struct mpii_cfg_sas_dev_pg0 {
   1466  1.1  bouyer 	struct mpii_ecfg_hdr	config_header;
   1467  1.1  bouyer 
   1468  1.1  bouyer 	u_int16_t		slot;
   1469  1.1  bouyer 	u_int16_t		enc_handle;
   1470  1.1  bouyer 
   1471  1.1  bouyer 	u_int64_t		sas_addr;
   1472  1.1  bouyer 
   1473  1.1  bouyer 	u_int16_t		parent_dev_handle;
   1474  1.1  bouyer 	u_int8_t		phy_num;
   1475  1.1  bouyer 	u_int8_t		access_status;
   1476  1.1  bouyer 
   1477  1.1  bouyer 	u_int16_t		dev_handle;
   1478  1.1  bouyer 	u_int8_t		target;
   1479  1.1  bouyer 	u_int8_t		bus;
   1480  1.1  bouyer 
   1481  1.1  bouyer 	u_int32_t		device_info;
   1482  1.1  bouyer #define MPII_CFG_SAS_DEV_0_DEVINFO_TYPE			(0x7)
   1483  1.1  bouyer #define MPII_CFG_SAS_DEV_0_DEVINFO_TYPE_NONE		(0x0)
   1484  1.1  bouyer #define MPII_CFG_SAS_DEV_0_DEVINFO_TYPE_END		(0x1)
   1485  1.1  bouyer #define MPII_CFG_SAS_DEV_0_DEVINFO_TYPE_EDGE_EXPANDER	(0x2)
   1486  1.1  bouyer #define MPII_CFG_SAS_DEV_0_DEVINFO_TYPE_FANOUT_EXPANDER	(0x3)
   1487  1.1  bouyer #define MPII_CFG_SAS_DEV_0_DEVINFO_SATA_HOST		(1<<3)
   1488  1.1  bouyer #define MPII_CFG_SAS_DEV_0_DEVINFO_SMP_INITIATOR	(1<<4)
   1489  1.1  bouyer #define MPII_CFG_SAS_DEV_0_DEVINFO_STP_INITIATOR	(1<<5)
   1490  1.1  bouyer #define MPII_CFG_SAS_DEV_0_DEVINFO_SSP_INITIATOR	(1<<6)
   1491  1.1  bouyer #define MPII_CFG_SAS_DEV_0_DEVINFO_SATA_DEVICE		(1<<7)
   1492  1.1  bouyer #define MPII_CFG_SAS_DEV_0_DEVINFO_SMP_TARGET		(1<<8)
   1493  1.1  bouyer #define MPII_CFG_SAS_DEV_0_DEVINFO_STP_TARGET		(1<<9)
   1494  1.1  bouyer #define MPII_CFG_SAS_DEV_0_DEVINFO_SSP_TARGET		(1<<10)
   1495  1.1  bouyer #define MPII_CFG_SAS_DEV_0_DEVINFO_DIRECT_ATTACHED	(1<<11)
   1496  1.1  bouyer #define MPII_CFG_SAS_DEV_0_DEVINFO_LSI_DEVICE		(1<<12)
   1497  1.1  bouyer #define MPII_CFG_SAS_DEV_0_DEVINFO_ATAPI_DEVICE		(1<<13)
   1498  1.1  bouyer #define MPII_CFG_SAS_DEV_0_DEVINFO_SEP_DEVICE		(1<<14)
   1499  1.1  bouyer 
   1500  1.1  bouyer 	u_int16_t		flags;
   1501  1.1  bouyer #define MPII_CFG_SAS_DEV_0_FLAGS_DEV_PRESENT		(1<<0)
   1502  1.1  bouyer #define MPII_CFG_SAS_DEV_0_FLAGS_DEV_MAPPED		(1<<1)
   1503  1.1  bouyer #define MPII_CFG_SAS_DEV_0_FLAGS_DEV_MAPPED_PERSISTENT	(1<<2)
   1504  1.1  bouyer #define MPII_CFG_SAS_DEV_0_FLAGS_SATA_PORT_SELECTOR	(1<<3)
   1505  1.1  bouyer #define MPII_CFG_SAS_DEV_0_FLAGS_SATA_FUA		(1<<4)
   1506  1.1  bouyer #define MPII_CFG_SAS_DEV_0_FLAGS_SATA_NCQ		(1<<5)
   1507  1.1  bouyer #define MPII_CFG_SAS_DEV_0_FLAGS_SATA_SMART		(1<<6)
   1508  1.1  bouyer #define MPII_CFG_SAS_DEV_0_FLAGS_SATA_LBA48		(1<<7)
   1509  1.1  bouyer #define MPII_CFG_SAS_DEV_0_FLAGS_UNSUPPORTED		(1<<8)
   1510  1.1  bouyer #define MPII_CFG_SAS_DEV_0_FLAGS_SATA_SETTINGS		(1<<9)
   1511  1.1  bouyer 	u_int8_t		physical_port;
   1512  1.1  bouyer 	u_int8_t		max_port_conn;
   1513  1.1  bouyer 
   1514  1.1  bouyer 	u_int64_t		device_name;
   1515  1.1  bouyer 
   1516  1.1  bouyer 	u_int8_t		port_groups;
   1517  1.1  bouyer 	u_int8_t		dma_group;
   1518  1.1  bouyer 	u_int8_t		ctrl_group;
   1519  1.1  bouyer 	u_int8_t		reserved1;
   1520  1.1  bouyer 
   1521  1.1  bouyer 	u_int64_t		reserved2;
   1522  1.1  bouyer } __packed;
   1523  1.1  bouyer 
   1524  1.1  bouyer #define MPII_CFG_RAID_CONFIG_ACTIVE_CONFIG		(2<<28)
   1525  1.1  bouyer 
   1526  1.1  bouyer struct mpii_cfg_raid_config_pg0 {
   1527  1.1  bouyer 	struct	mpii_ecfg_hdr	config_header;
   1528  1.1  bouyer 
   1529  1.1  bouyer 	u_int8_t		num_hot_spares;
   1530  1.1  bouyer 	u_int8_t		num_phys_disks;
   1531  1.1  bouyer 	u_int8_t		num_volumes;
   1532  1.1  bouyer 	u_int8_t		config_num;
   1533  1.1  bouyer 
   1534  1.1  bouyer 	u_int32_t		flags;
   1535  1.1  bouyer #define MPII_CFG_RAID_CONFIG_0_FLAGS_NATIVE		(0<<0)
   1536  1.1  bouyer #define MPII_CFG_RAID_CONFIG_0_FLAGS_FOREIGN		(1<<0)
   1537  1.1  bouyer 
   1538  1.1  bouyer 	u_int32_t		config_guid[6];
   1539  1.1  bouyer 
   1540  1.1  bouyer 	u_int32_t		reserved1;
   1541  1.1  bouyer 
   1542  1.1  bouyer 	u_int8_t		num_elements;
   1543  1.1  bouyer 	u_int8_t		reserved2[3];
   1544  1.1  bouyer 
   1545  1.1  bouyer 	/* followed by struct mpii_raid_config_element structs */
   1546  1.1  bouyer } __packed;
   1547  1.1  bouyer 
   1548  1.1  bouyer struct mpii_raid_config_element {
   1549  1.1  bouyer 	u_int16_t		element_flags;
   1550  1.1  bouyer #define MPII_RAID_CONFIG_ELEMENT_FLAG_VOLUME		(0x0)
   1551  1.1  bouyer #define MPII_RAID_CONFIG_ELEMENT_FLAG_VOLUME_PHYS_DISK	(0x1)
   1552  1.1  bouyer #define	MPII_RAID_CONFIG_ELEMENT_FLAG_HSP_PHYS_DISK	(0x2)
   1553  1.1  bouyer #define MPII_RAID_CONFIG_ELEMENT_ONLINE_CE_PHYS_DISK	(0x3)
   1554  1.1  bouyer 	u_int16_t		vol_dev_handle;
   1555  1.1  bouyer 
   1556  1.1  bouyer 	u_int8_t		hot_spare_pool;
   1557  1.1  bouyer 	u_int8_t		phys_disk_num;
   1558  1.1  bouyer 	u_int16_t		phys_disk_dev_handle;
   1559  1.1  bouyer } __packed;
   1560  1.1  bouyer 
   1561  1.1  bouyer struct mpii_cfg_dpm_pg0 {
   1562  1.1  bouyer 	struct mpii_ecfg_hdr	config_header;
   1563  1.1  bouyer #define MPII_DPM_ADDRESS_FORM_MASK			(0xf0000000)
   1564  1.1  bouyer #define MPII_DPM_ADDRESS_FORM_ENTRY_RANGE		(0x00000000)
   1565  1.1  bouyer #define MPII_DPM_ADDRESS_ENTRY_COUNT_MASK		(0x0fff0000)
   1566  1.1  bouyer #define MPII_DPM_ADDRESS_ENTRY_COUNT_SHIFT		(16)
   1567  1.1  bouyer #define MPII_DPM_ADDRESS_START_ENTRY_MASK		(0x0000ffff)
   1568  1.1  bouyer 
   1569  1.1  bouyer 	/* followed by struct mpii_dpm_entry structs */
   1570  1.1  bouyer } __packed;
   1571  1.1  bouyer 
   1572  1.1  bouyer struct mpii_dpm_entry {
   1573  1.1  bouyer 	u_int64_t		physical_identifier;
   1574  1.1  bouyer 
   1575  1.1  bouyer 	u_int16_t		mapping_information;
   1576  1.1  bouyer 	u_int16_t		device_index;
   1577  1.1  bouyer 
   1578  1.1  bouyer 	u_int32_t		physical_bits_mapping;
   1579  1.1  bouyer 
   1580  1.1  bouyer 	u_int32_t		reserved1;
   1581  1.1  bouyer } __packed;
   1582  1.1  bouyer 
   1583  1.1  bouyer struct mpii_evt_sas_discovery {
   1584  1.1  bouyer 	u_int8_t		flags;
   1585  1.1  bouyer #define	MPII_EVENT_SAS_DISC_FLAGS_DEV_CHANGE_MASK	(1<<1)
   1586  1.1  bouyer #define MPII_EVENT_SAS_DISC_FLAGS_DEV_CHANGE_NO_CHANGE	(0<<1)
   1587  1.1  bouyer #define MPII_EVENT_SAS_DISC_FLAGS_DEV_CHANGE_CHANGE	(1<<1)
   1588  1.1  bouyer #define MPII_EVENT_SAS_DISC_FLAGS_DISC_IN_PROG_MASK	(1<<0)
   1589  1.1  bouyer #define MPII_EVENT_SAS_DISC_FLAGS_DISC_NOT_IN_PROGRESS	(1<<0)
   1590  1.1  bouyer #define MPII_EVENT_SAS_DISC_FLAGS_DISC_IN_PROGRESS	(0<<0)
   1591  1.1  bouyer 	u_int8_t		reason_code;
   1592  1.1  bouyer #define MPII_EVENT_SAS_DISC_REASON_CODE_STARTED		(0x01)
   1593  1.1  bouyer #define	MPII_EVENT_SAS_DISC_REASON_CODE_COMPLETED	(0x02)
   1594  1.1  bouyer 	u_int8_t		physical_port;
   1595  1.1  bouyer 	u_int8_t		reserved1;
   1596  1.1  bouyer 
   1597  1.1  bouyer 	u_int32_t		discovery_status;
   1598  1.1  bouyer } __packed;
   1599  1.1  bouyer 
   1600  1.1  bouyer struct mpii_evt_ir_status {
   1601  1.1  bouyer 	u_int16_t		vol_dev_handle;
   1602  1.1  bouyer 	u_int16_t		reserved1;
   1603  1.1  bouyer 
   1604  1.1  bouyer 	u_int8_t		operation;
   1605  1.1  bouyer #define MPII_EVENT_IR_RAIDOP_RESYNC			(0x00)
   1606  1.1  bouyer #define MPII_EVENT_IR_RAIDOP_OCE			(0x01)
   1607  1.1  bouyer #define MPII_EVENT_IR_RAIDOP_CONS_CHECK			(0x02)
   1608  1.1  bouyer #define MPII_EVENT_IR_RAIDOP_BG_INIT			(0x03)
   1609  1.1  bouyer #define MPII_EVENT_IR_RAIDOP_MAKE_CONS			(0x04)
   1610  1.1  bouyer 	u_int8_t		percent;
   1611  1.1  bouyer 	u_int16_t		reserved2;
   1612  1.1  bouyer 
   1613  1.1  bouyer 	u_int32_t		reserved3;
   1614  1.1  bouyer };
   1615  1.1  bouyer 
   1616  1.1  bouyer struct mpii_evt_ir_volume {
   1617  1.1  bouyer 	u_int16_t		vol_dev_handle;
   1618  1.1  bouyer 	u_int8_t		reason_code;
   1619  1.1  bouyer #define MPII_EVENT_IR_VOL_RC_SETTINGS_CHANGED		(0x01)
   1620  1.1  bouyer #define MPII_EVENT_IR_VOL_RC_STATUS_CHANGED		(0x02)
   1621  1.1  bouyer #define MPII_EVENT_IR_VOL_RC_STATE_CHANGED		(0x03)
   1622  1.1  bouyer 	u_int8_t		reserved1;
   1623  1.1  bouyer 
   1624  1.1  bouyer 	u_int32_t		new_value;
   1625  1.1  bouyer 	u_int32_t		prev_value;
   1626  1.1  bouyer } __packed;
   1627  1.1  bouyer 
   1628  1.1  bouyer struct mpii_evt_ir_physical_disk {
   1629  1.1  bouyer 	u_int16_t		reserved1;
   1630  1.1  bouyer 	u_int8_t		reason_code;
   1631  1.1  bouyer #define MPII_EVENT_IR_PD_RC_SETTINGS_CHANGED		(0x01)
   1632  1.1  bouyer #define MPII_EVENT_IR_PD_RC_STATUS_FLAGS_CHANGED	(0x02)
   1633  1.1  bouyer #define MPII_EVENT_IR_PD_RC_STATUS_CHANGED		(0x03)
   1634  1.1  bouyer 	u_int8_t		phys_disk_num;
   1635  1.1  bouyer 
   1636  1.1  bouyer 	u_int16_t		phys_disk_dev_handle;
   1637  1.1  bouyer 	u_int16_t		reserved2;
   1638  1.1  bouyer 
   1639  1.1  bouyer 	u_int16_t		slot;
   1640  1.1  bouyer 	u_int16_t		enclosure_handle;
   1641  1.1  bouyer 
   1642  1.1  bouyer 	u_int32_t		new_value;
   1643  1.1  bouyer 	u_int32_t		previous_value;
   1644  1.1  bouyer } __packed;
   1645  1.1  bouyer 
   1646  1.1  bouyer struct mpii_evt_sas_tcl {
   1647  1.1  bouyer 	u_int16_t		enclosure_handle;
   1648  1.1  bouyer 	u_int16_t		expander_handle;
   1649  1.1  bouyer 
   1650  1.1  bouyer 	u_int8_t		num_phys;
   1651  1.1  bouyer 	u_int8_t		reserved1[3];
   1652  1.1  bouyer 
   1653  1.1  bouyer 	u_int8_t		num_entries;
   1654  1.1  bouyer 	u_int8_t		start_phy_num;
   1655  1.1  bouyer 	u_int8_t		expn_status;
   1656  1.1  bouyer #define	MPII_EVENT_SAS_TOPO_ES_ADDED			(0x01)
   1657  1.1  bouyer #define MPII_EVENT_SAS_TOPO_ES_NOT_RESPONDING		(0x02)
   1658  1.1  bouyer #define MPII_EVENT_SAS_TOPO_ES_RESPONDING		(0x03)
   1659  1.1  bouyer #define MPII_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING	(0x04)
   1660  1.1  bouyer 	u_int8_t		physical_port;
   1661  1.1  bouyer 
   1662  1.1  bouyer 	/* followed by num_entries number of struct mpii_evt_phy_entry */
   1663  1.1  bouyer } __packed;
   1664  1.1  bouyer 
   1665  1.1  bouyer struct mpii_evt_phy_entry {
   1666  1.1  bouyer 	u_int16_t		dev_handle;
   1667  1.1  bouyer 	u_int8_t		link_rate;
   1668  1.1  bouyer 	u_int8_t		phy_status;
   1669  1.1  bouyer #define MPII_EVENT_SAS_TOPO_PS_RC_MASK			(0x0f)
   1670  1.1  bouyer #define MPII_EVENT_SAS_TOPO_PS_RC_ADDED			(0x01)
   1671  1.1  bouyer #define MPII_EVENT_SAS_TOPO_PS_RC_MISSING		(0x02)
   1672  1.1  bouyer } __packed;
   1673  1.1  bouyer 
   1674  1.1  bouyer struct mpii_evt_ir_cfg_change_list {
   1675  1.1  bouyer 	u_int8_t		num_elements;
   1676  1.1  bouyer 	u_int16_t		reserved;
   1677  1.1  bouyer 	u_int8_t		config_num;
   1678  1.1  bouyer 
   1679  1.1  bouyer 	u_int32_t		flags;
   1680  1.1  bouyer #define MPII_EVT_IR_CFG_CHANGE_LIST_FOREIGN		(0x1)
   1681  1.1  bouyer 
   1682  1.1  bouyer 	/* followed by num_elements struct mpii_evt_ir_cfg_elements */
   1683  1.1  bouyer } __packed;
   1684  1.1  bouyer 
   1685  1.1  bouyer struct mpii_evt_ir_cfg_element {
   1686  1.1  bouyer 	u_int16_t		element_flags;
   1687  1.1  bouyer #define MPII_EVT_IR_CFG_ELEMENT_TYPE_MASK		(0xf)
   1688  1.1  bouyer #define MPII_EVT_IR_CFG_ELEMENT_TYPE_VOLUME		(0x0)
   1689  1.1  bouyer #define MPII_EVT_IR_CFG_ELEMENT_TYPE_VOLUME_DISK	(0x1)
   1690  1.1  bouyer #define MPII_EVT_IR_CFG_ELEMENT_TYPE_HOT_SPARE		(0x2)
   1691  1.1  bouyer 	u_int16_t		vol_dev_handle;
   1692  1.1  bouyer 
   1693  1.1  bouyer 	u_int8_t		reason_code;
   1694  1.1  bouyer #define MPII_EVT_IR_CFG_ELEMENT_RC_ADDED		(0x01)
   1695  1.1  bouyer #define MPII_EVT_IR_CFG_ELEMENT_RC_REMOVED		(0x02)
   1696  1.1  bouyer #define MPII_EVT_IR_CFG_ELEMENT_RC_NO_CHANGE		(0x03)
   1697  1.1  bouyer #define MPII_EVT_IR_CFG_ELEMENT_RC_HIDE			(0x04)
   1698  1.1  bouyer #define MPII_EVT_IR_CFG_ELEMENT_RC_UNHIDE		(0x05)
   1699  1.1  bouyer #define MPII_EVT_IR_CFG_ELEMENT_RC_VOLUME_CREATED	(0x06)
   1700  1.1  bouyer #define MPII_EVT_IR_CFG_ELEMENT_RC_VOLUME_DELETED	(0x07)
   1701  1.1  bouyer #define MPII_EVT_IR_CFG_ELEMENT_RC_PD_CREATED		(0x08)
   1702  1.1  bouyer #define MPII_EVT_IR_CFG_ELEMENT_RC_PD_DELETED		(0x09)
   1703  1.1  bouyer 	u_int8_t		phys_disk_num;
   1704  1.1  bouyer 	u_int16_t		phys_disk_dev_handle;
   1705  1.1  bouyer } __packed;
   1706  1.1  bouyer 
   1707  1.1  bouyer /* #define MPII_DEBUG */
   1708  1.1  bouyer #ifdef MPII_DEBUG
   1709  1.1  bouyer #define DPRINTF(x...)		do { if (mpii_debug) printf(x); } while(0)
   1710  1.1  bouyer #define DNPRINTF(n,x...)	do { if (mpii_debug & (n)) printf(x); } while(0)
   1711  1.1  bouyer #define	MPII_D_CMD		(0x0001)
   1712  1.1  bouyer #define	MPII_D_INTR		(0x0002)
   1713  1.1  bouyer #define	MPII_D_MISC		(0x0004)
   1714  1.1  bouyer #define	MPII_D_DMA		(0x0008)
   1715  1.1  bouyer #define	MPII_D_IOCTL		(0x0010)
   1716  1.1  bouyer #define	MPII_D_RW		(0x0020)
   1717  1.1  bouyer #define	MPII_D_MEM		(0x0040)
   1718  1.1  bouyer #define	MPII_D_CCB		(0x0080)
   1719  1.1  bouyer #define	MPII_D_PPR		(0x0100)
   1720  1.1  bouyer #define	MPII_D_RAID		(0x0200)
   1721  1.1  bouyer #define	MPII_D_EVT		(0x0400)
   1722  1.1  bouyer #define MPII_D_CFG		(0x0800)
   1723  1.1  bouyer #define MPII_D_MAP		(0x1000)
   1724  1.1  bouyer 
   1725  1.1  bouyer #if 0
   1726  1.1  bouyer u_int32_t  mpii_debug = 0
   1727  1.1  bouyer 		| MPII_D_CMD
   1728  1.1  bouyer 		| MPII_D_INTR
   1729  1.1  bouyer 		| MPII_D_MISC
   1730  1.1  bouyer 		| MPII_D_DMA
   1731  1.1  bouyer 		| MPII_D_IOCTL
   1732  1.1  bouyer 		| MPII_D_RW
   1733  1.1  bouyer 		| MPII_D_MEM
   1734  1.1  bouyer 		| MPII_D_CCB
   1735  1.1  bouyer 		| MPII_D_PPR
   1736  1.1  bouyer 		| MPII_D_RAID
   1737  1.1  bouyer 		| MPII_D_EVT
   1738  1.1  bouyer 		| MPII_D_CFG
   1739  1.1  bouyer 		| MPII_D_MAP
   1740  1.1  bouyer 	;
   1741  1.1  bouyer #endif
   1742  1.1  bouyer u_int32_t  mpii_debug = MPII_D_MISC;
   1743  1.1  bouyer #else
   1744  1.1  bouyer #define DPRINTF(x...)
   1745  1.1  bouyer #define DNPRINTF(n,x...)
   1746  1.1  bouyer #endif
   1747  1.1  bouyer 
   1748  1.1  bouyer #define MPII_REQUEST_SIZE	(512)
   1749  1.1  bouyer #define MPII_REPLY_SIZE		(128)
   1750  1.1  bouyer #define MPII_REPLY_COUNT	PAGE_SIZE / MPII_REPLY_SIZE
   1751  1.1  bouyer 
   1752  1.1  bouyer /*
   1753  1.1  bouyer  * this is the max number of sge's we can stuff in a request frame:
   1754  1.1  bouyer  * sizeof(scsi_io) + sizeof(sense) + sizeof(sge) * 32 = MPII_REQUEST_SIZE
   1755  1.1  bouyer  */
   1756  1.1  bouyer #define MPII_MAX_SGL			(32)
   1757  1.1  bouyer 
   1758  1.1  bouyer #define MPII_MAX_REQUEST_CREDIT		(128)
   1759  1.1  bouyer 
   1760  1.1  bouyer #define MPII_MAXFER MAXPHYS /* XXX bogus */
   1761  1.1  bouyer 
   1762  1.1  bouyer struct mpii_dmamem {
   1763  1.1  bouyer 	bus_dmamap_t		mdm_map;
   1764  1.1  bouyer 	bus_dma_segment_t	mdm_seg;
   1765  1.1  bouyer 	size_t			mdm_size;
   1766  1.1  bouyer 	void 			*mdm_kva;
   1767  1.1  bouyer };
   1768  1.1  bouyer #define MPII_DMA_MAP(_mdm)	(_mdm)->mdm_map
   1769  1.1  bouyer #define MPII_DMA_DVA(_mdm)	(_mdm)->mdm_map->dm_segs[0].ds_addr
   1770  1.1  bouyer #define MPII_DMA_KVA(_mdm)	(void *)(_mdm)->mdm_kva
   1771  1.1  bouyer 
   1772  1.1  bouyer struct mpii_ccb_bundle {
   1773  1.1  bouyer 	struct mpii_msg_scsi_io	mcb_io; /* sgl must follow */
   1774  1.1  bouyer 	struct mpii_sge		mcb_sgl[MPII_MAX_SGL];
   1775  1.1  bouyer 	struct scsi_sense_data	mcb_sense;
   1776  1.1  bouyer } __packed;
   1777  1.1  bouyer 
   1778  1.1  bouyer struct mpii_softc;
   1779  1.1  bouyer 
   1780  1.1  bouyer struct mpii_rcb {
   1781  1.1  bouyer 	union {
   1782  1.1  bouyer 		struct work	rcb_wk; /* has to be first in struct */
   1783  1.1  bouyer 		SIMPLEQ_ENTRY(mpii_rcb)	rcb_link;
   1784  1.1  bouyer 	} u;
   1785  1.1  bouyer 	void			*rcb_reply;
   1786  1.1  bouyer 	u_int32_t		rcb_reply_dva;
   1787  1.1  bouyer };
   1788  1.1  bouyer 
   1789  1.1  bouyer SIMPLEQ_HEAD(mpii_rcb_list, mpii_rcb);
   1790  1.1  bouyer 
   1791  1.1  bouyer struct mpii_device {
   1792  1.1  bouyer 	int			flags;
   1793  1.1  bouyer #define MPII_DF_ATTACH		(0x0001)
   1794  1.1  bouyer #define MPII_DF_DETACH		(0x0002)
   1795  1.1  bouyer #define MPII_DF_HIDDEN		(0x0004)
   1796  1.1  bouyer #define MPII_DF_UNUSED		(0x0008)
   1797  1.1  bouyer #define MPII_DF_VOLUME		(0x0010)
   1798  1.1  bouyer #define MPII_DF_VOLUME_DISK	(0x0020)
   1799  1.1  bouyer #define MPII_DF_HOT_SPARE	(0x0040)
   1800  1.1  bouyer 	short			slot;
   1801  1.1  bouyer 	short			percent;
   1802  1.1  bouyer 	u_int16_t		dev_handle;
   1803  1.1  bouyer 	u_int16_t		enclosure;
   1804  1.1  bouyer 	u_int16_t		expander;
   1805  1.1  bouyer 	u_int8_t		phy_num;
   1806  1.1  bouyer 	u_int8_t		physical_port;
   1807  1.1  bouyer };
   1808  1.1  bouyer 
   1809  1.1  bouyer struct mpii_ccb {
   1810  1.1  bouyer 	union {
   1811  1.1  bouyer 		struct work	ccb_wk; /* has to be first in struct */
   1812  1.1  bouyer 		SIMPLEQ_ENTRY(mpii_ccb)	ccb_link;
   1813  1.1  bouyer 	} u;
   1814  1.1  bouyer 	struct mpii_softc	*ccb_sc;
   1815  1.1  bouyer 	int			ccb_smid;
   1816  1.1  bouyer 
   1817  1.1  bouyer 	void *			ccb_cookie;
   1818  1.1  bouyer 	bus_dmamap_t		ccb_dmamap;
   1819  1.1  bouyer 
   1820  1.1  bouyer 	bus_addr_t		ccb_offset;
   1821  1.1  bouyer 	void			*ccb_cmd;
   1822  1.1  bouyer 	bus_addr_t		ccb_cmd_dva;
   1823  1.1  bouyer 	u_int16_t		ccb_dev_handle;
   1824  1.1  bouyer 
   1825  1.1  bouyer 	volatile enum {
   1826  1.1  bouyer 		MPII_CCB_FREE,
   1827  1.1  bouyer 		MPII_CCB_READY,
   1828  1.1  bouyer 		MPII_CCB_QUEUED,
   1829  1.1  bouyer 		MPII_CCB_TIMEOUT
   1830  1.1  bouyer 	}			ccb_state;
   1831  1.1  bouyer 
   1832  1.1  bouyer 	void			(*ccb_done)(struct mpii_ccb *);
   1833  1.1  bouyer 	struct mpii_rcb		*ccb_rcb;
   1834  1.1  bouyer 
   1835  1.1  bouyer };
   1836  1.1  bouyer 
   1837  1.1  bouyer struct mpii_ccb_wait {
   1838  1.1  bouyer 	kmutex_t	mpii_ccbw_mtx;
   1839  1.1  bouyer 	kcondvar_t	mpii_ccbw_cv;
   1840  1.1  bouyer };
   1841  1.1  bouyer 
   1842  1.1  bouyer SIMPLEQ_HEAD(mpii_ccb_list, mpii_ccb);
   1843  1.1  bouyer 
   1844  1.1  bouyer struct mpii_softc {
   1845  1.1  bouyer 	device_t		sc_dev;
   1846  1.1  bouyer 
   1847  1.1  bouyer 	pci_chipset_tag_t	sc_pc;
   1848  1.1  bouyer 	pcitag_t		sc_tag;
   1849  1.1  bouyer 
   1850  1.1  bouyer 	void			*sc_ih;
   1851  1.1  bouyer 
   1852  1.1  bouyer 	int			sc_flags;
   1853  1.1  bouyer #define MPII_F_RAID		(1<<1)
   1854  1.1  bouyer 
   1855  1.1  bouyer 	struct scsipi_adapter	sc_adapt;
   1856  1.1  bouyer 	struct scsipi_channel	sc_chan;
   1857  1.1  bouyer 	device_t		sc_child; /* our scsibus */
   1858  1.1  bouyer 
   1859  1.1  bouyer 	struct mpii_device	**sc_devs;
   1860  1.1  bouyer 
   1861  1.1  bouyer 	bus_space_tag_t		sc_iot;
   1862  1.1  bouyer 	bus_space_handle_t	sc_ioh;
   1863  1.1  bouyer 	bus_size_t		sc_ios;
   1864  1.1  bouyer 	bus_dma_tag_t		sc_dmat;
   1865  1.1  bouyer 
   1866  1.1  bouyer 	kmutex_t		sc_req_mtx;
   1867  1.1  bouyer 	kmutex_t		sc_rep_mtx;
   1868  1.1  bouyer 
   1869  1.1  bouyer 	u_int8_t		sc_porttype;
   1870  1.1  bouyer 	int			sc_request_depth;
   1871  1.1  bouyer 	int			sc_num_reply_frames;
   1872  1.1  bouyer 	int			sc_reply_free_qdepth;
   1873  1.1  bouyer 	int			sc_reply_post_qdepth;
   1874  1.1  bouyer 	int			sc_maxchdepth;
   1875  1.1  bouyer 	int			sc_first_sgl_len;
   1876  1.1  bouyer 	int			sc_chain_len;
   1877  1.1  bouyer 	int			sc_max_sgl_len;
   1878  1.1  bouyer 
   1879  1.1  bouyer 	u_int8_t		sc_ioc_event_replay;
   1880  1.1  bouyer 	u_int16_t		sc_max_enclosures;
   1881  1.1  bouyer 	u_int16_t		sc_max_expanders;
   1882  1.1  bouyer 	u_int8_t		sc_max_volumes;
   1883  1.1  bouyer 	u_int16_t		sc_max_devices;
   1884  1.1  bouyer 	u_int16_t		sc_max_dpm_entries;
   1885  1.1  bouyer 	u_int16_t		sc_vd_count;
   1886  1.1  bouyer 	u_int16_t		sc_vd_id_low;
   1887  1.1  bouyer 	u_int16_t		sc_pd_id_start;
   1888  1.1  bouyer 	u_int8_t		sc_num_channels;
   1889  1.1  bouyer 	int			sc_ioc_number;
   1890  1.1  bouyer 	u_int8_t		sc_vf_id;
   1891  1.1  bouyer 	u_int8_t		sc_num_ports;
   1892  1.1  bouyer 
   1893  1.1  bouyer 	struct mpii_ccb		*sc_ccbs;
   1894  1.1  bouyer 	struct mpii_ccb_list	sc_ccb_free;
   1895  1.1  bouyer 	kmutex_t		sc_ccb_free_mtx;
   1896  1.1  bouyer 	kcondvar_t		sc_ccb_free_cv;
   1897  1.1  bouyer 
   1898  1.1  bouyer 	kmutex_t		sc_ccb_mtx;
   1899  1.1  bouyer 				/*
   1900  1.1  bouyer 				 * this protects the ccb state and list entry
   1901  1.1  bouyer 				 * between mpii_scsi_cmd and scsidone.
   1902  1.1  bouyer 				 */
   1903  1.1  bouyer 
   1904  1.1  bouyer 	struct workqueue	*sc_ssb_tmowk;
   1905  1.1  bouyer 
   1906  1.1  bouyer 	struct mpii_dmamem	*sc_requests;
   1907  1.1  bouyer 
   1908  1.1  bouyer 	struct mpii_dmamem	*sc_replies;
   1909  1.1  bouyer 	struct mpii_rcb		*sc_rcbs;
   1910  1.1  bouyer 
   1911  1.1  bouyer 	struct mpii_dmamem	*sc_reply_postq;
   1912  1.1  bouyer 	struct mpii_reply_descr	*sc_reply_postq_kva;
   1913  1.1  bouyer 	int			sc_reply_post_host_index;
   1914  1.1  bouyer 
   1915  1.1  bouyer 	struct mpii_dmamem	*sc_reply_freeq;
   1916  1.1  bouyer 	int			sc_reply_free_host_index;
   1917  1.1  bouyer 
   1918  1.1  bouyer 	struct workqueue	*sc_ssb_evt_ackwk;
   1919  1.1  bouyer 
   1920  1.1  bouyer 	struct sysmon_envsys	*sc_sme;
   1921  1.1  bouyer 	envsys_data_t		*sc_sensors;
   1922  1.1  bouyer };
   1923  1.1  bouyer 
   1924  1.1  bouyer static int	mpii_match(device_t, cfdata_t, void *);
   1925  1.1  bouyer static void	mpii_attach(device_t, device_t, void *);
   1926  1.1  bouyer static int	mpii_detach(device_t, int);
   1927  1.1  bouyer static void	mpii_childdetached(device_t, device_t);
   1928  1.1  bouyer static int	mpii_rescan(device_t, const char *, const int *);
   1929  1.1  bouyer 
   1930  1.1  bouyer static int	mpii_intr(void *);
   1931  1.1  bouyer 
   1932  1.1  bouyer CFATTACH_DECL3_NEW(mpii, sizeof(struct mpii_softc),
   1933  1.1  bouyer     mpii_match, mpii_attach, mpii_detach, NULL, mpii_rescan,
   1934  1.1  bouyer     mpii_childdetached, DVF_DETACH_SHUTDOWN);
   1935  1.1  bouyer 
   1936  1.1  bouyer #define PREAD(s, r)	pci_conf_read((s)->sc_pc, (s)->sc_tag, (r))
   1937  1.1  bouyer #define PWRITE(s, r, v)	pci_conf_write((s)->sc_pc, (s)->sc_tag, (r), (v))
   1938  1.1  bouyer 
   1939  1.1  bouyer static void	mpii_scsipi_request(struct scsipi_channel *,
   1940  1.1  bouyer 		    scsipi_adapter_req_t, void *);
   1941  1.1  bouyer static void	mpii_scsi_cmd_done(struct mpii_ccb *);
   1942  1.1  bouyer static void	mpii_minphys(struct buf *bp);
   1943  1.1  bouyer 
   1944  1.1  bouyer static struct mpii_dmamem *mpii_dmamem_alloc(struct mpii_softc *, size_t);
   1945  1.1  bouyer static void	mpii_dmamem_free(struct mpii_softc *, struct mpii_dmamem *);
   1946  1.1  bouyer static int	mpii_alloc_ccbs(struct mpii_softc *);
   1947  1.1  bouyer static struct mpii_ccb *mpii_get_ccb(struct mpii_softc *, int);
   1948  1.1  bouyer #define MPII_NOSLEEP 0x0001
   1949  1.1  bouyer static void	mpii_put_ccb(struct mpii_softc *, struct mpii_ccb *);
   1950  1.1  bouyer static int	mpii_alloc_replies(struct mpii_softc *);
   1951  1.1  bouyer static int	mpii_alloc_queues(struct mpii_softc *);
   1952  1.1  bouyer static void	mpii_push_reply(struct mpii_softc *, struct mpii_rcb *);
   1953  1.1  bouyer static void	mpii_push_replies(struct mpii_softc *);
   1954  1.1  bouyer 
   1955  1.1  bouyer static void	mpii_scsi_cmd_tmo(void *);
   1956  1.1  bouyer static void	mpii_scsi_cmd_tmo_handler(struct work *, void *);
   1957  1.1  bouyer static void	mpii_scsi_cmd_tmo_done(struct mpii_ccb *);
   1958  1.1  bouyer 
   1959  1.1  bouyer static int	mpii_alloc_dev(struct mpii_softc *);
   1960  1.1  bouyer static int	mpii_insert_dev(struct mpii_softc *, struct mpii_device *);
   1961  1.1  bouyer static int	mpii_remove_dev(struct mpii_softc *, struct mpii_device *);
   1962  1.1  bouyer static struct mpii_device *mpii_find_dev(struct mpii_softc *, u_int16_t);
   1963  1.1  bouyer 
   1964  1.1  bouyer static void	mpii_start(struct mpii_softc *, struct mpii_ccb *);
   1965  1.1  bouyer static int	mpii_poll(struct mpii_softc *, struct mpii_ccb *);
   1966  1.1  bouyer static void	mpii_poll_done(struct mpii_ccb *);
   1967  1.1  bouyer static struct mpii_rcb *mpii_reply(struct mpii_softc *,
   1968  1.1  bouyer 			struct mpii_reply_descr *);
   1969  1.1  bouyer 
   1970  1.1  bouyer static void	mpii_wait(struct mpii_softc *, struct mpii_ccb *);
   1971  1.1  bouyer static void	mpii_wait_done(struct mpii_ccb *);
   1972  1.1  bouyer 
   1973  1.1  bouyer static void	mpii_init_queues(struct mpii_softc *);
   1974  1.1  bouyer 
   1975  1.1  bouyer static int	mpii_load_xs(struct mpii_ccb *);
   1976  1.1  bouyer 
   1977  1.1  bouyer static u_int32_t mpii_read(struct mpii_softc *, bus_size_t);
   1978  1.1  bouyer static void	mpii_write(struct mpii_softc *, bus_size_t, u_int32_t);
   1979  1.1  bouyer static int	mpii_wait_eq(struct mpii_softc *, bus_size_t, u_int32_t,
   1980  1.1  bouyer 		    u_int32_t);
   1981  1.1  bouyer static int	mpii_wait_ne(struct mpii_softc *, bus_size_t, u_int32_t,
   1982  1.1  bouyer 		    u_int32_t);
   1983  1.1  bouyer 
   1984  1.1  bouyer static int	mpii_init(struct mpii_softc *);
   1985  1.1  bouyer static int	mpii_reset_soft(struct mpii_softc *);
   1986  1.1  bouyer static int	mpii_reset_hard(struct mpii_softc *);
   1987  1.1  bouyer 
   1988  1.1  bouyer static int	mpii_handshake_send(struct mpii_softc *, void *, size_t);
   1989  1.1  bouyer static int	mpii_handshake_recv_dword(struct mpii_softc *,
   1990  1.1  bouyer 		    u_int32_t *);
   1991  1.1  bouyer static int	mpii_handshake_recv(struct mpii_softc *, void *, size_t);
   1992  1.1  bouyer 
   1993  1.1  bouyer static void	mpii_empty_done(struct mpii_ccb *);
   1994  1.1  bouyer 
   1995  1.1  bouyer static int	mpii_iocinit(struct mpii_softc *);
   1996  1.1  bouyer static int	mpii_iocfacts(struct mpii_softc *);
   1997  1.1  bouyer static int	mpii_portfacts(struct mpii_softc *);
   1998  1.1  bouyer static int	mpii_portenable(struct mpii_softc *);
   1999  1.1  bouyer static int	mpii_cfg_coalescing(struct mpii_softc *);
   2000  1.1  bouyer 
   2001  1.1  bouyer static int	mpii_eventnotify(struct mpii_softc *);
   2002  1.1  bouyer static void	mpii_eventnotify_done(struct mpii_ccb *);
   2003  1.1  bouyer static void	mpii_eventack(struct work *, void *);
   2004  1.1  bouyer static void	mpii_eventack_done(struct mpii_ccb *);
   2005  1.1  bouyer static void	mpii_event_process(struct mpii_softc *, struct mpii_rcb *);
   2006  1.1  bouyer static void	mpii_event_sas(struct mpii_softc *,
   2007  1.1  bouyer 		    struct mpii_msg_event_reply *);
   2008  1.1  bouyer static void	mpii_event_raid(struct mpii_softc *,
   2009  1.1  bouyer 		    struct mpii_msg_event_reply *);
   2010  1.1  bouyer static void	mpii_event_defer(void *, void *);
   2011  1.1  bouyer 
   2012  1.1  bouyer static void	mpii_sas_remove_device(struct mpii_softc *, u_int16_t);
   2013  1.1  bouyer 
   2014  1.1  bouyer static int	mpii_req_cfg_header(struct mpii_softc *, u_int8_t,
   2015  1.1  bouyer 		    u_int8_t, u_int32_t, int, void *);
   2016  1.1  bouyer static int	mpii_req_cfg_page(struct mpii_softc *, u_int32_t, int,
   2017  1.1  bouyer 		    void *, int, void *, size_t);
   2018  1.1  bouyer 
   2019  1.1  bouyer static int	mpii_get_ioc_pg8(struct mpii_softc *);
   2020  1.1  bouyer 
   2021  1.1  bouyer #if 0
   2022  1.1  bouyer static int	mpii_ioctl_cache(struct scsi_link *, u_long, struct dk_cache *);
   2023  1.1  bouyer #endif
   2024  1.1  bouyer static int	mpii_cache_enable(struct mpii_softc *, struct mpii_device *);
   2025  1.1  bouyer 
   2026  1.1  bouyer #if NBIO > 0
   2027  1.1  bouyer static int	mpii_ioctl(device_t, u_long, void *);
   2028  1.1  bouyer static int	mpii_ioctl_inq(struct mpii_softc *, struct bioc_inq *);
   2029  1.1  bouyer static int	mpii_ioctl_vol(struct mpii_softc *, struct bioc_vol *);
   2030  1.1  bouyer static int	mpii_ioctl_disk(struct mpii_softc *, struct bioc_disk *);
   2031  1.1  bouyer static int	mpii_bio_hs(struct mpii_softc *, struct bioc_disk *, int,
   2032  1.1  bouyer 		    int, int *);
   2033  1.1  bouyer static int	mpii_bio_disk(struct mpii_softc *, struct bioc_disk *,
   2034  1.1  bouyer 		    u_int8_t);
   2035  1.1  bouyer static struct mpii_device *mpii_find_vol(struct mpii_softc *, int);
   2036  1.1  bouyer static int	mpii_bio_volstate(struct mpii_softc *, struct bioc_vol *);
   2037  1.1  bouyer static int	mpii_create_sensors(struct mpii_softc *);
   2038  1.1  bouyer static int	mpii_destroy_sensors(struct mpii_softc *);
   2039  1.1  bouyer static void	mpii_refresh_sensors(struct sysmon_envsys *, envsys_data_t *);
   2040  1.1  bouyer #endif /* NBIO > 0 */
   2041  1.1  bouyer 
   2042  1.1  bouyer #define DEVNAME(_s)		(device_xname((_s)->sc_dev))
   2043  1.1  bouyer 
   2044  1.1  bouyer #define dwordsof(s)		(sizeof(s) / sizeof(u_int32_t))
   2045  1.1  bouyer #define dwordn(p, n)		(((u_int32_t *)(p))[(n)])
   2046  1.1  bouyer 
   2047  1.1  bouyer #define mpii_read_db(s)		mpii_read((s), MPII_DOORBELL)
   2048  1.1  bouyer #define mpii_write_db(s, v)	mpii_write((s), MPII_DOORBELL, (v))
   2049  1.1  bouyer #define mpii_read_intr(s)	mpii_read((s), MPII_INTR_STATUS)
   2050  1.1  bouyer #define mpii_write_intr(s, v)	mpii_write((s), MPII_INTR_STATUS, (v))
   2051  1.1  bouyer #define mpii_reply_waiting(s)	((mpii_read_intr((s)) & MPII_INTR_STATUS_REPLY)\
   2052  1.1  bouyer 				    == MPII_INTR_STATUS_REPLY)
   2053  1.1  bouyer 
   2054  1.1  bouyer #define mpii_read_reply_free(s)		mpii_read((s), \
   2055  1.1  bouyer 						MPII_REPLY_FREE_HOST_INDEX)
   2056  1.1  bouyer #define mpii_write_reply_free(s, v)	mpii_write((s), \
   2057  1.1  bouyer 						MPII_REPLY_FREE_HOST_INDEX, (v))
   2058  1.1  bouyer #define mpii_read_reply_post(s)		mpii_read((s), \
   2059  1.1  bouyer 						MPII_REPLY_POST_HOST_INDEX)
   2060  1.1  bouyer #define mpii_write_reply_post(s, v)	mpii_write((s), \
   2061  1.1  bouyer 						MPII_REPLY_POST_HOST_INDEX, (v))
   2062  1.1  bouyer 
   2063  1.1  bouyer #define mpii_wait_db_int(s)	mpii_wait_ne((s), MPII_INTR_STATUS, \
   2064  1.1  bouyer 				    MPII_INTR_STATUS_IOC2SYSDB, 0)
   2065  1.1  bouyer #define mpii_wait_db_ack(s)	mpii_wait_eq((s), MPII_INTR_STATUS, \
   2066  1.1  bouyer 				    MPII_INTR_STATUS_SYS2IOCDB, 0)
   2067  1.1  bouyer 
   2068  1.1  bouyer #define MPII_PG_EXTENDED	(1<<0)
   2069  1.1  bouyer #define MPII_PG_POLL		(1<<1)
   2070  1.1  bouyer #define MPII_PG_FMT		"\020" "\002POLL" "\001EXTENDED"
   2071  1.1  bouyer 
   2072  1.1  bouyer #define mpii_cfg_header(_s, _t, _n, _a, _h) \
   2073  1.1  bouyer 	mpii_req_cfg_header((_s), (_t), (_n), (_a), \
   2074  1.1  bouyer 	    MPII_PG_POLL, (_h))
   2075  1.1  bouyer #define mpii_ecfg_header(_s, _t, _n, _a, _h) \
   2076  1.1  bouyer 	mpii_req_cfg_header((_s), (_t), (_n), (_a), \
   2077  1.1  bouyer 	    MPII_PG_POLL|MPII_PG_EXTENDED, (_h))
   2078  1.1  bouyer 
   2079  1.1  bouyer #define mpii_cfg_page(_s, _a, _h, _r, _p, _l) \
   2080  1.1  bouyer 	mpii_req_cfg_page((_s), (_a), MPII_PG_POLL, \
   2081  1.1  bouyer 	    (_h), (_r), (_p), (_l))
   2082  1.1  bouyer #define mpii_ecfg_page(_s, _a, _h, _r, _p, _l) \
   2083  1.1  bouyer 	mpii_req_cfg_page((_s), (_a), MPII_PG_POLL|MPII_PG_EXTENDED, \
   2084  1.1  bouyer 	    (_h), (_r), (_p), (_l))
   2085  1.1  bouyer 
   2086  1.1  bouyer 
   2087  1.1  bouyer static const struct mpii_pci_product {
   2088  1.1  bouyer 	pci_vendor_id_t         mpii_vendor;
   2089  1.1  bouyer 	pci_product_id_t        mpii_product;
   2090  1.1  bouyer } mpii_devices[] = {
   2091  1.1  bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2004 },
   2092  1.1  bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2008 },
   2093  1.1  bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2108_3 },
   2094  1.1  bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2108_4 },
   2095  1.1  bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2108_5 },
   2096  1.1  bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2116_1 },
   2097  1.1  bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2116_2 },
   2098  1.1  bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2208_1 },
   2099  1.1  bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2208_2 },
   2100  1.1  bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2208_3 },
   2101  1.1  bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2208_4 },
   2102  1.1  bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2208_5 },
   2103  1.1  bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2208_6 },
   2104  1.1  bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2308_1 },
   2105  1.1  bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2308_2 },
   2106  1.1  bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2308_3 },
   2107  1.1  bouyer 	{ 0,	0 }
   2108  1.1  bouyer };
   2109  1.1  bouyer 
   2110  1.1  bouyer static int
   2111  1.1  bouyer mpii_match(device_t parent, cfdata_t match, void *aux)
   2112  1.1  bouyer {
   2113  1.1  bouyer 	struct pci_attach_args *pa = aux;
   2114  1.1  bouyer 	const struct mpii_pci_product *mpii;
   2115  1.1  bouyer 
   2116  1.1  bouyer 	for (mpii = mpii_devices; mpii->mpii_vendor != 0; mpii++) {
   2117  1.1  bouyer 		if (PCI_VENDOR(pa->pa_id) == mpii->mpii_vendor &&
   2118  1.1  bouyer 		    PCI_PRODUCT(pa->pa_id) == mpii->mpii_product)
   2119  1.1  bouyer 			return (1);
   2120  1.1  bouyer 	}
   2121  1.1  bouyer 	return (0);
   2122  1.1  bouyer }
   2123  1.1  bouyer 
   2124  1.1  bouyer static void
   2125  1.1  bouyer mpii_attach(device_t parent, device_t self, void *aux)
   2126  1.1  bouyer {
   2127  1.1  bouyer 	struct mpii_softc		*sc = device_private(self);
   2128  1.1  bouyer 	struct pci_attach_args		*pa = aux;
   2129  1.1  bouyer 	pcireg_t			memtype;
   2130  1.1  bouyer 	int				r;
   2131  1.1  bouyer 	pci_intr_handle_t		ih;
   2132  1.1  bouyer 	const char			*intrstr;
   2133  1.1  bouyer 	struct mpii_ccb			*ccb;
   2134  1.1  bouyer 	struct scsipi_adapter *adapt = &sc->sc_adapt;
   2135  1.1  bouyer 	struct scsipi_channel *chan = &sc->sc_chan;
   2136  1.1  bouyer 	char wkname[15];
   2137  1.1  bouyer 
   2138  1.1  bouyer 	pci_aprint_devinfo(pa, NULL);
   2139  1.1  bouyer 
   2140  1.1  bouyer 	sc->sc_pc = pa->pa_pc;
   2141  1.1  bouyer 	sc->sc_tag = pa->pa_tag;
   2142  1.1  bouyer 	sc->sc_dmat = pa->pa_dmat;
   2143  1.1  bouyer 	sc->sc_dev = self;
   2144  1.1  bouyer 
   2145  1.1  bouyer 	mutex_init(&sc->sc_req_mtx, MUTEX_DEFAULT, IPL_BIO);
   2146  1.1  bouyer 	mutex_init(&sc->sc_rep_mtx, MUTEX_DEFAULT, IPL_BIO);
   2147  1.1  bouyer 	mutex_init(&sc->sc_ccb_free_mtx, MUTEX_DEFAULT, IPL_BIO);
   2148  1.1  bouyer 	cv_init(&sc->sc_ccb_free_cv, "mpii_ccbs");
   2149  1.1  bouyer 	mutex_init(&sc->sc_ccb_mtx, MUTEX_DEFAULT, IPL_BIO);
   2150  1.1  bouyer 
   2151  1.1  bouyer 	snprintf(wkname, sizeof(wkname), "%s_tmo", DEVNAME(sc));
   2152  1.1  bouyer 	if (workqueue_create(&sc->sc_ssb_tmowk, wkname,
   2153  1.1  bouyer 	    mpii_scsi_cmd_tmo_handler, sc, PRI_NONE, IPL_BIO, WQ_MPSAFE) != 0) {
   2154  1.1  bouyer 		aprint_error_dev(self, "can't create %s workqueue\n", wkname);
   2155  1.1  bouyer 		return;
   2156  1.1  bouyer 	}
   2157  1.1  bouyer 
   2158  1.1  bouyer 	snprintf(wkname, sizeof(wkname), "%s_evt", DEVNAME(sc));
   2159  1.1  bouyer 	if (workqueue_create(&sc->sc_ssb_evt_ackwk, wkname,
   2160  1.1  bouyer 	    mpii_eventack, sc, PRI_NONE, IPL_BIO, WQ_MPSAFE) != 0) {
   2161  1.1  bouyer 		aprint_error_dev(self, "can't create %s workqueue\n", wkname);
   2162  1.1  bouyer 		return;
   2163  1.1  bouyer 	}
   2164  1.1  bouyer 
   2165  1.1  bouyer 	/* find the appropriate memory base */
   2166  1.1  bouyer 	for (r = PCI_MAPREG_START; r < PCI_MAPREG_END; r += sizeof(memtype)) {
   2167  1.1  bouyer 		memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, r);
   2168  1.1  bouyer 		if ((memtype & PCI_MAPREG_TYPE_MASK) == PCI_MAPREG_TYPE_MEM)
   2169  1.1  bouyer 			break;
   2170  1.1  bouyer 	}
   2171  1.1  bouyer 	if (r >= PCI_MAPREG_END) {
   2172  1.1  bouyer 		aprint_error_dev(self,
   2173  1.1  bouyer 		    "unable to locate system interface registers\n");
   2174  1.1  bouyer 		return;
   2175  1.1  bouyer 	}
   2176  1.1  bouyer 
   2177  1.1  bouyer 	if (pci_mapreg_map(pa, r, memtype, 0, &sc->sc_iot, &sc->sc_ioh,
   2178  1.1  bouyer 	    NULL, &sc->sc_ios) != 0) {
   2179  1.1  bouyer 		aprint_error_dev(self,
   2180  1.1  bouyer 		    "unable to map system interface registers\n");
   2181  1.1  bouyer 		return;
   2182  1.1  bouyer 	}
   2183  1.1  bouyer 
   2184  1.1  bouyer 	/* disable the expansion rom */
   2185  1.1  bouyer 	PWRITE(sc, PCI_MAPREG_ROM,
   2186  1.1  bouyer 	    PREAD(sc, PCI_MAPREG_ROM) & ~PCI_MAPREG_ROM_ENABLE);
   2187  1.1  bouyer 
   2188  1.1  bouyer 	/* disable interrupts */
   2189  1.1  bouyer 	mpii_write(sc, MPII_INTR_MASK,
   2190  1.1  bouyer 	    MPII_INTR_MASK_RESET | MPII_INTR_MASK_REPLY |
   2191  1.1  bouyer 	    MPII_INTR_MASK_DOORBELL);
   2192  1.1  bouyer 
   2193  1.1  bouyer 	/* hook up the interrupt */
   2194  1.1  bouyer 	if (pci_intr_map(pa, &ih) != 0) {
   2195  1.1  bouyer 		aprint_error_dev(self, "unable to map interrupt\n");
   2196  1.1  bouyer 		goto unmap;
   2197  1.1  bouyer 	}
   2198  1.1  bouyer 	intrstr = pci_intr_string(pa->pa_pc, ih);
   2199  1.1  bouyer 
   2200  1.1  bouyer 	if (mpii_init(sc) != 0) {
   2201  1.1  bouyer 		aprint_error_dev(self, "unable to initialize ioc\n");
   2202  1.1  bouyer 		goto unmap;
   2203  1.1  bouyer 	}
   2204  1.1  bouyer 
   2205  1.1  bouyer 	if (mpii_iocfacts(sc) != 0) {
   2206  1.1  bouyer 		aprint_error_dev(self, "unable to get iocfacts\n");
   2207  1.1  bouyer 		goto unmap;
   2208  1.1  bouyer 	}
   2209  1.1  bouyer 
   2210  1.1  bouyer 	if (mpii_alloc_ccbs(sc) != 0) {
   2211  1.1  bouyer 		/* error already printed */
   2212  1.1  bouyer 		goto unmap;
   2213  1.1  bouyer 	}
   2214  1.1  bouyer 
   2215  1.1  bouyer 	if (mpii_alloc_replies(sc) != 0) {
   2216  1.1  bouyer 		aprint_error_dev(self, "unable to allocated reply space\n");
   2217  1.1  bouyer 		goto free_ccbs;
   2218  1.1  bouyer 	}
   2219  1.1  bouyer 
   2220  1.1  bouyer 	if (mpii_alloc_queues(sc) != 0) {
   2221  1.1  bouyer 		aprint_error_dev(self, "unable to allocate reply queues\n");
   2222  1.1  bouyer 		goto free_replies;
   2223  1.1  bouyer 	}
   2224  1.1  bouyer 
   2225  1.1  bouyer 	if (mpii_iocinit(sc) != 0) {
   2226  1.1  bouyer 		aprint_error_dev(self, "unable to send iocinit\n");
   2227  1.1  bouyer 		goto free_queues;
   2228  1.1  bouyer 	}
   2229  1.1  bouyer 
   2230  1.1  bouyer 	if (mpii_wait_eq(sc, MPII_DOORBELL, MPII_DOORBELL_STATE,
   2231  1.1  bouyer 	    MPII_DOORBELL_STATE_OPER) != 0) {
   2232  1.1  bouyer 		aprint_error_dev(self, "state: 0x%08x\n",
   2233  1.1  bouyer 			mpii_read_db(sc) & MPII_DOORBELL_STATE);
   2234  1.1  bouyer 		aprint_error_dev(self, "operational state timeout\n");
   2235  1.1  bouyer 		goto free_queues;
   2236  1.1  bouyer 	}
   2237  1.1  bouyer 
   2238  1.1  bouyer 	mpii_push_replies(sc);
   2239  1.1  bouyer 	mpii_init_queues(sc);
   2240  1.1  bouyer 
   2241  1.1  bouyer 	if (mpii_portfacts(sc) != 0) {
   2242  1.1  bouyer 		aprint_error_dev(self, "unable to get portfacts\n");
   2243  1.1  bouyer 		goto free_queues;
   2244  1.1  bouyer 	}
   2245  1.1  bouyer 
   2246  1.1  bouyer 	if (mpii_get_ioc_pg8(sc) != 0) {
   2247  1.1  bouyer 		aprint_error_dev(self, "unable to get ioc page 8\n");
   2248  1.1  bouyer 		goto free_queues;
   2249  1.1  bouyer 	}
   2250  1.1  bouyer 
   2251  1.1  bouyer 	if (mpii_cfg_coalescing(sc) != 0) {
   2252  1.1  bouyer 		aprint_error_dev(self, "unable to configure coalescing\n");
   2253  1.1  bouyer 		goto free_queues;
   2254  1.1  bouyer 	}
   2255  1.1  bouyer 
   2256  1.1  bouyer 	/* XXX bail on unsupported porttype? */
   2257  1.1  bouyer 	if ((sc->sc_porttype == MPII_PORTFACTS_PORTTYPE_SAS_PHYSICAL) ||
   2258  1.1  bouyer 	    (sc->sc_porttype == MPII_PORTFACTS_PORTTYPE_SAS_VIRTUAL)) {
   2259  1.1  bouyer 		if (mpii_eventnotify(sc) != 0) {
   2260  1.1  bouyer 			aprint_error_dev(self, "unable to enable events\n");
   2261  1.1  bouyer 			goto free_queues;
   2262  1.1  bouyer 		}
   2263  1.1  bouyer 	}
   2264  1.1  bouyer 
   2265  1.1  bouyer 	if (mpii_alloc_dev(sc) != 0) {
   2266  1.1  bouyer 		aprint_error_dev(self,
   2267  1.1  bouyer 		    "unable to allocate memory for mpii_device\n");
   2268  1.1  bouyer 		goto free_queues;
   2269  1.1  bouyer 	}
   2270  1.1  bouyer 
   2271  1.1  bouyer 	if (mpii_portenable(sc) != 0) {
   2272  1.1  bouyer 		aprint_error_dev(self, "unable to enable port\n");
   2273  1.1  bouyer 		goto free_dev;
   2274  1.1  bouyer 	}
   2275  1.1  bouyer 
   2276  1.1  bouyer 	sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_BIO,
   2277  1.1  bouyer 	    mpii_intr, sc);
   2278  1.1  bouyer 	if (sc->sc_ih == NULL) {
   2279  1.1  bouyer 		aprint_error_dev(self, "can't establish interrupt");
   2280  1.1  bouyer 		if (intrstr)
   2281  1.1  bouyer 			aprint_error(" at %s", intrstr);
   2282  1.1  bouyer 		aprint_error("\n");
   2283  1.1  bouyer 		goto free_dev;
   2284  1.1  bouyer 	}
   2285  1.1  bouyer 
   2286  1.1  bouyer 	memset(adapt, 0, sizeof(*adapt));
   2287  1.1  bouyer 	adapt->adapt_dev = sc->sc_dev;
   2288  1.1  bouyer 	adapt->adapt_nchannels = 1;
   2289  1.1  bouyer 	adapt->adapt_openings = sc->sc_request_depth - 1;
   2290  1.1  bouyer 	adapt->adapt_max_periph = adapt->adapt_openings;
   2291  1.1  bouyer 	adapt->adapt_request = mpii_scsipi_request;
   2292  1.1  bouyer 	adapt->adapt_minphys = mpii_minphys;
   2293  1.1  bouyer 
   2294  1.1  bouyer 	memset(chan, 0, sizeof(*chan));
   2295  1.1  bouyer 	chan->chan_adapter = adapt;
   2296  1.1  bouyer 	chan->chan_bustype = &scsi_sas_bustype;
   2297  1.1  bouyer 	chan->chan_channel = 0;
   2298  1.1  bouyer 	chan->chan_flags = 0;
   2299  1.2  kardel 	chan->chan_nluns = 8;
   2300  1.1  bouyer 	chan->chan_ntargets = sc->sc_max_devices;
   2301  1.1  bouyer 	chan->chan_id = -1;
   2302  1.1  bouyer 
   2303  1.1  bouyer 	mpii_rescan(self, "scsi", NULL);
   2304  1.1  bouyer 
   2305  1.1  bouyer 	/* enable interrupts */
   2306  1.1  bouyer 	mpii_write(sc, MPII_INTR_MASK, MPII_INTR_MASK_DOORBELL
   2307  1.1  bouyer 	    | MPII_INTR_MASK_RESET);
   2308  1.1  bouyer 
   2309  1.1  bouyer #if NBIO > 0
   2310  1.1  bouyer 	if (ISSET(sc->sc_flags, MPII_F_RAID)) {
   2311  1.1  bouyer 		if (bio_register(sc->sc_dev, mpii_ioctl) != 0)
   2312  1.1  bouyer 			panic("%s: controller registration failed",
   2313  1.1  bouyer 			    DEVNAME(sc));
   2314  1.1  bouyer 
   2315  1.1  bouyer 		if (mpii_create_sensors(sc) != 0)
   2316  1.1  bouyer 			aprint_error_dev(self, "unable to create sensors\n");
   2317  1.1  bouyer 	}
   2318  1.1  bouyer #endif
   2319  1.1  bouyer 
   2320  1.1  bouyer 	return;
   2321  1.1  bouyer 
   2322  1.1  bouyer free_dev:
   2323  1.1  bouyer 	if (sc->sc_devs)
   2324  1.1  bouyer 		free(sc->sc_devs, M_DEVBUF);
   2325  1.1  bouyer 
   2326  1.1  bouyer free_queues:
   2327  1.1  bouyer 	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_freeq),
   2328  1.1  bouyer      	    0, sc->sc_reply_free_qdepth * 4, BUS_DMASYNC_POSTREAD);
   2329  1.1  bouyer 	mpii_dmamem_free(sc, sc->sc_reply_freeq);
   2330  1.1  bouyer 
   2331  1.1  bouyer 	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq),
   2332  1.1  bouyer 	    0, sc->sc_reply_post_qdepth * 8, BUS_DMASYNC_POSTREAD);
   2333  1.1  bouyer 	mpii_dmamem_free(sc, sc->sc_reply_postq);
   2334  1.1  bouyer 
   2335  1.1  bouyer free_replies:
   2336  1.1  bouyer 	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_replies),
   2337  1.1  bouyer 		0, PAGE_SIZE, BUS_DMASYNC_POSTREAD);
   2338  1.1  bouyer 	mpii_dmamem_free(sc, sc->sc_replies);
   2339  1.1  bouyer 
   2340  1.1  bouyer free_ccbs:
   2341  1.1  bouyer 	while ((ccb = mpii_get_ccb(sc, MPII_NOSLEEP)) != NULL)
   2342  1.1  bouyer 		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
   2343  1.1  bouyer 	mpii_dmamem_free(sc, sc->sc_requests);
   2344  1.1  bouyer 	free(sc->sc_ccbs, M_DEVBUF);
   2345  1.1  bouyer 
   2346  1.1  bouyer unmap:
   2347  1.1  bouyer 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
   2348  1.1  bouyer 	sc->sc_ios = 0;
   2349  1.1  bouyer }
   2350  1.1  bouyer 
   2351  1.1  bouyer static int
   2352  1.1  bouyer mpii_detach(device_t self, int flags)
   2353  1.1  bouyer {
   2354  1.1  bouyer 	struct mpii_softc		*sc = device_private(self);
   2355  1.1  bouyer 	int error;
   2356  1.1  bouyer 	struct mpii_ccb *ccb;
   2357  1.1  bouyer 
   2358  1.1  bouyer 	if ((error = config_detach_children(sc->sc_dev, flags)) != 0)
   2359  1.1  bouyer 		return error;
   2360  1.1  bouyer 
   2361  1.1  bouyer #if NBIO > 0
   2362  1.1  bouyer 	mpii_destroy_sensors(sc);
   2363  1.1  bouyer 	bio_unregister(sc->sc_dev);
   2364  1.1  bouyer #endif /* NBIO > 0 */
   2365  1.1  bouyer 
   2366  1.1  bouyer 	if (sc->sc_ih != NULL) {
   2367  1.1  bouyer 		if (sc->sc_devs)
   2368  1.1  bouyer 			free(sc->sc_devs, M_DEVBUF);
   2369  1.1  bouyer 
   2370  1.1  bouyer 		bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_freeq),
   2371  1.1  bouyer 		    0, sc->sc_reply_free_qdepth * 4, BUS_DMASYNC_POSTREAD);
   2372  1.1  bouyer 		mpii_dmamem_free(sc, sc->sc_reply_freeq);
   2373  1.1  bouyer 
   2374  1.1  bouyer 		bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq),
   2375  1.1  bouyer 		    0, sc->sc_reply_post_qdepth * 8, BUS_DMASYNC_POSTREAD);
   2376  1.1  bouyer 		mpii_dmamem_free(sc, sc->sc_reply_postq);
   2377  1.1  bouyer 
   2378  1.1  bouyer 		bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_replies),
   2379  1.1  bouyer 			0, PAGE_SIZE, BUS_DMASYNC_POSTREAD);
   2380  1.1  bouyer 		mpii_dmamem_free(sc, sc->sc_replies);
   2381  1.1  bouyer 
   2382  1.1  bouyer 		while ((ccb = mpii_get_ccb(sc, MPII_NOSLEEP)) != NULL)
   2383  1.1  bouyer 			bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
   2384  1.1  bouyer 		mpii_dmamem_free(sc, sc->sc_requests);
   2385  1.1  bouyer 		free(sc->sc_ccbs, M_DEVBUF);
   2386  1.1  bouyer 
   2387  1.1  bouyer 		pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
   2388  1.1  bouyer 		sc->sc_ih = NULL;
   2389  1.1  bouyer 	}
   2390  1.1  bouyer 	if (sc->sc_ios != 0) {
   2391  1.1  bouyer 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
   2392  1.1  bouyer 		sc->sc_ios = 0;
   2393  1.1  bouyer 	}
   2394  1.1  bouyer 
   2395  1.1  bouyer 	return (0);
   2396  1.1  bouyer }
   2397  1.1  bouyer 
   2398  1.1  bouyer static int
   2399  1.1  bouyer mpii_rescan(device_t self, const char *ifattr, const int *locators)
   2400  1.1  bouyer {
   2401  1.1  bouyer 	struct mpii_softc *sc = device_private(self);
   2402  1.1  bouyer 
   2403  1.1  bouyer 	if (sc->sc_child != NULL)
   2404  1.1  bouyer 		return 0;
   2405  1.1  bouyer 
   2406  1.1  bouyer 	sc->sc_child = config_found_sm_loc(self, ifattr, locators, &sc->sc_chan,
   2407  1.1  bouyer 	    scsiprint, NULL);
   2408  1.1  bouyer 
   2409  1.1  bouyer 	return 0;
   2410  1.1  bouyer }
   2411  1.1  bouyer 
   2412  1.1  bouyer static void
   2413  1.1  bouyer mpii_childdetached(device_t self, device_t child)
   2414  1.1  bouyer {
   2415  1.1  bouyer         struct mpii_softc *sc = device_private(self);
   2416  1.1  bouyer 
   2417  1.1  bouyer         KASSERT(self == sc->sc_dev);
   2418  1.1  bouyer         KASSERT(child == sc->sc_child);
   2419  1.1  bouyer 
   2420  1.1  bouyer         if (child == sc->sc_child)
   2421  1.1  bouyer                 sc->sc_child = NULL;
   2422  1.1  bouyer }
   2423  1.1  bouyer 
   2424  1.1  bouyer static int
   2425  1.1  bouyer mpii_intr(void *arg)
   2426  1.1  bouyer {
   2427  1.1  bouyer 	struct mpii_rcb_list		evts = SIMPLEQ_HEAD_INITIALIZER(evts);
   2428  1.1  bouyer 	struct mpii_ccb_list		ccbs = SIMPLEQ_HEAD_INITIALIZER(ccbs);
   2429  1.1  bouyer 	struct mpii_softc		*sc = arg;
   2430  1.1  bouyer 	struct mpii_reply_descr		*postq = sc->sc_reply_postq_kva, *rdp;
   2431  1.1  bouyer 	struct mpii_ccb			*ccb;
   2432  1.1  bouyer 	struct mpii_rcb			*rcb;
   2433  1.1  bouyer 	int				smid;
   2434  1.1  bouyer 	int				rv = 0;
   2435  1.1  bouyer 
   2436  1.1  bouyer 	mutex_enter(&sc->sc_rep_mtx);
   2437  1.1  bouyer 	bus_dmamap_sync(sc->sc_dmat,
   2438  1.1  bouyer 	    MPII_DMA_MAP(sc->sc_reply_postq),
   2439  1.1  bouyer 	    0, 8 * sc->sc_reply_post_qdepth,
   2440  1.1  bouyer 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
   2441  1.1  bouyer 
   2442  1.1  bouyer 	for (;;) {
   2443  1.1  bouyer 		rdp = &postq[sc->sc_reply_post_host_index];
   2444  1.1  bouyer 		if ((rdp->reply_flags & MPII_REPLY_DESCR_TYPE_MASK) ==
   2445  1.1  bouyer 		    MPII_REPLY_DESCR_UNUSED)
   2446  1.1  bouyer 			break;
   2447  1.1  bouyer 		if (rdp->data == 0xffffffff) {
   2448  1.1  bouyer 			/*
   2449  1.1  bouyer 			 * ioc is still writing to the reply post queue
   2450  1.1  bouyer 			 * race condition - bail!
   2451  1.1  bouyer 			 */
   2452  1.1  bouyer 			break;
   2453  1.1  bouyer 		}
   2454  1.1  bouyer 
   2455  1.1  bouyer 		smid = le16toh(rdp->smid);
   2456  1.1  bouyer 		rcb = mpii_reply(sc, rdp);
   2457  1.1  bouyer 
   2458  1.1  bouyer 		if (smid) {
   2459  1.1  bouyer 			ccb = &sc->sc_ccbs[smid - 1];
   2460  1.1  bouyer 			ccb->ccb_state = MPII_CCB_READY;
   2461  1.1  bouyer 			ccb->ccb_rcb = rcb;
   2462  1.1  bouyer 			SIMPLEQ_INSERT_TAIL(&ccbs, ccb, u.ccb_link);
   2463  1.1  bouyer 		} else
   2464  1.1  bouyer 			SIMPLEQ_INSERT_TAIL(&evts, rcb, u.rcb_link);
   2465  1.1  bouyer 
   2466  1.1  bouyer 		sc->sc_reply_post_host_index++;
   2467  1.1  bouyer 		sc->sc_reply_post_host_index %= sc->sc_reply_post_qdepth;
   2468  1.1  bouyer 		rv = 1;
   2469  1.1  bouyer 	}
   2470  1.1  bouyer 
   2471  1.1  bouyer 	bus_dmamap_sync(sc->sc_dmat,
   2472  1.1  bouyer 	    MPII_DMA_MAP(sc->sc_reply_postq),
   2473  1.1  bouyer 	    0, 8 * sc->sc_reply_post_qdepth,
   2474  1.1  bouyer 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
   2475  1.1  bouyer 
   2476  1.1  bouyer 	if (rv)
   2477  1.1  bouyer 		mpii_write_reply_post(sc, sc->sc_reply_post_host_index);
   2478  1.1  bouyer 
   2479  1.1  bouyer 	mutex_exit(&sc->sc_rep_mtx);
   2480  1.1  bouyer 
   2481  1.1  bouyer 	if (rv == 0)
   2482  1.1  bouyer 		return (0);
   2483  1.1  bouyer 
   2484  1.1  bouyer 	while ((ccb = SIMPLEQ_FIRST(&ccbs)) != NULL) {
   2485  1.1  bouyer 		SIMPLEQ_REMOVE_HEAD(&ccbs, u.ccb_link);
   2486  1.1  bouyer 		ccb->ccb_done(ccb);
   2487  1.1  bouyer 	}
   2488  1.1  bouyer 	while ((rcb = SIMPLEQ_FIRST(&evts)) != NULL) {
   2489  1.1  bouyer 		SIMPLEQ_REMOVE_HEAD(&evts, u.rcb_link);
   2490  1.1  bouyer 		mpii_event_process(sc, rcb);
   2491  1.1  bouyer 	}
   2492  1.1  bouyer 
   2493  1.1  bouyer 	return (1);
   2494  1.1  bouyer }
   2495  1.1  bouyer 
   2496  1.1  bouyer static int
   2497  1.1  bouyer mpii_load_xs(struct mpii_ccb *ccb)
   2498  1.1  bouyer {
   2499  1.1  bouyer 	struct mpii_softc	*sc = ccb->ccb_sc;
   2500  1.1  bouyer 	struct scsipi_xfer	*xs = ccb->ccb_cookie;
   2501  1.1  bouyer 	struct mpii_ccb_bundle	*mcb = ccb->ccb_cmd;
   2502  1.1  bouyer 	struct mpii_msg_scsi_io	*io = &mcb->mcb_io;
   2503  1.1  bouyer 	struct mpii_sge		*sge = NULL, *nsge = &mcb->mcb_sgl[0];
   2504  1.1  bouyer 	struct mpii_sge		*ce = NULL, *nce = NULL;
   2505  1.1  bouyer 	u_int64_t		ce_dva;
   2506  1.1  bouyer 	bus_dmamap_t		dmap = ccb->ccb_dmamap;
   2507  1.1  bouyer 	u_int32_t		addr, flags;
   2508  1.1  bouyer 	int			i, error;
   2509  1.1  bouyer 
   2510  1.1  bouyer 	/* zero length transfer still requires an SGE */
   2511  1.1  bouyer 	if (xs->datalen == 0) {
   2512  1.1  bouyer 		nsge->sg_hdr = htole32(MPII_SGE_FL_TYPE_SIMPLE |
   2513  1.1  bouyer 		    MPII_SGE_FL_LAST | MPII_SGE_FL_EOB | MPII_SGE_FL_EOL);
   2514  1.1  bouyer 		return (0);
   2515  1.1  bouyer 	}
   2516  1.1  bouyer 
   2517  1.1  bouyer 	error = bus_dmamap_load(sc->sc_dmat, dmap,
   2518  1.1  bouyer 	    xs->data, xs->datalen, NULL, (xs->xs_control & XS_CTL_NOSLEEP) ?
   2519  1.1  bouyer 	      BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
   2520  1.1  bouyer 	if (error) {
   2521  1.1  bouyer 		aprint_error_dev(sc->sc_dev, "error %d loading dmamap\n",
   2522  1.1  bouyer 		    error);
   2523  1.1  bouyer 		return (1);
   2524  1.1  bouyer 	}
   2525  1.1  bouyer 
   2526  1.1  bouyer 	/* safe default staring flags */
   2527  1.1  bouyer 	flags = MPII_SGE_FL_TYPE_SIMPLE | MPII_SGE_FL_SIZE_64;
   2528  1.1  bouyer 	/* if data out */
   2529  1.1  bouyer 	if (xs->xs_control & XS_CTL_DATA_OUT)
   2530  1.1  bouyer 		flags |= MPII_SGE_FL_DIR_OUT;
   2531  1.1  bouyer 
   2532  1.1  bouyer 	/* we will have to exceed the SGEs we can cram into the request frame */
   2533  1.1  bouyer 	if (dmap->dm_nsegs > sc->sc_first_sgl_len) {
   2534  1.1  bouyer 		ce = &mcb->mcb_sgl[sc->sc_first_sgl_len - 1];
   2535  1.1  bouyer 		io->chain_offset = ((u_int8_t *)ce - (u_int8_t *)io) / 4;
   2536  1.1  bouyer 	}
   2537  1.1  bouyer 
   2538  1.1  bouyer 	for (i = 0; i < dmap->dm_nsegs; i++) {
   2539  1.1  bouyer 		if (nsge == ce) {
   2540  1.1  bouyer 			nsge++;
   2541  1.1  bouyer 			sge->sg_hdr |= htole32(MPII_SGE_FL_LAST);
   2542  1.1  bouyer 
   2543  1.1  bouyer 			DNPRINTF(MPII_D_DMA, "%s:   - 0x%08x 0x%08x 0x%08x\n",
   2544  1.1  bouyer 			    DEVNAME(sc), sge->sg_hdr,
   2545  1.1  bouyer 			    sge->sg_hi_addr, sge->sg_lo_addr);
   2546  1.1  bouyer 
   2547  1.1  bouyer 			if ((dmap->dm_nsegs - i) > sc->sc_chain_len) {
   2548  1.1  bouyer 				nce = &nsge[sc->sc_chain_len - 1];
   2549  1.1  bouyer 				addr = ((u_int8_t *)nce - (u_int8_t *)nsge) / 4;
   2550  1.1  bouyer 				addr = addr << 16 |
   2551  1.1  bouyer 				    sizeof(struct mpii_sge) * sc->sc_chain_len;
   2552  1.1  bouyer 			} else {
   2553  1.1  bouyer 				nce = NULL;
   2554  1.1  bouyer 				addr = sizeof(struct mpii_sge) *
   2555  1.1  bouyer 				    (dmap->dm_nsegs - i);
   2556  1.1  bouyer 			}
   2557  1.1  bouyer 
   2558  1.1  bouyer 			ce->sg_hdr = htole32(MPII_SGE_FL_TYPE_CHAIN |
   2559  1.1  bouyer 			    MPII_SGE_FL_SIZE_64 | addr);
   2560  1.1  bouyer 
   2561  1.1  bouyer 			ce_dva = ccb->ccb_cmd_dva +
   2562  1.1  bouyer 			    ((u_int8_t *)nsge - (u_int8_t *)mcb);
   2563  1.1  bouyer 
   2564  1.1  bouyer 			addr = (u_int32_t)(ce_dva >> 32);
   2565  1.1  bouyer 			ce->sg_hi_addr = htole32(addr);
   2566  1.1  bouyer 			addr = (u_int32_t)ce_dva;
   2567  1.1  bouyer 			ce->sg_lo_addr = htole32(addr);
   2568  1.1  bouyer 
   2569  1.1  bouyer 			DNPRINTF(MPII_D_DMA, "%s:  ce: 0x%08x 0x%08x 0x%08x\n",
   2570  1.1  bouyer 			    DEVNAME(sc), ce->sg_hdr, ce->sg_hi_addr,
   2571  1.1  bouyer 			    ce->sg_lo_addr);
   2572  1.1  bouyer 
   2573  1.1  bouyer 			ce = nce;
   2574  1.1  bouyer 		}
   2575  1.1  bouyer 
   2576  1.1  bouyer 		DNPRINTF(MPII_D_DMA, "%s:  %d: %" PRId64 " 0x%016" PRIx64 "\n",
   2577  1.1  bouyer 		    DEVNAME(sc), i, (int64_t)dmap->dm_segs[i].ds_len,
   2578  1.1  bouyer 		    (u_int64_t)dmap->dm_segs[i].ds_addr);
   2579  1.1  bouyer 
   2580  1.1  bouyer 		sge = nsge;
   2581  1.1  bouyer 
   2582  1.1  bouyer 		sge->sg_hdr = htole32(flags | dmap->dm_segs[i].ds_len);
   2583  1.1  bouyer 		addr = (u_int32_t)((u_int64_t)dmap->dm_segs[i].ds_addr >> 32);
   2584  1.1  bouyer 		sge->sg_hi_addr = htole32(addr);
   2585  1.1  bouyer 		addr = (u_int32_t)dmap->dm_segs[i].ds_addr;
   2586  1.1  bouyer 		sge->sg_lo_addr = htole32(addr);
   2587  1.1  bouyer 
   2588  1.1  bouyer 		DNPRINTF(MPII_D_DMA, "%s:  %d: 0x%08x 0x%08x 0x%08x\n",
   2589  1.1  bouyer 		    DEVNAME(sc), i, sge->sg_hdr, sge->sg_hi_addr,
   2590  1.1  bouyer 		    sge->sg_lo_addr);
   2591  1.1  bouyer 
   2592  1.1  bouyer 		nsge = sge + 1;
   2593  1.1  bouyer 	}
   2594  1.1  bouyer 
   2595  1.1  bouyer 	/* terminate list */
   2596  1.1  bouyer 	sge->sg_hdr |= htole32(MPII_SGE_FL_LAST | MPII_SGE_FL_EOB |
   2597  1.1  bouyer 	    MPII_SGE_FL_EOL);
   2598  1.1  bouyer 
   2599  1.1  bouyer 	bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
   2600  1.1  bouyer 	    (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD :
   2601  1.1  bouyer 	    BUS_DMASYNC_PREWRITE);
   2602  1.1  bouyer 
   2603  1.1  bouyer 	return (0);
   2604  1.1  bouyer }
   2605  1.1  bouyer 
   2606  1.1  bouyer static u_int32_t
   2607  1.1  bouyer mpii_read(struct mpii_softc *sc, bus_size_t r)
   2608  1.1  bouyer {
   2609  1.1  bouyer 	u_int32_t			rv;
   2610  1.1  bouyer 
   2611  1.1  bouyer 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
   2612  1.1  bouyer 	    BUS_SPACE_BARRIER_READ);
   2613  1.1  bouyer 	rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
   2614  1.1  bouyer 
   2615  1.1  bouyer 	DNPRINTF(MPII_D_RW, "%s: mpii_read %#" PRIx64 " %#x\n", DEVNAME(sc),
   2616  1.1  bouyer 	    (uint64_t)r, rv);
   2617  1.1  bouyer 
   2618  1.1  bouyer 	return (rv);
   2619  1.1  bouyer }
   2620  1.1  bouyer 
   2621  1.1  bouyer static void
   2622  1.1  bouyer mpii_write(struct mpii_softc *sc, bus_size_t r, u_int32_t v)
   2623  1.1  bouyer {
   2624  1.1  bouyer 	DNPRINTF(MPII_D_RW, "%s: mpii_write %#" PRIx64 " %#x\n", DEVNAME(sc),
   2625  1.1  bouyer 	    (uint64_t)r, v);
   2626  1.1  bouyer 
   2627  1.1  bouyer 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
   2628  1.1  bouyer 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
   2629  1.1  bouyer 	    BUS_SPACE_BARRIER_WRITE);
   2630  1.1  bouyer }
   2631  1.1  bouyer 
   2632  1.1  bouyer 
   2633  1.1  bouyer static int
   2634  1.1  bouyer mpii_wait_eq(struct mpii_softc *sc, bus_size_t r, u_int32_t mask,
   2635  1.1  bouyer     u_int32_t target)
   2636  1.1  bouyer {
   2637  1.1  bouyer 	int			i;
   2638  1.1  bouyer 
   2639  1.1  bouyer 	DNPRINTF(MPII_D_RW, "%s: mpii_wait_eq %#" PRIx64 " %#x %#x\n",
   2640  1.1  bouyer 	    DEVNAME(sc), (uint64_t)r, mask, target);
   2641  1.1  bouyer 
   2642  1.1  bouyer 	for (i = 0; i < 15000; i++) {
   2643  1.1  bouyer 		if ((mpii_read(sc, r) & mask) == target)
   2644  1.1  bouyer 			return (0);
   2645  1.1  bouyer 		delay(1000);
   2646  1.1  bouyer 	}
   2647  1.1  bouyer 
   2648  1.1  bouyer 	return (1);
   2649  1.1  bouyer }
   2650  1.1  bouyer 
   2651  1.1  bouyer static int
   2652  1.1  bouyer mpii_wait_ne(struct mpii_softc *sc, bus_size_t r, u_int32_t mask,
   2653  1.1  bouyer     u_int32_t target)
   2654  1.1  bouyer {
   2655  1.1  bouyer 	int			i;
   2656  1.1  bouyer 
   2657  1.1  bouyer 	DNPRINTF(MPII_D_RW, "%s: mpii_wait_ne %#" PRIx64 " %#x %#x\n",
   2658  1.1  bouyer 	    DEVNAME(sc), (uint64_t)r, mask, target);
   2659  1.1  bouyer 
   2660  1.1  bouyer 	for (i = 0; i < 15000; i++) {
   2661  1.1  bouyer 		if ((mpii_read(sc, r) & mask) != target)
   2662  1.1  bouyer 			return (0);
   2663  1.1  bouyer 		delay(1000);
   2664  1.1  bouyer 	}
   2665  1.1  bouyer 
   2666  1.1  bouyer 	return (1);
   2667  1.1  bouyer }
   2668  1.1  bouyer 
   2669  1.1  bouyer 
   2670  1.1  bouyer static int
   2671  1.1  bouyer mpii_init(struct mpii_softc *sc)
   2672  1.1  bouyer {
   2673  1.1  bouyer 	u_int32_t		db;
   2674  1.1  bouyer 	int			i;
   2675  1.1  bouyer 
   2676  1.1  bouyer 	/* spin until the ioc leaves the reset state */
   2677  1.1  bouyer 	if (mpii_wait_ne(sc, MPII_DOORBELL, MPII_DOORBELL_STATE,
   2678  1.1  bouyer 	    MPII_DOORBELL_STATE_RESET) != 0) {
   2679  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_init timeout waiting to leave "
   2680  1.1  bouyer 		    "reset state\n", DEVNAME(sc));
   2681  1.1  bouyer 		return (1);
   2682  1.1  bouyer 	}
   2683  1.1  bouyer 
   2684  1.1  bouyer 	/* check current ownership */
   2685  1.1  bouyer 	db = mpii_read_db(sc);
   2686  1.1  bouyer 	if ((db & MPII_DOORBELL_WHOINIT) == MPII_DOORBELL_WHOINIT_PCIPEER) {
   2687  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_init initialised by pci peer\n",
   2688  1.1  bouyer 		    DEVNAME(sc));
   2689  1.1  bouyer 		return (0);
   2690  1.1  bouyer 	}
   2691  1.1  bouyer 
   2692  1.1  bouyer 	for (i = 0; i < 5; i++) {
   2693  1.1  bouyer 		switch (db & MPII_DOORBELL_STATE) {
   2694  1.1  bouyer 		case MPII_DOORBELL_STATE_READY:
   2695  1.1  bouyer 			DNPRINTF(MPII_D_MISC, "%s: mpii_init ioc is ready\n",
   2696  1.1  bouyer 			    DEVNAME(sc));
   2697  1.1  bouyer 			return (0);
   2698  1.1  bouyer 
   2699  1.1  bouyer 		case MPII_DOORBELL_STATE_OPER:
   2700  1.1  bouyer 			DNPRINTF(MPII_D_MISC, "%s: mpii_init ioc is oper\n",
   2701  1.1  bouyer 			    DEVNAME(sc));
   2702  1.1  bouyer 			if (sc->sc_ioc_event_replay)
   2703  1.1  bouyer 				mpii_reset_soft(sc);
   2704  1.1  bouyer 			else
   2705  1.1  bouyer 				mpii_reset_hard(sc);
   2706  1.1  bouyer 			break;
   2707  1.1  bouyer 
   2708  1.1  bouyer 		case MPII_DOORBELL_STATE_FAULT:
   2709  1.1  bouyer 			DNPRINTF(MPII_D_MISC, "%s: mpii_init ioc is being "
   2710  1.1  bouyer 			    "reset hard\n" , DEVNAME(sc));
   2711  1.1  bouyer 			mpii_reset_hard(sc);
   2712  1.1  bouyer 			break;
   2713  1.1  bouyer 
   2714  1.1  bouyer 		case MPII_DOORBELL_STATE_RESET:
   2715  1.1  bouyer 			DNPRINTF(MPII_D_MISC, "%s: mpii_init waiting to come "
   2716  1.1  bouyer 			    "out of reset\n", DEVNAME(sc));
   2717  1.1  bouyer 			if (mpii_wait_ne(sc, MPII_DOORBELL, MPII_DOORBELL_STATE,
   2718  1.1  bouyer 			    MPII_DOORBELL_STATE_RESET) != 0)
   2719  1.1  bouyer 				return (1);
   2720  1.1  bouyer 			break;
   2721  1.1  bouyer 		}
   2722  1.1  bouyer 		db = mpii_read_db(sc);
   2723  1.1  bouyer 	}
   2724  1.1  bouyer 
   2725  1.1  bouyer 	return (1);
   2726  1.1  bouyer }
   2727  1.1  bouyer 
   2728  1.1  bouyer static int
   2729  1.1  bouyer mpii_reset_soft(struct mpii_softc *sc)
   2730  1.1  bouyer {
   2731  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_reset_soft\n", DEVNAME(sc));
   2732  1.1  bouyer 
   2733  1.1  bouyer 	if (mpii_read_db(sc) & MPII_DOORBELL_INUSE) {
   2734  1.1  bouyer 		return (1);
   2735  1.1  bouyer 	}
   2736  1.1  bouyer 
   2737  1.1  bouyer 	mpii_write_db(sc,
   2738  1.1  bouyer 	    MPII_DOORBELL_FUNCTION(MPII_FUNCTION_IOC_MESSAGE_UNIT_RESET));
   2739  1.1  bouyer 
   2740  1.1  bouyer 	/* XXX LSI waits 15 sec */
   2741  1.1  bouyer 	if (mpii_wait_db_ack(sc) != 0)
   2742  1.1  bouyer 		return (1);
   2743  1.1  bouyer 
   2744  1.1  bouyer 	/* XXX LSI waits 15 sec */
   2745  1.1  bouyer 	if (mpii_wait_eq(sc, MPII_DOORBELL, MPII_DOORBELL_STATE,
   2746  1.1  bouyer 	    MPII_DOORBELL_STATE_READY) != 0)
   2747  1.1  bouyer 		return (1);
   2748  1.1  bouyer 
   2749  1.1  bouyer 	/* XXX wait for Sys2IOCDB bit to clear in HIS?? */
   2750  1.1  bouyer 
   2751  1.1  bouyer 	return (0);
   2752  1.1  bouyer }
   2753  1.1  bouyer 
   2754  1.1  bouyer static int
   2755  1.1  bouyer mpii_reset_hard(struct mpii_softc *sc)
   2756  1.1  bouyer {
   2757  1.1  bouyer 	u_int16_t		i;
   2758  1.1  bouyer 
   2759  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_reset_hard\n", DEVNAME(sc));
   2760  1.1  bouyer 
   2761  1.1  bouyer 	mpii_write_intr(sc, 0);
   2762  1.1  bouyer 
   2763  1.1  bouyer 	/* enable diagnostic register */
   2764  1.1  bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_FLUSH);
   2765  1.1  bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_1);
   2766  1.1  bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_2);
   2767  1.1  bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_3);
   2768  1.1  bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_4);
   2769  1.1  bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_5);
   2770  1.1  bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_6);
   2771  1.1  bouyer 
   2772  1.1  bouyer 	delay(100);
   2773  1.1  bouyer 
   2774  1.1  bouyer 	if ((mpii_read(sc, MPII_HOSTDIAG) & MPII_HOSTDIAG_DWRE) == 0) {
   2775  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_reset_hard failure to enable "
   2776  1.1  bouyer 		    "diagnostic read/write\n", DEVNAME(sc));
   2777  1.1  bouyer 		return(1);
   2778  1.1  bouyer 	}
   2779  1.1  bouyer 
   2780  1.1  bouyer 	/* reset ioc */
   2781  1.1  bouyer 	mpii_write(sc, MPII_HOSTDIAG, MPII_HOSTDIAG_RESET_ADAPTER);
   2782  1.1  bouyer 
   2783  1.1  bouyer 	/* 240 milliseconds */
   2784  1.1  bouyer 	delay(240000);
   2785  1.1  bouyer 
   2786  1.1  bouyer 
   2787  1.1  bouyer 	/* XXX this whole function should be more robust */
   2788  1.1  bouyer 
   2789  1.1  bouyer 	/* XXX  read the host diagnostic reg until reset adapter bit clears ? */
   2790  1.1  bouyer 	for (i = 0; i < 30000; i++) {
   2791  1.1  bouyer 		if ((mpii_read(sc, MPII_HOSTDIAG) &
   2792  1.1  bouyer 		    MPII_HOSTDIAG_RESET_ADAPTER) == 0)
   2793  1.1  bouyer 			break;
   2794  1.1  bouyer 		delay(10000);
   2795  1.1  bouyer 	}
   2796  1.1  bouyer 
   2797  1.1  bouyer 	/* disable diagnostic register */
   2798  1.1  bouyer 	mpii_write(sc, MPII_WRITESEQ, 0xff);
   2799  1.1  bouyer 
   2800  1.1  bouyer 	/* XXX what else? */
   2801  1.1  bouyer 
   2802  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s: done with mpii_reset_hard\n", DEVNAME(sc));
   2803  1.1  bouyer 
   2804  1.1  bouyer 	return(0);
   2805  1.1  bouyer }
   2806  1.1  bouyer 
   2807  1.1  bouyer static int
   2808  1.1  bouyer mpii_handshake_send(struct mpii_softc *sc, void *buf, size_t dwords)
   2809  1.1  bouyer {
   2810  1.1  bouyer 	u_int32_t		*query = buf;
   2811  1.1  bouyer 	int			i;
   2812  1.1  bouyer 
   2813  1.1  bouyer 	/* make sure the doorbell is not in use. */
   2814  1.1  bouyer 	if (mpii_read_db(sc) & MPII_DOORBELL_INUSE)
   2815  1.1  bouyer 		return (1);
   2816  1.1  bouyer 
   2817  1.1  bouyer 	/* clear pending doorbell interrupts */
   2818  1.1  bouyer 	if (mpii_read_intr(sc) & MPII_INTR_STATUS_IOC2SYSDB)
   2819  1.1  bouyer 		mpii_write_intr(sc, 0);
   2820  1.1  bouyer 
   2821  1.1  bouyer 	/*
   2822  1.1  bouyer 	 * first write the doorbell with the handshake function and the
   2823  1.1  bouyer 	 * dword count.
   2824  1.1  bouyer 	 */
   2825  1.1  bouyer 	mpii_write_db(sc, MPII_DOORBELL_FUNCTION(MPII_FUNCTION_HANDSHAKE) |
   2826  1.1  bouyer 	    MPII_DOORBELL_DWORDS(dwords));
   2827  1.1  bouyer 
   2828  1.1  bouyer 	/*
   2829  1.1  bouyer 	 * the doorbell used bit will be set because a doorbell function has
   2830  1.1  bouyer 	 * started. wait for the interrupt and then ack it.
   2831  1.1  bouyer 	 */
   2832  1.1  bouyer 	if (mpii_wait_db_int(sc) != 0)
   2833  1.1  bouyer 		return (1);
   2834  1.1  bouyer 	mpii_write_intr(sc, 0);
   2835  1.1  bouyer 
   2836  1.1  bouyer 	/* poll for the acknowledgement. */
   2837  1.1  bouyer 	if (mpii_wait_db_ack(sc) != 0)
   2838  1.1  bouyer 		return (1);
   2839  1.1  bouyer 
   2840  1.1  bouyer 	/* write the query through the doorbell. */
   2841  1.1  bouyer 	for (i = 0; i < dwords; i++) {
   2842  1.1  bouyer 		mpii_write_db(sc, htole32(query[i]));
   2843  1.1  bouyer 		if (mpii_wait_db_ack(sc) != 0)
   2844  1.1  bouyer 			return (1);
   2845  1.1  bouyer 	}
   2846  1.1  bouyer 
   2847  1.1  bouyer 	return (0);
   2848  1.1  bouyer }
   2849  1.1  bouyer 
   2850  1.1  bouyer static int
   2851  1.1  bouyer mpii_handshake_recv_dword(struct mpii_softc *sc, u_int32_t *dword)
   2852  1.1  bouyer {
   2853  1.1  bouyer 	u_int16_t		*words = (u_int16_t *)dword;
   2854  1.1  bouyer 	int			i;
   2855  1.1  bouyer 
   2856  1.1  bouyer 	for (i = 0; i < 2; i++) {
   2857  1.1  bouyer 		if (mpii_wait_db_int(sc) != 0)
   2858  1.1  bouyer 			return (1);
   2859  1.1  bouyer 		words[i] = le16toh(mpii_read_db(sc) & MPII_DOORBELL_DATA_MASK);
   2860  1.1  bouyer 		mpii_write_intr(sc, 0);
   2861  1.1  bouyer 	}
   2862  1.1  bouyer 
   2863  1.1  bouyer 	return (0);
   2864  1.1  bouyer }
   2865  1.1  bouyer 
   2866  1.1  bouyer static int
   2867  1.1  bouyer mpii_handshake_recv(struct mpii_softc *sc, void *buf, size_t dwords)
   2868  1.1  bouyer {
   2869  1.1  bouyer 	struct mpii_msg_reply	*reply = buf;
   2870  1.1  bouyer 	u_int32_t		*dbuf = buf, dummy;
   2871  1.1  bouyer 	int			i;
   2872  1.1  bouyer 
   2873  1.1  bouyer 	/* get the first dword so we can read the length out of the header. */
   2874  1.1  bouyer 	if (mpii_handshake_recv_dword(sc, &dbuf[0]) != 0)
   2875  1.1  bouyer 		return (1);
   2876  1.1  bouyer 
   2877  1.1  bouyer 	DNPRINTF(MPII_D_CMD, "%s: mpii_handshake_recv dwords: %zd reply: %d\n",
   2878  1.1  bouyer 	    DEVNAME(sc), dwords, reply->msg_length);
   2879  1.1  bouyer 
   2880  1.1  bouyer 	/*
   2881  1.1  bouyer 	 * the total length, in dwords, is in the message length field of the
   2882  1.1  bouyer 	 * reply header.
   2883  1.1  bouyer 	 */
   2884  1.1  bouyer 	for (i = 1; i < MIN(dwords, reply->msg_length); i++) {
   2885  1.1  bouyer 		if (mpii_handshake_recv_dword(sc, &dbuf[i]) != 0)
   2886  1.1  bouyer 			return (1);
   2887  1.1  bouyer 	}
   2888  1.1  bouyer 
   2889  1.1  bouyer 	/* if there's extra stuff to come off the ioc, discard it */
   2890  1.1  bouyer 	while (i++ < reply->msg_length) {
   2891  1.1  bouyer 		if (mpii_handshake_recv_dword(sc, &dummy) != 0)
   2892  1.1  bouyer 			return (1);
   2893  1.1  bouyer 		DNPRINTF(MPII_D_CMD, "%s: mpii_handshake_recv dummy read: "
   2894  1.1  bouyer 		    "0x%08x\n", DEVNAME(sc), dummy);
   2895  1.1  bouyer 	}
   2896  1.1  bouyer 
   2897  1.1  bouyer 	/* wait for the doorbell used bit to be reset and clear the intr */
   2898  1.1  bouyer 	if (mpii_wait_db_int(sc) != 0)
   2899  1.1  bouyer 		return (1);
   2900  1.1  bouyer 
   2901  1.1  bouyer 	if (mpii_wait_eq(sc, MPII_DOORBELL, MPII_DOORBELL_INUSE, 0) != 0)
   2902  1.1  bouyer 		return (1);
   2903  1.1  bouyer 
   2904  1.1  bouyer 	mpii_write_intr(sc, 0);
   2905  1.1  bouyer 
   2906  1.1  bouyer 	return (0);
   2907  1.1  bouyer }
   2908  1.1  bouyer 
   2909  1.1  bouyer static void
   2910  1.1  bouyer mpii_empty_done(struct mpii_ccb *ccb)
   2911  1.1  bouyer {
   2912  1.1  bouyer 	/* nothing to do */
   2913  1.1  bouyer }
   2914  1.1  bouyer 
   2915  1.1  bouyer static int
   2916  1.1  bouyer mpii_iocfacts(struct mpii_softc *sc)
   2917  1.1  bouyer {
   2918  1.1  bouyer 	struct mpii_msg_iocfacts_request	ifq;
   2919  1.1  bouyer 	struct mpii_msg_iocfacts_reply		ifp;
   2920  1.1  bouyer 
   2921  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_iocfacts\n", DEVNAME(sc));
   2922  1.1  bouyer 
   2923  1.1  bouyer 	bzero(&ifq, sizeof(ifq));
   2924  1.1  bouyer 	bzero(&ifp, sizeof(ifp));
   2925  1.1  bouyer 
   2926  1.1  bouyer 	ifq.function = MPII_FUNCTION_IOC_FACTS;
   2927  1.1  bouyer 
   2928  1.1  bouyer 	if (mpii_handshake_send(sc, &ifq, dwordsof(ifq)) != 0) {
   2929  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_iocfacts send failed\n",
   2930  1.1  bouyer 		    DEVNAME(sc));
   2931  1.1  bouyer 		return (1);
   2932  1.1  bouyer 	}
   2933  1.1  bouyer 
   2934  1.1  bouyer 	if (mpii_handshake_recv(sc, &ifp, dwordsof(ifp)) != 0) {
   2935  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_iocfacts recv failed\n",
   2936  1.1  bouyer 		    DEVNAME(sc));
   2937  1.1  bouyer 		return (1);
   2938  1.1  bouyer 	}
   2939  1.1  bouyer 
   2940  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  func: 0x%02x length: %d msgver: %d.%d\n",
   2941  1.1  bouyer 	    DEVNAME(sc), ifp.function, ifp.msg_length,
   2942  1.1  bouyer 	    ifp.msg_version_maj, ifp.msg_version_min);
   2943  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  msgflags: 0x%02x iocnumber: 0x%02x "
   2944  1.1  bouyer 	    "headerver: %d.%d\n", DEVNAME(sc), ifp.msg_flags,
   2945  1.1  bouyer 	    ifp.ioc_number, ifp.header_version_unit,
   2946  1.1  bouyer 	    ifp.header_version_dev);
   2947  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc),
   2948  1.1  bouyer 	    ifp.vp_id, ifp.vf_id);
   2949  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  iocstatus: 0x%04x ioexceptions: 0x%04x\n",
   2950  1.1  bouyer 	    DEVNAME(sc), le16toh(ifp.ioc_status),
   2951  1.1  bouyer 	    le16toh(ifp.ioc_exceptions));
   2952  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  iocloginfo: 0x%08x\n", DEVNAME(sc),
   2953  1.1  bouyer 	    le32toh(ifp.ioc_loginfo));
   2954  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  numberofports: 0x%02x whoinit: 0x%02x "
   2955  1.1  bouyer 	    "maxchaindepth: %d\n", DEVNAME(sc), ifp.number_of_ports,
   2956  1.1  bouyer 	    ifp.whoinit, ifp.max_chain_depth);
   2957  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  productid: 0x%04x requestcredit: 0x%04x\n",
   2958  1.1  bouyer 	    DEVNAME(sc), le16toh(ifp.product_id), le16toh(ifp.request_credit));
   2959  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_capabilities: 0x%08x\n", DEVNAME(sc),
   2960  1.1  bouyer 	    le32toh(ifp.ioc_capabilities));
   2961  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  fw_version: %d.%d fw_version_unit: 0x%02x "
   2962  1.1  bouyer 	    "fw_version_dev: 0x%02x\n", DEVNAME(sc),
   2963  1.1  bouyer 	    ifp.fw_version_maj, ifp.fw_version_min,
   2964  1.1  bouyer 	    ifp.fw_version_unit, ifp.fw_version_dev);
   2965  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  iocrequestframesize: 0x%04x\n",
   2966  1.1  bouyer 	    DEVNAME(sc), le16toh(ifp.ioc_request_frame_size));
   2967  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  maxtargets: 0x%04x "
   2968  1.1  bouyer 	    "maxinitiators: 0x%04x\n", DEVNAME(sc),
   2969  1.1  bouyer 	    le16toh(ifp.max_targets), le16toh(ifp.max_initiators));
   2970  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  maxenclosures: 0x%04x "
   2971  1.1  bouyer 	    "maxsasexpanders: 0x%04x\n", DEVNAME(sc),
   2972  1.1  bouyer 	    le16toh(ifp.max_enclosures), le16toh(ifp.max_sas_expanders));
   2973  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  highprioritycredit: 0x%04x "
   2974  1.1  bouyer 	    "protocolflags: 0x%02x\n", DEVNAME(sc),
   2975  1.1  bouyer 	    le16toh(ifp.high_priority_credit), le16toh(ifp.protocol_flags));
   2976  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  maxvolumes: 0x%02x replyframesize: 0x%02x "
   2977  1.1  bouyer 	    "mrdpqd: 0x%04x\n", DEVNAME(sc), ifp.max_volumes,
   2978  1.1  bouyer 	    ifp.reply_frame_size,
   2979  1.1  bouyer 	    le16toh(ifp.max_reply_descriptor_post_queue_depth));
   2980  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  maxpersistententries: 0x%04x "
   2981  1.1  bouyer 	    "maxdevhandle: 0x%02x\n", DEVNAME(sc),
   2982  1.1  bouyer 	    le16toh(ifp.max_persistent_entries), le16toh(ifp.max_dev_handle));
   2983  1.1  bouyer 
   2984  1.1  bouyer 	sc->sc_maxchdepth = ifp.max_chain_depth;
   2985  1.1  bouyer 	sc->sc_ioc_number = ifp.ioc_number;
   2986  1.1  bouyer 	sc->sc_vf_id = ifp.vf_id;
   2987  1.1  bouyer 
   2988  1.1  bouyer 	sc->sc_num_ports = ifp.number_of_ports;
   2989  1.1  bouyer 	sc->sc_ioc_event_replay = (le32toh(ifp.ioc_capabilities) &
   2990  1.1  bouyer 	    MPII_IOCFACTS_CAPABILITY_EVENT_REPLAY) ? 1 : 0;
   2991  1.1  bouyer 	sc->sc_max_enclosures = le16toh(ifp.max_enclosures);
   2992  1.1  bouyer 	sc->sc_max_expanders = le16toh(ifp.max_sas_expanders);
   2993  1.1  bouyer 	sc->sc_max_volumes = ifp.max_volumes;
   2994  1.1  bouyer 	sc->sc_max_devices = ifp.max_volumes + le16toh(ifp.max_targets);
   2995  1.1  bouyer 	sc->sc_num_channels = 1;
   2996  1.1  bouyer 
   2997  1.1  bouyer 	if (ISSET(le32toh(ifp.ioc_capabilities),
   2998  1.1  bouyer 	    MPII_IOCFACTS_CAPABILITY_INTEGRATED_RAID))
   2999  1.1  bouyer 		SET(sc->sc_flags, MPII_F_RAID);
   3000  1.1  bouyer 
   3001  1.1  bouyer 	sc->sc_request_depth = MIN(le16toh(ifp.request_credit),
   3002  1.1  bouyer 	    MPII_MAX_REQUEST_CREDIT);
   3003  1.1  bouyer 
   3004  1.1  bouyer 	/* should not be multiple of 16 */
   3005  1.1  bouyer 	sc->sc_num_reply_frames = sc->sc_request_depth + 32;
   3006  1.1  bouyer 	if (!(sc->sc_num_reply_frames % 16))
   3007  1.1  bouyer 		sc->sc_num_reply_frames--;
   3008  1.1  bouyer 
   3009  1.1  bouyer 	/* must be multiple of 16 */
   3010  1.1  bouyer 	sc->sc_reply_free_qdepth = sc->sc_num_reply_frames +
   3011  1.1  bouyer 	    (16 - (sc->sc_num_reply_frames % 16));
   3012  1.1  bouyer 	sc->sc_reply_post_qdepth = ((sc->sc_request_depth +
   3013  1.1  bouyer 	    sc->sc_num_reply_frames + 1 + 15) / 16) * 16;
   3014  1.1  bouyer 
   3015  1.1  bouyer 	if (sc->sc_reply_post_qdepth >
   3016  1.1  bouyer 	    ifp.max_reply_descriptor_post_queue_depth)
   3017  1.1  bouyer 		sc->sc_reply_post_qdepth =
   3018  1.1  bouyer 		    ifp.max_reply_descriptor_post_queue_depth;
   3019  1.1  bouyer 
   3020  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s: sc_request_depth: %d "
   3021  1.1  bouyer 	    "sc_num_reply_frames: %d sc_reply_free_qdepth: %d "
   3022  1.1  bouyer 	    "sc_reply_post_qdepth: %d\n", DEVNAME(sc), sc->sc_request_depth,
   3023  1.1  bouyer 	    sc->sc_num_reply_frames, sc->sc_reply_free_qdepth,
   3024  1.1  bouyer 	    sc->sc_reply_post_qdepth);
   3025  1.1  bouyer 
   3026  1.1  bouyer 	/*
   3027  1.1  bouyer 	 * you can fit sg elements on the end of the io cmd if they fit in the
   3028  1.1  bouyer 	 * request frame size.
   3029  1.1  bouyer 	 */
   3030  1.1  bouyer 
   3031  1.1  bouyer 	sc->sc_first_sgl_len = ((le16toh(ifp.ioc_request_frame_size) * 4) -
   3032  1.1  bouyer 	    sizeof(struct mpii_msg_scsi_io)) / sizeof(struct mpii_sge);
   3033  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:   first sgl len: %d\n", DEVNAME(sc),
   3034  1.1  bouyer 	    sc->sc_first_sgl_len);
   3035  1.1  bouyer 
   3036  1.1  bouyer 	sc->sc_chain_len = (le16toh(ifp.ioc_request_frame_size) * 4) /
   3037  1.1  bouyer 	    sizeof(struct mpii_sge);
   3038  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:   chain len: %d\n", DEVNAME(sc),
   3039  1.1  bouyer 	    sc->sc_chain_len);
   3040  1.1  bouyer 
   3041  1.1  bouyer 	/* the sgl tailing the io cmd loses an entry to the chain element. */
   3042  1.1  bouyer 	sc->sc_max_sgl_len = MPII_MAX_SGL - 1;
   3043  1.1  bouyer 	/* the sgl chains lose an entry for each chain element */
   3044  1.1  bouyer 	sc->sc_max_sgl_len -= (MPII_MAX_SGL - sc->sc_first_sgl_len) /
   3045  1.1  bouyer 	    sc->sc_chain_len;
   3046  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:   max sgl len: %d\n", DEVNAME(sc),
   3047  1.1  bouyer 	    sc->sc_max_sgl_len);
   3048  1.1  bouyer 
   3049  1.1  bouyer 	/* XXX we're ignoring the max chain depth */
   3050  1.1  bouyer 
   3051  1.1  bouyer 	return(0);
   3052  1.1  bouyer 
   3053  1.1  bouyer }
   3054  1.1  bouyer 
   3055  1.1  bouyer static int
   3056  1.1  bouyer mpii_iocinit(struct mpii_softc *sc)
   3057  1.1  bouyer {
   3058  1.1  bouyer 	struct mpii_msg_iocinit_request		iiq;
   3059  1.1  bouyer 	struct mpii_msg_iocinit_reply		iip;
   3060  1.1  bouyer 	u_int32_t				hi_addr;
   3061  1.1  bouyer 
   3062  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_iocinit\n", DEVNAME(sc));
   3063  1.1  bouyer 
   3064  1.1  bouyer 	bzero(&iiq, sizeof(iiq));
   3065  1.1  bouyer 	bzero(&iip, sizeof(iip));
   3066  1.1  bouyer 
   3067  1.1  bouyer 	iiq.function = MPII_FUNCTION_IOC_INIT;
   3068  1.1  bouyer 	iiq.whoinit = MPII_WHOINIT_HOST_DRIVER;
   3069  1.1  bouyer 
   3070  1.1  bouyer 	/* XXX JPG do something about vf_id */
   3071  1.1  bouyer 	iiq.vf_id = 0;
   3072  1.1  bouyer 
   3073  1.1  bouyer 	iiq.msg_version_maj = 0x02;
   3074  1.1  bouyer 	iiq.msg_version_min = 0x00;
   3075  1.1  bouyer 
   3076  1.1  bouyer 	/* XXX JPG ensure compliance with some level and hard-code? */
   3077  1.1  bouyer 	iiq.hdr_version_unit = 0x00;
   3078  1.1  bouyer 	iiq.hdr_version_dev = 0x00;
   3079  1.1  bouyer 
   3080  1.1  bouyer 	iiq.system_request_frame_size = htole16(MPII_REQUEST_SIZE / 4);
   3081  1.1  bouyer 
   3082  1.1  bouyer 	iiq.reply_descriptor_post_queue_depth =
   3083  1.1  bouyer 	    htole16(sc->sc_reply_post_qdepth);
   3084  1.1  bouyer 
   3085  1.1  bouyer 	iiq.reply_free_queue_depth = htole16(sc->sc_reply_free_qdepth);
   3086  1.1  bouyer 
   3087  1.1  bouyer 	hi_addr = (u_int32_t)((u_int64_t)MPII_DMA_DVA(sc->sc_requests) >> 32);
   3088  1.1  bouyer 	iiq.sense_buffer_address_high = htole32(hi_addr);
   3089  1.1  bouyer 
   3090  1.1  bouyer 	hi_addr = (u_int32_t)
   3091  1.1  bouyer 	    ((u_int64_t)MPII_DMA_DVA(sc->sc_replies) >> 32);
   3092  1.1  bouyer 	iiq.system_reply_address_high = htole32(hi_addr);
   3093  1.1  bouyer 
   3094  1.1  bouyer 	iiq.system_request_frame_base_address =
   3095  1.1  bouyer 	    (u_int64_t)MPII_DMA_DVA(sc->sc_requests);
   3096  1.1  bouyer 
   3097  1.1  bouyer 	iiq.reply_descriptor_post_queue_address =
   3098  1.1  bouyer 	    (u_int64_t)MPII_DMA_DVA(sc->sc_reply_postq);
   3099  1.1  bouyer 
   3100  1.1  bouyer 	iiq.reply_free_queue_address =
   3101  1.1  bouyer 	    (u_int64_t)MPII_DMA_DVA(sc->sc_reply_freeq);
   3102  1.1  bouyer 
   3103  1.1  bouyer 	if (mpii_handshake_send(sc, &iiq, dwordsof(iiq)) != 0) {
   3104  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_iocinit send failed\n",
   3105  1.1  bouyer 		    DEVNAME(sc));
   3106  1.1  bouyer 		return (1);
   3107  1.1  bouyer 	}
   3108  1.1  bouyer 
   3109  1.1  bouyer 	if (mpii_handshake_recv(sc, &iip, dwordsof(iip)) != 0) {
   3110  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_iocinit recv failed\n",
   3111  1.1  bouyer 		    DEVNAME(sc));
   3112  1.1  bouyer 		return (1);
   3113  1.1  bouyer 	}
   3114  1.1  bouyer 
   3115  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  function: 0x%02x msg_length: %d "
   3116  1.1  bouyer 	    "whoinit: 0x%02x\n", DEVNAME(sc), iip.function,
   3117  1.1  bouyer 	    iip.msg_length, iip.whoinit);
   3118  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  msg_flags: 0x%02x\n", DEVNAME(sc),
   3119  1.1  bouyer 	    iip.msg_flags);
   3120  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  vf_id: 0x%02x vp_id: 0x%02x\n", DEVNAME(sc),
   3121  1.1  bouyer 	    iip.vf_id, iip.vp_id);
   3122  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
   3123  1.1  bouyer 	    le16toh(iip.ioc_status));
   3124  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
   3125  1.1  bouyer 	    le32toh(iip.ioc_loginfo));
   3126  1.1  bouyer 
   3127  1.1  bouyer 	if ((iip.ioc_status != MPII_IOCSTATUS_SUCCESS) || (iip.ioc_loginfo))
   3128  1.1  bouyer 		return (1);
   3129  1.1  bouyer 
   3130  1.1  bouyer 	return (0);
   3131  1.1  bouyer }
   3132  1.1  bouyer 
   3133  1.1  bouyer static void
   3134  1.1  bouyer mpii_push_reply(struct mpii_softc *sc, struct mpii_rcb *rcb)
   3135  1.1  bouyer {
   3136  1.1  bouyer 	u_int32_t		*rfp;
   3137  1.1  bouyer 
   3138  1.1  bouyer 	if (rcb == NULL)
   3139  1.1  bouyer 		return;
   3140  1.1  bouyer 
   3141  1.1  bouyer 	rfp = MPII_DMA_KVA(sc->sc_reply_freeq);
   3142  1.1  bouyer 	rfp[sc->sc_reply_free_host_index] = rcb->rcb_reply_dva;
   3143  1.1  bouyer 
   3144  1.1  bouyer 	sc->sc_reply_free_host_index = (sc->sc_reply_free_host_index + 1) %
   3145  1.1  bouyer 	    sc->sc_reply_free_qdepth;
   3146  1.1  bouyer 
   3147  1.1  bouyer 	mpii_write_reply_free(sc, sc->sc_reply_free_host_index);
   3148  1.1  bouyer }
   3149  1.1  bouyer 
   3150  1.1  bouyer static int
   3151  1.1  bouyer mpii_portfacts(struct mpii_softc *sc)
   3152  1.1  bouyer {
   3153  1.1  bouyer 	struct mpii_msg_portfacts_request	*pfq;
   3154  1.1  bouyer 	struct mpii_msg_portfacts_reply		*pfp;
   3155  1.1  bouyer 	struct mpii_ccb				*ccb;
   3156  1.1  bouyer 	int					rv = 1;
   3157  1.1  bouyer 
   3158  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_portfacts\n", DEVNAME(sc));
   3159  1.1  bouyer 
   3160  1.1  bouyer 	ccb = mpii_get_ccb(sc, 0);
   3161  1.1  bouyer 	if (ccb == NULL) {
   3162  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_portfacts mpii_get_ccb fail\n",
   3163  1.1  bouyer 		    DEVNAME(sc));
   3164  1.1  bouyer 		return (rv);
   3165  1.1  bouyer 	}
   3166  1.1  bouyer 
   3167  1.1  bouyer 	ccb->ccb_done = mpii_empty_done;
   3168  1.1  bouyer 	pfq = ccb->ccb_cmd;
   3169  1.1  bouyer 
   3170  1.1  bouyer 	bzero(pfq, sizeof(*pfq));
   3171  1.1  bouyer 
   3172  1.1  bouyer 	pfq->function = MPII_FUNCTION_PORT_FACTS;
   3173  1.1  bouyer 	pfq->chain_offset = 0;
   3174  1.1  bouyer 	pfq->msg_flags = 0;
   3175  1.1  bouyer 	pfq->port_number = 0;
   3176  1.1  bouyer 	pfq->vp_id = 0;
   3177  1.1  bouyer 	pfq->vf_id = 0;
   3178  1.1  bouyer 
   3179  1.1  bouyer 	if (mpii_poll(sc, ccb) != 0) {
   3180  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_portfacts poll\n",
   3181  1.1  bouyer 		    DEVNAME(sc));
   3182  1.1  bouyer 		goto err;
   3183  1.1  bouyer 	}
   3184  1.1  bouyer 
   3185  1.1  bouyer 	if (ccb->ccb_rcb == NULL) {
   3186  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: empty portfacts reply\n",
   3187  1.1  bouyer 		    DEVNAME(sc));
   3188  1.1  bouyer 		goto err;
   3189  1.1  bouyer 	}
   3190  1.1  bouyer 
   3191  1.1  bouyer 	pfp = ccb->ccb_rcb->rcb_reply;
   3192  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s   pfp: %p\n", DEVNAME(sc), pfp);
   3193  1.1  bouyer 
   3194  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  function: 0x%02x msg_length: %d\n",
   3195  1.1  bouyer 	    DEVNAME(sc), pfp->function, pfp->msg_length);
   3196  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  msg_flags: 0x%02x port_number: %d\n",
   3197  1.1  bouyer 	    DEVNAME(sc), pfp->msg_flags, pfp->port_number);
   3198  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  vf_id: 0x%02x vp_id: 0x%02x\n",
   3199  1.1  bouyer 	    DEVNAME(sc), pfp->vf_id, pfp->vp_id);
   3200  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
   3201  1.1  bouyer 	    le16toh(pfp->ioc_status));
   3202  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
   3203  1.1  bouyer 	    le32toh(pfp->ioc_loginfo));
   3204  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  port_type: 0x%02x\n", DEVNAME(sc),
   3205  1.1  bouyer 	    pfp->port_type);
   3206  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  max_posted_cmd_buffers: %d\n", DEVNAME(sc),
   3207  1.1  bouyer 	    le16toh(pfp->max_posted_cmd_buffers));
   3208  1.1  bouyer 
   3209  1.1  bouyer 	sc->sc_porttype = pfp->port_type;
   3210  1.1  bouyer 
   3211  1.1  bouyer 	mpii_push_reply(sc, ccb->ccb_rcb);
   3212  1.1  bouyer 	rv = 0;
   3213  1.1  bouyer err:
   3214  1.1  bouyer 	mpii_put_ccb(sc, ccb);
   3215  1.1  bouyer 
   3216  1.1  bouyer 	return (rv);
   3217  1.1  bouyer }
   3218  1.1  bouyer 
   3219  1.1  bouyer static void
   3220  1.1  bouyer mpii_eventack(struct work *wk, void *cookie)
   3221  1.1  bouyer {
   3222  1.1  bouyer 	struct mpii_softc			*sc = cookie;
   3223  1.1  bouyer 	struct mpii_ccb				*ccb;
   3224  1.1  bouyer 	struct mpii_rcb				*rcb = (void *)wk;
   3225  1.1  bouyer 	struct mpii_msg_event_reply		*enp;
   3226  1.1  bouyer 	struct mpii_msg_eventack_request	*eaq;
   3227  1.1  bouyer 
   3228  1.1  bouyer 	ccb = mpii_get_ccb(sc, 0);
   3229  1.1  bouyer 
   3230  1.1  bouyer 	enp = (struct mpii_msg_event_reply *)rcb->rcb_reply;
   3231  1.1  bouyer 
   3232  1.1  bouyer 	ccb->ccb_done = mpii_eventack_done;
   3233  1.1  bouyer 	eaq = ccb->ccb_cmd;
   3234  1.1  bouyer 
   3235  1.1  bouyer 	eaq->function = MPII_FUNCTION_EVENT_ACK;
   3236  1.1  bouyer 
   3237  1.1  bouyer 	eaq->event = enp->event;
   3238  1.1  bouyer 	eaq->event_context = enp->event_context;
   3239  1.1  bouyer 
   3240  1.1  bouyer 	mpii_push_reply(sc, rcb);
   3241  1.1  bouyer 
   3242  1.1  bouyer 	mpii_start(sc, ccb);
   3243  1.1  bouyer 
   3244  1.1  bouyer }
   3245  1.1  bouyer 
   3246  1.1  bouyer static void
   3247  1.1  bouyer mpii_eventack_done(struct mpii_ccb *ccb)
   3248  1.1  bouyer {
   3249  1.1  bouyer 	struct mpii_softc			*sc = ccb->ccb_sc;
   3250  1.1  bouyer 
   3251  1.1  bouyer 	DNPRINTF(MPII_D_EVT, "%s: event ack done\n", DEVNAME(sc));
   3252  1.1  bouyer 
   3253  1.1  bouyer 	mpii_push_reply(sc, ccb->ccb_rcb);
   3254  1.1  bouyer 	mpii_put_ccb(sc, ccb);
   3255  1.1  bouyer }
   3256  1.1  bouyer 
   3257  1.1  bouyer static int
   3258  1.1  bouyer mpii_portenable(struct mpii_softc *sc)
   3259  1.1  bouyer {
   3260  1.1  bouyer 	struct mpii_msg_portenable_request	*peq;
   3261  1.1  bouyer 	struct mpii_msg_portenable_repy		*pep;
   3262  1.1  bouyer 	struct mpii_ccb				*ccb;
   3263  1.1  bouyer 
   3264  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_portenable\n", DEVNAME(sc));
   3265  1.1  bouyer 
   3266  1.1  bouyer 	ccb = mpii_get_ccb(sc, 0);
   3267  1.1  bouyer 	if (ccb == NULL) {
   3268  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_portenable ccb_get\n",
   3269  1.1  bouyer 		    DEVNAME(sc));
   3270  1.1  bouyer 		return (1);
   3271  1.1  bouyer 	}
   3272  1.1  bouyer 
   3273  1.1  bouyer 	ccb->ccb_done = mpii_empty_done;
   3274  1.1  bouyer 	peq = ccb->ccb_cmd;
   3275  1.1  bouyer 
   3276  1.1  bouyer 	peq->function = MPII_FUNCTION_PORT_ENABLE;
   3277  1.1  bouyer 	peq->vf_id = sc->sc_vf_id;
   3278  1.1  bouyer 
   3279  1.1  bouyer 	if (mpii_poll(sc, ccb) != 0) {
   3280  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_portenable poll\n",
   3281  1.1  bouyer 		    DEVNAME(sc));
   3282  1.1  bouyer 		return (1);
   3283  1.1  bouyer 	}
   3284  1.1  bouyer 
   3285  1.1  bouyer 	if (ccb->ccb_rcb == NULL) {
   3286  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: empty portenable reply\n",
   3287  1.1  bouyer 		    DEVNAME(sc));
   3288  1.1  bouyer 		return (1);
   3289  1.1  bouyer 	}
   3290  1.1  bouyer 	pep = ccb->ccb_rcb->rcb_reply;
   3291  1.1  bouyer 
   3292  1.1  bouyer 	mpii_push_reply(sc, ccb->ccb_rcb);
   3293  1.1  bouyer 	mpii_put_ccb(sc, ccb);
   3294  1.1  bouyer 
   3295  1.1  bouyer 	return (0);
   3296  1.1  bouyer }
   3297  1.1  bouyer 
   3298  1.1  bouyer static int
   3299  1.1  bouyer mpii_cfg_coalescing(struct mpii_softc *sc)
   3300  1.1  bouyer {
   3301  1.1  bouyer 	struct mpii_cfg_hdr		hdr;
   3302  1.1  bouyer 	struct mpii_cfg_ioc_pg1		pg;
   3303  1.1  bouyer 
   3304  1.1  bouyer 	if (mpii_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_IOC, 1, 0,
   3305  1.1  bouyer 	    &hdr) != 0) {
   3306  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: unable to fetch IOC page 1 "
   3307  1.1  bouyer 		    "header\n", DEVNAME(sc));
   3308  1.1  bouyer 		return (1);
   3309  1.1  bouyer 	}
   3310  1.1  bouyer 
   3311  1.1  bouyer 	if (mpii_cfg_page(sc, 0, &hdr, 1, &pg, sizeof(pg)) != 0) {
   3312  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: unable to fetch IOC page 1\n"
   3313  1.1  bouyer 		    "page 1\n", DEVNAME(sc));
   3314  1.1  bouyer 		return (1);
   3315  1.1  bouyer 	}
   3316  1.1  bouyer 
   3317  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s: IOC page 1\n", DEVNAME(sc));
   3318  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  flags: 0x08%x\n", DEVNAME(sc),
   3319  1.1  bouyer 	    le32toh(pg.flags));
   3320  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  coalescing_timeout: %d\n", DEVNAME(sc),
   3321  1.1  bouyer 	    le32toh(pg.coalescing_timeout));
   3322  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  coalescing_depth: %d pci_slot_num: %d\n",
   3323  1.1  bouyer 	    DEVNAME(sc), pg.coalescing_timeout, pg.pci_slot_num);
   3324  1.1  bouyer 
   3325  1.1  bouyer 	if (!ISSET(le32toh(pg.flags), MPII_CFG_IOC_1_REPLY_COALESCING))
   3326  1.1  bouyer 		return (0);
   3327  1.1  bouyer 
   3328  1.1  bouyer 	CLR(pg.flags, htole32(MPII_CFG_IOC_1_REPLY_COALESCING));
   3329  1.1  bouyer 	if (mpii_cfg_page(sc, 0, &hdr, 0, &pg, sizeof(pg)) != 0) {
   3330  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: unable to clear coalescing\n",
   3331  1.1  bouyer 		    DEVNAME(sc));
   3332  1.1  bouyer 		return (1);
   3333  1.1  bouyer 	}
   3334  1.1  bouyer 
   3335  1.1  bouyer 	return (0);
   3336  1.1  bouyer }
   3337  1.1  bouyer 
   3338  1.1  bouyer #define MPII_EVENT_MASKALL(enq)		do {			\
   3339  1.1  bouyer 		enq->event_masks[0] = 0xffffffff;		\
   3340  1.1  bouyer 		enq->event_masks[1] = 0xffffffff;		\
   3341  1.1  bouyer 		enq->event_masks[2] = 0xffffffff;		\
   3342  1.1  bouyer 		enq->event_masks[3] = 0xffffffff;		\
   3343  1.1  bouyer 	} while (0)
   3344  1.1  bouyer 
   3345  1.1  bouyer #define MPII_EVENT_UNMASK(enq, evt)	do {			\
   3346  1.1  bouyer 		enq->event_masks[evt / 32] &=			\
   3347  1.1  bouyer 		    htole32(~(1 << (evt % 32)));		\
   3348  1.1  bouyer 	} while (0)
   3349  1.1  bouyer 
   3350  1.1  bouyer static int
   3351  1.1  bouyer mpii_eventnotify(struct mpii_softc *sc)
   3352  1.1  bouyer {
   3353  1.1  bouyer 	struct mpii_msg_event_request		*enq;
   3354  1.1  bouyer 	struct mpii_ccb				*ccb;
   3355  1.1  bouyer 
   3356  1.1  bouyer 	ccb = mpii_get_ccb(sc, 0);
   3357  1.1  bouyer 	if (ccb == NULL) {
   3358  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_eventnotify ccb_get\n",
   3359  1.1  bouyer 		    DEVNAME(sc));
   3360  1.1  bouyer 		return (1);
   3361  1.1  bouyer 	}
   3362  1.1  bouyer 
   3363  1.1  bouyer 	ccb->ccb_done = mpii_eventnotify_done;
   3364  1.1  bouyer 	enq = ccb->ccb_cmd;
   3365  1.1  bouyer 
   3366  1.1  bouyer 	enq->function = MPII_FUNCTION_EVENT_NOTIFICATION;
   3367  1.1  bouyer 
   3368  1.1  bouyer 	/*
   3369  1.1  bouyer 	 * Enable reporting of the following events:
   3370  1.1  bouyer 	 *
   3371  1.1  bouyer 	 * MPII_EVENT_SAS_DISCOVERY
   3372  1.1  bouyer 	 * MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST
   3373  1.1  bouyer 	 * MPII_EVENT_SAS_DEVICE_STATUS_CHANGE
   3374  1.1  bouyer 	 * MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE
   3375  1.1  bouyer 	 * MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST
   3376  1.1  bouyer 	 * MPII_EVENT_IR_VOLUME
   3377  1.1  bouyer 	 * MPII_EVENT_IR_PHYSICAL_DISK
   3378  1.1  bouyer 	 * MPII_EVENT_IR_OPERATION_STATUS
   3379  1.1  bouyer 	 */
   3380  1.1  bouyer 
   3381  1.1  bouyer 	MPII_EVENT_MASKALL(enq);
   3382  1.1  bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_DISCOVERY);
   3383  1.1  bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
   3384  1.1  bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_DEVICE_STATUS_CHANGE);
   3385  1.1  bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE);
   3386  1.1  bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST);
   3387  1.1  bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_VOLUME);
   3388  1.1  bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_PHYSICAL_DISK);
   3389  1.1  bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_OPERATION_STATUS);
   3390  1.1  bouyer 
   3391  1.1  bouyer 	mpii_start(sc, ccb);
   3392  1.1  bouyer 
   3393  1.1  bouyer 	return (0);
   3394  1.1  bouyer }
   3395  1.1  bouyer 
   3396  1.1  bouyer static void
   3397  1.1  bouyer mpii_eventnotify_done(struct mpii_ccb *ccb)
   3398  1.1  bouyer {
   3399  1.1  bouyer 	struct mpii_softc			*sc = ccb->ccb_sc;
   3400  1.1  bouyer 	struct mpii_rcb				*rcb = ccb->ccb_rcb;
   3401  1.1  bouyer 
   3402  1.1  bouyer 	DNPRINTF(MPII_D_EVT, "%s: mpii_eventnotify_done\n", DEVNAME(sc));
   3403  1.1  bouyer 
   3404  1.1  bouyer 	mpii_put_ccb(sc, ccb);
   3405  1.1  bouyer 	mpii_event_process(sc, rcb);
   3406  1.1  bouyer }
   3407  1.1  bouyer 
   3408  1.1  bouyer static void
   3409  1.1  bouyer mpii_event_raid(struct mpii_softc *sc, struct mpii_msg_event_reply *enp)
   3410  1.1  bouyer {
   3411  1.1  bouyer 	struct mpii_evt_ir_cfg_change_list	*ccl;
   3412  1.1  bouyer 	struct mpii_evt_ir_cfg_element		*ce;
   3413  1.1  bouyer 	struct mpii_device			*dev;
   3414  1.1  bouyer 	u_int16_t				type;
   3415  1.1  bouyer 	int					i;
   3416  1.1  bouyer 
   3417  1.1  bouyer 	ccl = (struct mpii_evt_ir_cfg_change_list *)(enp + 1);
   3418  1.1  bouyer 
   3419  1.1  bouyer 	if (ccl->num_elements == 0)
   3420  1.1  bouyer 		return;
   3421  1.1  bouyer 	if (ISSET(le32toh(ccl->flags), MPII_EVT_IR_CFG_CHANGE_LIST_FOREIGN))
   3422  1.1  bouyer 		/* bail on foreign configurations */
   3423  1.1  bouyer 		return;
   3424  1.1  bouyer 
   3425  1.1  bouyer 	ce = (struct mpii_evt_ir_cfg_element *)(ccl + 1);
   3426  1.1  bouyer 
   3427  1.1  bouyer 	for (i = 0; i < ccl->num_elements; i++, ce++) {
   3428  1.1  bouyer 		type = (le16toh(ce->element_flags) &
   3429  1.1  bouyer 		    MPII_EVT_IR_CFG_ELEMENT_TYPE_MASK);
   3430  1.1  bouyer 
   3431  1.1  bouyer 		switch (type) {
   3432  1.1  bouyer 		case MPII_EVT_IR_CFG_ELEMENT_TYPE_VOLUME:
   3433  1.1  bouyer 			switch (ce->reason_code) {
   3434  1.1  bouyer 			case MPII_EVT_IR_CFG_ELEMENT_RC_ADDED:
   3435  1.1  bouyer 			case MPII_EVT_IR_CFG_ELEMENT_RC_VOLUME_CREATED:
   3436  1.1  bouyer 				if (mpii_find_dev(sc,
   3437  1.1  bouyer 				    le16toh(ce->vol_dev_handle))) {
   3438  1.1  bouyer 					printf("%s: device %#x is already "
   3439  1.1  bouyer 					    "configured\n", DEVNAME(sc),
   3440  1.1  bouyer 					    le16toh(ce->vol_dev_handle));
   3441  1.1  bouyer 					break;
   3442  1.1  bouyer 				}
   3443  1.1  bouyer 				dev = malloc(sizeof(*dev), M_DEVBUF,
   3444  1.1  bouyer 				    M_NOWAIT | M_ZERO);
   3445  1.1  bouyer 				if (!dev) {
   3446  1.1  bouyer 					printf("%s: failed to allocate a "
   3447  1.1  bouyer 				    	    "device structure\n", DEVNAME(sc));
   3448  1.1  bouyer 					break;
   3449  1.1  bouyer 				}
   3450  1.1  bouyer 				SET(dev->flags, MPII_DF_VOLUME);
   3451  1.1  bouyer 				dev->slot = sc->sc_vd_id_low;
   3452  1.1  bouyer 				dev->dev_handle = le16toh(ce->vol_dev_handle);
   3453  1.1  bouyer 				if (mpii_insert_dev(sc, dev)) {
   3454  1.1  bouyer 					free(dev, M_DEVBUF);
   3455  1.1  bouyer 					break;
   3456  1.1  bouyer 				}
   3457  1.1  bouyer 				mpii_cache_enable(sc, dev);
   3458  1.1  bouyer 				sc->sc_vd_count++;
   3459  1.1  bouyer 				break;
   3460  1.1  bouyer 			case MPII_EVT_IR_CFG_ELEMENT_RC_REMOVED:
   3461  1.1  bouyer 			case MPII_EVT_IR_CFG_ELEMENT_RC_VOLUME_DELETED:
   3462  1.1  bouyer 				if (!(dev = mpii_find_dev(sc,
   3463  1.1  bouyer 				    le16toh(ce->vol_dev_handle))))
   3464  1.1  bouyer 					break;
   3465  1.1  bouyer 				mpii_remove_dev(sc, dev);
   3466  1.1  bouyer 				sc->sc_vd_count--;
   3467  1.1  bouyer 				break;
   3468  1.1  bouyer 			}
   3469  1.1  bouyer 			break;
   3470  1.1  bouyer 		case MPII_EVT_IR_CFG_ELEMENT_TYPE_VOLUME_DISK:
   3471  1.1  bouyer 			if (ce->reason_code ==
   3472  1.1  bouyer 			    MPII_EVT_IR_CFG_ELEMENT_RC_PD_CREATED ||
   3473  1.1  bouyer 			    ce->reason_code ==
   3474  1.1  bouyer 			    MPII_EVT_IR_CFG_ELEMENT_RC_HIDE) {
   3475  1.1  bouyer 				/* there should be an underlying sas drive */
   3476  1.1  bouyer 				if (!(dev = mpii_find_dev(sc,
   3477  1.1  bouyer 				    le16toh(ce->phys_disk_dev_handle))))
   3478  1.1  bouyer 					break;
   3479  1.1  bouyer 				/* promoted from a hot spare? */
   3480  1.1  bouyer 				CLR(dev->flags, MPII_DF_HOT_SPARE);
   3481  1.1  bouyer 				SET(dev->flags, MPII_DF_VOLUME_DISK |
   3482  1.1  bouyer 				    MPII_DF_HIDDEN);
   3483  1.1  bouyer 			}
   3484  1.1  bouyer 			break;
   3485  1.1  bouyer 		case MPII_EVT_IR_CFG_ELEMENT_TYPE_HOT_SPARE:
   3486  1.1  bouyer 			if (ce->reason_code ==
   3487  1.1  bouyer 			    MPII_EVT_IR_CFG_ELEMENT_RC_HIDE) {
   3488  1.1  bouyer 				/* there should be an underlying sas drive */
   3489  1.1  bouyer 				if (!(dev = mpii_find_dev(sc,
   3490  1.1  bouyer 				    le16toh(ce->phys_disk_dev_handle))))
   3491  1.1  bouyer 					break;
   3492  1.1  bouyer 				SET(dev->flags, MPII_DF_HOT_SPARE |
   3493  1.1  bouyer 				    MPII_DF_HIDDEN);
   3494  1.1  bouyer 			}
   3495  1.1  bouyer 			break;
   3496  1.1  bouyer 		}
   3497  1.1  bouyer 	}
   3498  1.1  bouyer }
   3499  1.1  bouyer 
   3500  1.1  bouyer static void
   3501  1.1  bouyer mpii_event_sas(struct mpii_softc *sc, struct mpii_msg_event_reply *enp)
   3502  1.1  bouyer {
   3503  1.1  bouyer 	struct mpii_evt_sas_tcl		*tcl;
   3504  1.1  bouyer 	struct mpii_evt_phy_entry	*pe;
   3505  1.1  bouyer 	struct mpii_device		*dev;
   3506  1.1  bouyer 	int				i;
   3507  1.1  bouyer 
   3508  1.1  bouyer 	tcl = (struct mpii_evt_sas_tcl *)(enp + 1);
   3509  1.1  bouyer 
   3510  1.1  bouyer 	if (tcl->num_entries == 0)
   3511  1.1  bouyer 		return;
   3512  1.1  bouyer 
   3513  1.1  bouyer 	pe = (struct mpii_evt_phy_entry *)(tcl + 1);
   3514  1.1  bouyer 
   3515  1.1  bouyer 	for (i = 0; i < tcl->num_entries; i++, pe++) {
   3516  1.1  bouyer 		switch (pe->phy_status & MPII_EVENT_SAS_TOPO_PS_RC_MASK) {
   3517  1.1  bouyer 		case MPII_EVENT_SAS_TOPO_PS_RC_ADDED:
   3518  1.1  bouyer 			if (mpii_find_dev(sc, le16toh(pe->dev_handle))) {
   3519  1.1  bouyer 				printf("%s: device %#x is already "
   3520  1.1  bouyer 				    "configured\n", DEVNAME(sc),
   3521  1.1  bouyer 				    le16toh(pe->dev_handle));
   3522  1.1  bouyer 				break;
   3523  1.1  bouyer 			}
   3524  1.1  bouyer 			dev = malloc(sizeof(*dev), M_DEVBUF, M_NOWAIT | M_ZERO);
   3525  1.1  bouyer 			if (!dev) {
   3526  1.1  bouyer 				printf("%s: failed to allocate a "
   3527  1.1  bouyer 				    "device structure\n", DEVNAME(sc));
   3528  1.1  bouyer 				break;
   3529  1.1  bouyer 			}
   3530  1.1  bouyer 			dev->slot = sc->sc_pd_id_start + tcl->start_phy_num + i;
   3531  1.1  bouyer 			dev->dev_handle = le16toh(pe->dev_handle);
   3532  1.1  bouyer 			dev->phy_num = tcl->start_phy_num + i;
   3533  1.1  bouyer 			if (tcl->enclosure_handle)
   3534  1.1  bouyer 				dev->physical_port = tcl->physical_port;
   3535  1.1  bouyer 			dev->enclosure = le16toh(tcl->enclosure_handle);
   3536  1.1  bouyer 			dev->expander = le16toh(tcl->expander_handle);
   3537  1.1  bouyer 			if (mpii_insert_dev(sc, dev)) {
   3538  1.1  bouyer 				free(dev, M_DEVBUF);
   3539  1.1  bouyer 				break;
   3540  1.1  bouyer 			}
   3541  1.1  bouyer 			break;
   3542  1.1  bouyer 		case MPII_EVENT_SAS_TOPO_PS_RC_MISSING:
   3543  1.1  bouyer 			if (!(dev = mpii_find_dev(sc,
   3544  1.1  bouyer 			    le16toh(pe->dev_handle))))
   3545  1.1  bouyer 				break;
   3546  1.1  bouyer 			mpii_remove_dev(sc, dev);
   3547  1.1  bouyer #if 0
   3548  1.1  bouyer 			if (sc->sc_scsibus) {
   3549  1.1  bouyer 				SET(dev->flags, MPII_DF_DETACH);
   3550  1.1  bouyer 				scsi_activate(sc->sc_scsibus, dev->slot, -1,
   3551  1.1  bouyer 				    DVACT_DEACTIVATE);
   3552  1.1  bouyer 				if (scsi_task(mpii_event_defer, sc,
   3553  1.1  bouyer 				    dev, 0) != 0)
   3554  1.1  bouyer 					printf("%s: unable to run device "
   3555  1.1  bouyer 					    "detachment routine\n",
   3556  1.1  bouyer 					    DEVNAME(sc));
   3557  1.1  bouyer 			}
   3558  1.1  bouyer #else
   3559  1.1  bouyer 			mpii_event_defer(sc, dev);
   3560  1.1  bouyer #endif /* XXX */
   3561  1.1  bouyer 			break;
   3562  1.1  bouyer 		}
   3563  1.1  bouyer 	}
   3564  1.1  bouyer }
   3565  1.1  bouyer 
   3566  1.1  bouyer static void
   3567  1.1  bouyer mpii_event_process(struct mpii_softc *sc, struct mpii_rcb *rcb)
   3568  1.1  bouyer {
   3569  1.1  bouyer 	struct mpii_msg_event_reply		*enp;
   3570  1.1  bouyer 
   3571  1.1  bouyer 	enp = (struct mpii_msg_event_reply *)rcb->rcb_reply;
   3572  1.1  bouyer 
   3573  1.1  bouyer 	DNPRINTF(MPII_D_EVT, "%s: mpii_event_process: %#x\n", DEVNAME(sc),
   3574  1.1  bouyer 	    le32toh(enp->event));
   3575  1.1  bouyer 
   3576  1.1  bouyer 	switch (le32toh(enp->event)) {
   3577  1.1  bouyer 	case MPII_EVENT_EVENT_CHANGE:
   3578  1.1  bouyer 		/* should be properly ignored */
   3579  1.1  bouyer 		break;
   3580  1.1  bouyer 	case MPII_EVENT_SAS_DISCOVERY: {
   3581  1.1  bouyer 		struct mpii_evt_sas_discovery	*esd =
   3582  1.1  bouyer 		    (struct mpii_evt_sas_discovery *)(enp + 1);
   3583  1.1  bouyer 
   3584  1.1  bouyer 		if (esd->reason_code ==
   3585  1.1  bouyer 		    MPII_EVENT_SAS_DISC_REASON_CODE_COMPLETED &&
   3586  1.1  bouyer 		    esd->discovery_status != 0)
   3587  1.1  bouyer 			printf("%s: sas discovery completed with status %#x\n",
   3588  1.1  bouyer 			    DEVNAME(sc), esd->discovery_status);
   3589  1.1  bouyer 		}
   3590  1.1  bouyer 		break;
   3591  1.1  bouyer 	case MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
   3592  1.1  bouyer 		mpii_event_sas(sc, enp);
   3593  1.1  bouyer 		break;
   3594  1.1  bouyer 	case MPII_EVENT_SAS_DEVICE_STATUS_CHANGE:
   3595  1.1  bouyer 		break;
   3596  1.1  bouyer 	case MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
   3597  1.1  bouyer 		break;
   3598  1.1  bouyer 	case MPII_EVENT_IR_VOLUME: {
   3599  1.1  bouyer 		struct mpii_evt_ir_volume	*evd =
   3600  1.1  bouyer 		    (struct mpii_evt_ir_volume *)(enp + 1);
   3601  1.1  bouyer 		struct mpii_device		*dev;
   3602  1.1  bouyer #if NBIO > 0
   3603  1.1  bouyer 		const char *vol_states[] = {
   3604  1.1  bouyer 			BIOC_SVINVALID_S,
   3605  1.1  bouyer 			BIOC_SVOFFLINE_S,
   3606  1.1  bouyer 			BIOC_SVBUILDING_S,
   3607  1.1  bouyer 			BIOC_SVONLINE_S,
   3608  1.1  bouyer 			BIOC_SVDEGRADED_S,
   3609  1.1  bouyer 			BIOC_SVONLINE_S,
   3610  1.1  bouyer 		};
   3611  1.1  bouyer #endif
   3612  1.1  bouyer 
   3613  1.1  bouyer 		if (cold)
   3614  1.1  bouyer 			break;
   3615  1.1  bouyer 		if (!(dev = mpii_find_dev(sc, le16toh(evd->vol_dev_handle))))
   3616  1.1  bouyer 			break;
   3617  1.1  bouyer #if NBIO > 0
   3618  1.1  bouyer 		if (evd->reason_code == MPII_EVENT_IR_VOL_RC_STATE_CHANGED)
   3619  1.1  bouyer 			printf("%s: volume %d state changed from %s to %s\n",
   3620  1.1  bouyer 			    DEVNAME(sc), dev->slot - sc->sc_vd_id_low,
   3621  1.1  bouyer 			    vol_states[evd->prev_value],
   3622  1.1  bouyer 			    vol_states[evd->new_value]);
   3623  1.1  bouyer #endif
   3624  1.1  bouyer 		if (evd->reason_code == MPII_EVENT_IR_VOL_RC_STATUS_CHANGED &&
   3625  1.1  bouyer 		    ISSET(evd->new_value, MPII_CFG_RAID_VOL_0_STATUS_RESYNC) &&
   3626  1.1  bouyer 		    !ISSET(evd->prev_value, MPII_CFG_RAID_VOL_0_STATUS_RESYNC))
   3627  1.1  bouyer 			printf("%s: started resync on a volume %d\n",
   3628  1.1  bouyer 			    DEVNAME(sc), dev->slot - sc->sc_vd_id_low);
   3629  1.1  bouyer 		}
   3630  1.1  bouyer 		break;
   3631  1.1  bouyer 	case MPII_EVENT_IR_PHYSICAL_DISK:
   3632  1.1  bouyer 		break;
   3633  1.1  bouyer 	case MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST:
   3634  1.1  bouyer 		mpii_event_raid(sc, enp);
   3635  1.1  bouyer 		break;
   3636  1.1  bouyer 	case MPII_EVENT_IR_OPERATION_STATUS: {
   3637  1.1  bouyer 		struct mpii_evt_ir_status	*evs =
   3638  1.1  bouyer 		    (struct mpii_evt_ir_status *)(enp + 1);
   3639  1.1  bouyer 		struct mpii_device		*dev;
   3640  1.1  bouyer 
   3641  1.1  bouyer 		if (!(dev = mpii_find_dev(sc, le16toh(evs->vol_dev_handle))))
   3642  1.1  bouyer 			break;
   3643  1.1  bouyer 		if (evs->operation == MPII_EVENT_IR_RAIDOP_RESYNC)
   3644  1.1  bouyer 			dev->percent = evs->percent;
   3645  1.1  bouyer 		break;
   3646  1.1  bouyer 		}
   3647  1.1  bouyer 	default:
   3648  1.1  bouyer 		DNPRINTF(MPII_D_EVT, "%s:  unhandled event 0x%02x\n",
   3649  1.1  bouyer 		    DEVNAME(sc), le32toh(enp->event));
   3650  1.1  bouyer 	}
   3651  1.1  bouyer 
   3652  1.1  bouyer 	if (enp->ack_required)
   3653  1.1  bouyer 		workqueue_enqueue(sc->sc_ssb_evt_ackwk, &rcb->u.rcb_wk, NULL);
   3654  1.1  bouyer 	else
   3655  1.1  bouyer 		mpii_push_reply(sc, rcb);
   3656  1.1  bouyer }
   3657  1.1  bouyer 
   3658  1.1  bouyer static void
   3659  1.1  bouyer mpii_event_defer(void *xsc, void *arg)
   3660  1.1  bouyer {
   3661  1.1  bouyer 	struct mpii_softc	*sc = xsc;
   3662  1.1  bouyer 	struct mpii_device	*dev = arg;
   3663  1.1  bouyer 
   3664  1.1  bouyer 	if (ISSET(dev->flags, MPII_DF_DETACH)) {
   3665  1.1  bouyer 		mpii_sas_remove_device(sc, dev->dev_handle);
   3666  1.1  bouyer #if 0
   3667  1.1  bouyer 		if (!ISSET(dev->flags, MPII_DF_HIDDEN)) {
   3668  1.1  bouyer 			scsi_detach_target(sc->sc_scsibus, dev->slot,
   3669  1.1  bouyer 			    DETACH_FORCE);
   3670  1.1  bouyer 		}
   3671  1.1  bouyer #endif /* XXX */
   3672  1.1  bouyer 		free(dev, M_DEVBUF);
   3673  1.1  bouyer 
   3674  1.1  bouyer 	} else if (ISSET(dev->flags, MPII_DF_ATTACH)) {
   3675  1.1  bouyer 		CLR(dev->flags, MPII_DF_ATTACH);
   3676  1.1  bouyer #if 0
   3677  1.1  bouyer 		if (!ISSET(dev->flags, MPII_DF_HIDDEN))
   3678  1.1  bouyer 			scsi_probe_target(sc->sc_scsibus, dev->slot);
   3679  1.1  bouyer #endif /* XXX */
   3680  1.1  bouyer 	}
   3681  1.1  bouyer }
   3682  1.1  bouyer 
   3683  1.1  bouyer static void
   3684  1.1  bouyer mpii_sas_remove_device(struct mpii_softc *sc, u_int16_t handle)
   3685  1.1  bouyer {
   3686  1.1  bouyer  	struct mpii_msg_scsi_task_request	*stq;
   3687  1.1  bouyer 	struct mpii_msg_sas_oper_request	*soq;
   3688  1.1  bouyer 	struct mpii_ccb				*ccb;
   3689  1.1  bouyer 
   3690  1.1  bouyer 	ccb = mpii_get_ccb(sc, 0);
   3691  1.1  bouyer 	if (ccb == NULL)
   3692  1.1  bouyer 		return;
   3693  1.1  bouyer 
   3694  1.1  bouyer 	stq = ccb->ccb_cmd;
   3695  1.1  bouyer 	stq->function = MPII_FUNCTION_SCSI_TASK_MGMT;
   3696  1.1  bouyer 	stq->task_type = MPII_SCSI_TASK_TARGET_RESET;
   3697  1.1  bouyer 	stq->dev_handle = htole16(handle);
   3698  1.1  bouyer 
   3699  1.1  bouyer 	ccb->ccb_done = mpii_empty_done;
   3700  1.1  bouyer 	mpii_wait(sc, ccb);
   3701  1.1  bouyer 
   3702  1.1  bouyer 	if (ccb->ccb_rcb != NULL)
   3703  1.1  bouyer 		mpii_push_reply(sc, ccb->ccb_rcb);
   3704  1.1  bouyer 
   3705  1.1  bouyer 	/* reuse a ccb */
   3706  1.1  bouyer 	ccb->ccb_state = MPII_CCB_READY;
   3707  1.1  bouyer 	ccb->ccb_rcb = NULL;
   3708  1.1  bouyer 
   3709  1.1  bouyer 	soq = ccb->ccb_cmd;
   3710  1.1  bouyer 	bzero(soq, sizeof(*soq));
   3711  1.1  bouyer 	soq->function = MPII_FUNCTION_SAS_IO_UNIT_CONTROL;
   3712  1.1  bouyer 	soq->operation = MPII_SAS_OP_REMOVE_DEVICE;
   3713  1.1  bouyer 	soq->dev_handle = htole16(handle);
   3714  1.1  bouyer 
   3715  1.1  bouyer 	ccb->ccb_done = mpii_empty_done;
   3716  1.1  bouyer 	mpii_wait(sc, ccb);
   3717  1.1  bouyer 	if (ccb->ccb_rcb != NULL)
   3718  1.1  bouyer 		mpii_push_reply(sc, ccb->ccb_rcb);
   3719  1.1  bouyer }
   3720  1.1  bouyer 
   3721  1.1  bouyer static int
   3722  1.1  bouyer mpii_get_ioc_pg8(struct mpii_softc *sc)
   3723  1.1  bouyer {
   3724  1.1  bouyer 	struct mpii_cfg_hdr	hdr;
   3725  1.1  bouyer 	struct mpii_cfg_ioc_pg8	*page;
   3726  1.1  bouyer 	size_t			pagelen;
   3727  1.1  bouyer 	u_int16_t		flags;
   3728  1.1  bouyer 	int			pad = 0, rv = 0;
   3729  1.1  bouyer 
   3730  1.1  bouyer 	DNPRINTF(MPII_D_RAID, "%s: mpii_get_ioc_pg8\n", DEVNAME(sc));
   3731  1.1  bouyer 
   3732  1.1  bouyer 	if (mpii_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_IOC, 8, 0,
   3733  1.1  bouyer 	    &hdr) != 0) {
   3734  1.1  bouyer 		DNPRINTF(MPII_D_CFG, "%s: mpii_get_ioc_pg8 unable to fetch "
   3735  1.1  bouyer 		    "header for IOC page 8\n", DEVNAME(sc));
   3736  1.1  bouyer 		return (1);
   3737  1.1  bouyer 	}
   3738  1.1  bouyer 
   3739  1.1  bouyer 	pagelen = hdr.page_length * 4; /* dwords to bytes */
   3740  1.1  bouyer 
   3741  1.1  bouyer 	page = malloc(pagelen, M_TEMP, M_NOWAIT);
   3742  1.1  bouyer 	if (page == NULL) {
   3743  1.1  bouyer 		DNPRINTF(MPII_D_CFG, "%s: mpii_get_ioc_pg8 unable to allocate "
   3744  1.1  bouyer 		    "space for ioc config page 8\n", DEVNAME(sc));
   3745  1.1  bouyer 		return (1);
   3746  1.1  bouyer 	}
   3747  1.1  bouyer 
   3748  1.1  bouyer 	if (mpii_cfg_page(sc, 0, &hdr, 1, page, pagelen) != 0) {
   3749  1.1  bouyer 		DNPRINTF(MPII_D_CFG, "%s: mpii_get_raid unable to fetch IOC "
   3750  1.1  bouyer 		    "page 8\n", DEVNAME(sc));
   3751  1.1  bouyer 		rv = 1;
   3752  1.1  bouyer 		goto out;
   3753  1.1  bouyer 	}
   3754  1.1  bouyer 
   3755  1.1  bouyer 	DNPRINTF(MPII_D_CFG, "%s:  numdevsperenclosure: 0x%02x\n", DEVNAME(sc),
   3756  1.1  bouyer 	    page->num_devs_per_enclosure);
   3757  1.1  bouyer 	DNPRINTF(MPII_D_CFG, "%s:  maxpersistententries: 0x%04x "
   3758  1.1  bouyer 	    "maxnumphysicalmappedids: 0x%04x\n", DEVNAME(sc),
   3759  1.1  bouyer 	    le16toh(page->max_persistent_entries),
   3760  1.1  bouyer 	    le16toh(page->max_num_physical_mapped_ids));
   3761  1.1  bouyer 	DNPRINTF(MPII_D_CFG, "%s:  flags: 0x%04x\n", DEVNAME(sc),
   3762  1.1  bouyer 	    le16toh(page->flags));
   3763  1.1  bouyer 	DNPRINTF(MPII_D_CFG, "%s:  irvolumemappingflags: 0x%04x\n",
   3764  1.1  bouyer 	    DEVNAME(sc), le16toh(page->ir_volume_mapping_flags));
   3765  1.1  bouyer 
   3766  1.1  bouyer 	if (page->flags & MPII_IOC_PG8_FLAGS_RESERVED_TARGETID_0)
   3767  1.1  bouyer 		pad = 1;
   3768  1.1  bouyer 
   3769  1.1  bouyer 	flags = page->ir_volume_mapping_flags &
   3770  1.1  bouyer 	    MPII_IOC_PG8_IRFLAGS_VOLUME_MAPPING_MODE_MASK;
   3771  1.1  bouyer 	if (ISSET(sc->sc_flags, MPII_F_RAID)) {
   3772  1.1  bouyer 		if (flags == MPII_IOC_PG8_IRFLAGS_LOW_VOLUME_MAPPING) {
   3773  1.1  bouyer 			sc->sc_vd_id_low += pad;
   3774  1.1  bouyer 			pad = sc->sc_max_volumes; /* for sc_pd_id_start */
   3775  1.1  bouyer 		} else
   3776  1.1  bouyer 			sc->sc_vd_id_low = sc->sc_max_devices -
   3777  1.1  bouyer 			    sc->sc_max_volumes;
   3778  1.1  bouyer 	}
   3779  1.1  bouyer 
   3780  1.1  bouyer 	sc->sc_pd_id_start += pad;
   3781  1.1  bouyer 
   3782  1.1  bouyer 	DNPRINTF(MPII_D_MAP, "%s: mpii_get_ioc_pg8 mapping: sc_pd_id_start: %d "
   3783  1.1  bouyer 	    "sc_vd_id_low: %d sc_max_volumes: %d\n", DEVNAME(sc),
   3784  1.1  bouyer 	    sc->sc_pd_id_start, sc->sc_vd_id_low, sc->sc_max_volumes);
   3785  1.1  bouyer 
   3786  1.1  bouyer out:
   3787  1.1  bouyer 	free(page, M_TEMP);
   3788  1.1  bouyer 
   3789  1.1  bouyer 	return(rv);
   3790  1.1  bouyer }
   3791  1.1  bouyer 
   3792  1.1  bouyer static int
   3793  1.1  bouyer mpii_req_cfg_header(struct mpii_softc *sc, u_int8_t type, u_int8_t number,
   3794  1.1  bouyer     u_int32_t address, int flags, void *p)
   3795  1.1  bouyer {
   3796  1.1  bouyer 	struct mpii_msg_config_request		*cq;
   3797  1.1  bouyer 	struct mpii_msg_config_reply		*cp;
   3798  1.1  bouyer 	struct mpii_cfg_hdr	*hdr = p;
   3799  1.1  bouyer 	struct mpii_ccb		*ccb;
   3800  1.1  bouyer 	struct mpii_ecfg_hdr	*ehdr = p;
   3801  1.1  bouyer 	int			etype = 0;
   3802  1.1  bouyer 	int			rv = 0;
   3803  1.1  bouyer 
   3804  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_req_cfg_header type: %#x number: %x "
   3805  1.1  bouyer 	    "address: 0x%08x flags: 0x%x\n", DEVNAME(sc), type, number,
   3806  1.1  bouyer 	    address, flags);
   3807  1.1  bouyer 
   3808  1.1  bouyer 	ccb = mpii_get_ccb(sc, ISSET(flags, MPII_PG_POLL) ? MPII_NOSLEEP : 0);
   3809  1.1  bouyer 	if (ccb == NULL) {
   3810  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header ccb_get\n",
   3811  1.1  bouyer 		    DEVNAME(sc));
   3812  1.1  bouyer 		return (1);
   3813  1.1  bouyer 	}
   3814  1.1  bouyer 
   3815  1.1  bouyer 	if (ISSET(flags, MPII_PG_EXTENDED)) {
   3816  1.1  bouyer 		etype = type;
   3817  1.1  bouyer 		type = MPII_CONFIG_REQ_PAGE_TYPE_EXTENDED;
   3818  1.1  bouyer 	}
   3819  1.1  bouyer 
   3820  1.1  bouyer 	cq = ccb->ccb_cmd;
   3821  1.1  bouyer 
   3822  1.1  bouyer 	cq->function = MPII_FUNCTION_CONFIG;
   3823  1.1  bouyer 
   3824  1.1  bouyer 	cq->action = MPII_CONFIG_REQ_ACTION_PAGE_HEADER;
   3825  1.1  bouyer 
   3826  1.1  bouyer 	cq->config_header.page_number = number;
   3827  1.1  bouyer 	cq->config_header.page_type = type;
   3828  1.1  bouyer 	cq->ext_page_type = etype;
   3829  1.1  bouyer 	cq->page_address = htole32(address);
   3830  1.1  bouyer 	cq->page_buffer.sg_hdr = htole32(MPII_SGE_FL_TYPE_SIMPLE |
   3831  1.1  bouyer 	    MPII_SGE_FL_LAST | MPII_SGE_FL_EOB | MPII_SGE_FL_EOL);
   3832  1.1  bouyer 
   3833  1.1  bouyer 	ccb->ccb_done = mpii_empty_done;
   3834  1.1  bouyer 	if (ISSET(flags, MPII_PG_POLL)) {
   3835  1.1  bouyer 		if (mpii_poll(sc, ccb) != 0) {
   3836  1.1  bouyer 			DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header poll\n",
   3837  1.1  bouyer 			    DEVNAME(sc));
   3838  1.1  bouyer 			return (1);
   3839  1.1  bouyer 		}
   3840  1.1  bouyer 	} else
   3841  1.1  bouyer 		mpii_wait(sc, ccb);
   3842  1.1  bouyer 
   3843  1.1  bouyer 	if (ccb->ccb_rcb == NULL) {
   3844  1.1  bouyer 		mpii_put_ccb(sc, ccb);
   3845  1.1  bouyer 		return (1);
   3846  1.1  bouyer 	}
   3847  1.1  bouyer 	cp = ccb->ccb_rcb->rcb_reply;
   3848  1.1  bouyer 
   3849  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  action: 0x%02x sgl_flags: 0x%02x "
   3850  1.1  bouyer 	    "msg_length: %d function: 0x%02x\n", DEVNAME(sc), cp->action,
   3851  1.1  bouyer 	    cp->sgl_flags, cp->msg_length, cp->function);
   3852  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ext_page_length: %d ext_page_type: 0x%02x "
   3853  1.1  bouyer 	    "msg_flags: 0x%02x\n", DEVNAME(sc),
   3854  1.1  bouyer 	    le16toh(cp->ext_page_length), cp->ext_page_type,
   3855  1.1  bouyer 	    cp->msg_flags);
   3856  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc),
   3857  1.1  bouyer 	    cp->vp_id, cp->vf_id);
   3858  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
   3859  1.1  bouyer 	    le16toh(cp->ioc_status));
   3860  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
   3861  1.1  bouyer 	    le32toh(cp->ioc_loginfo));
   3862  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  page_version: 0x%02x page_length: %d "
   3863  1.1  bouyer 	    "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc),
   3864  1.1  bouyer 	    cp->config_header.page_version,
   3865  1.1  bouyer 	    cp->config_header.page_length,
   3866  1.1  bouyer 	    cp->config_header.page_number,
   3867  1.1  bouyer 	    cp->config_header.page_type);
   3868  1.1  bouyer 
   3869  1.1  bouyer 	if (le16toh(cp->ioc_status) != MPII_IOCSTATUS_SUCCESS)
   3870  1.1  bouyer 		rv = 1;
   3871  1.1  bouyer 	else if (ISSET(flags, MPII_PG_EXTENDED)) {
   3872  1.1  bouyer 		bzero(ehdr, sizeof(*ehdr));
   3873  1.1  bouyer 		ehdr->page_version = cp->config_header.page_version;
   3874  1.1  bouyer 		ehdr->page_number = cp->config_header.page_number;
   3875  1.1  bouyer 		ehdr->page_type = cp->config_header.page_type;
   3876  1.1  bouyer 		ehdr->ext_page_length = cp->ext_page_length;
   3877  1.1  bouyer 		ehdr->ext_page_type = cp->ext_page_type;
   3878  1.1  bouyer 	} else
   3879  1.1  bouyer 		*hdr = cp->config_header;
   3880  1.1  bouyer 
   3881  1.1  bouyer 	mpii_push_reply(sc, ccb->ccb_rcb);
   3882  1.1  bouyer 	mpii_put_ccb(sc, ccb);
   3883  1.1  bouyer 
   3884  1.1  bouyer 	return (rv);
   3885  1.1  bouyer }
   3886  1.1  bouyer 
   3887  1.1  bouyer static int
   3888  1.1  bouyer mpii_req_cfg_page(struct mpii_softc *sc, u_int32_t address, int flags,
   3889  1.1  bouyer     void *p, int read, void *page, size_t len)
   3890  1.1  bouyer {
   3891  1.1  bouyer 	struct mpii_msg_config_request		*cq;
   3892  1.1  bouyer 	struct mpii_msg_config_reply		*cp;
   3893  1.1  bouyer 	struct mpii_cfg_hdr	*hdr = p;
   3894  1.1  bouyer 	struct mpii_ccb		*ccb;
   3895  1.1  bouyer 	struct mpii_ecfg_hdr	*ehdr = p;
   3896  1.1  bouyer 	u_int64_t		dva;
   3897  1.1  bouyer 	char			*kva;
   3898  1.1  bouyer 	int			page_length;
   3899  1.1  bouyer 	int			rv = 0;
   3900  1.1  bouyer 
   3901  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_page address: %d read: %d "
   3902  1.1  bouyer 	    "type: %x\n", DEVNAME(sc), address, read, hdr->page_type);
   3903  1.1  bouyer 
   3904  1.1  bouyer 	page_length = ISSET(flags, MPII_PG_EXTENDED) ?
   3905  1.1  bouyer 	    le16toh(ehdr->ext_page_length) : hdr->page_length;
   3906  1.1  bouyer 
   3907  1.1  bouyer 	if (len > MPII_REQUEST_SIZE - sizeof(struct mpii_msg_config_request) ||
   3908  1.1  bouyer     	    len < page_length * 4)
   3909  1.1  bouyer 		return (1);
   3910  1.1  bouyer 
   3911  1.1  bouyer 	ccb = mpii_get_ccb(sc,
   3912  1.1  bouyer 	    ISSET(flags, MPII_PG_POLL) ? MPII_NOSLEEP : 0);
   3913  1.1  bouyer 	if (ccb == NULL) {
   3914  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_page ccb_get\n",
   3915  1.1  bouyer 		    DEVNAME(sc));
   3916  1.1  bouyer 		return (1);
   3917  1.1  bouyer 	}
   3918  1.1  bouyer 
   3919  1.1  bouyer 	cq = ccb->ccb_cmd;
   3920  1.1  bouyer 
   3921  1.1  bouyer 	cq->function = MPII_FUNCTION_CONFIG;
   3922  1.1  bouyer 
   3923  1.1  bouyer 	cq->action = (read ? MPII_CONFIG_REQ_ACTION_PAGE_READ_CURRENT :
   3924  1.1  bouyer 	    MPII_CONFIG_REQ_ACTION_PAGE_WRITE_CURRENT);
   3925  1.1  bouyer 
   3926  1.1  bouyer 	if (ISSET(flags, MPII_PG_EXTENDED)) {
   3927  1.1  bouyer 		cq->config_header.page_version = ehdr->page_version;
   3928  1.1  bouyer 		cq->config_header.page_number = ehdr->page_number;
   3929  1.1  bouyer 		cq->config_header.page_type = ehdr->page_type;
   3930  1.1  bouyer 		cq->ext_page_len = ehdr->ext_page_length;
   3931  1.1  bouyer 		cq->ext_page_type = ehdr->ext_page_type;
   3932  1.1  bouyer 	} else
   3933  1.1  bouyer 		cq->config_header = *hdr;
   3934  1.1  bouyer 	cq->config_header.page_type &= MPII_CONFIG_REQ_PAGE_TYPE_MASK;
   3935  1.1  bouyer 	cq->page_address = htole32(address);
   3936  1.1  bouyer 	cq->page_buffer.sg_hdr = htole32(MPII_SGE_FL_TYPE_SIMPLE |
   3937  1.1  bouyer 	    MPII_SGE_FL_LAST | MPII_SGE_FL_EOB | MPII_SGE_FL_EOL |
   3938  1.1  bouyer 	    MPII_SGE_FL_SIZE_64 | (page_length * 4) |
   3939  1.1  bouyer 	    (read ? MPII_SGE_FL_DIR_IN : MPII_SGE_FL_DIR_OUT));
   3940  1.1  bouyer 
   3941  1.1  bouyer 	/* bounce the page via the request space to avoid more bus_dma games */
   3942  1.1  bouyer 	dva = ccb->ccb_cmd_dva + sizeof(struct mpii_msg_config_request);
   3943  1.1  bouyer 
   3944  1.1  bouyer 	cq->page_buffer.sg_hi_addr = htole32((u_int32_t)(dva >> 32));
   3945  1.1  bouyer 	cq->page_buffer.sg_lo_addr = htole32((u_int32_t)dva);
   3946  1.1  bouyer 
   3947  1.1  bouyer 	kva = ccb->ccb_cmd;
   3948  1.1  bouyer 	kva += sizeof(struct mpii_msg_config_request);
   3949  1.1  bouyer 
   3950  1.1  bouyer 	if (!read)
   3951  1.1  bouyer 		bcopy(page, kva, len);
   3952  1.1  bouyer 
   3953  1.1  bouyer 	ccb->ccb_done = mpii_empty_done;
   3954  1.1  bouyer 	if (ISSET(flags, MPII_PG_POLL)) {
   3955  1.1  bouyer 		if (mpii_poll(sc, ccb) != 0) {
   3956  1.1  bouyer 			DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header poll\n",
   3957  1.1  bouyer 			    DEVNAME(sc));
   3958  1.1  bouyer 			return (1);
   3959  1.1  bouyer 		}
   3960  1.1  bouyer 	} else
   3961  1.1  bouyer 		mpii_wait(sc, ccb);
   3962  1.1  bouyer 
   3963  1.1  bouyer 	if (ccb->ccb_rcb == NULL) {
   3964  1.1  bouyer 		mpii_put_ccb(sc, ccb);
   3965  1.1  bouyer 		return (1);
   3966  1.1  bouyer 	}
   3967  1.1  bouyer 	cp = ccb->ccb_rcb->rcb_reply;
   3968  1.1  bouyer 
   3969  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  action: 0x%02x "
   3970  1.1  bouyer 	    "msg_length: %d function: 0x%02x\n", DEVNAME(sc), cp->action,
   3971  1.1  bouyer 	    cp->msg_length, cp->function);
   3972  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ext_page_length: %d ext_page_type: 0x%02x "
   3973  1.1  bouyer 	    "msg_flags: 0x%02x\n", DEVNAME(sc),
   3974  1.1  bouyer 	    le16toh(cp->ext_page_length), cp->ext_page_type,
   3975  1.1  bouyer 	    cp->msg_flags);
   3976  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc),
   3977  1.1  bouyer 	    cp->vp_id, cp->vf_id);
   3978  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
   3979  1.1  bouyer 	    le16toh(cp->ioc_status));
   3980  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
   3981  1.1  bouyer 	    le32toh(cp->ioc_loginfo));
   3982  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  page_version: 0x%02x page_length: %d "
   3983  1.1  bouyer 	    "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc),
   3984  1.1  bouyer 	    cp->config_header.page_version,
   3985  1.1  bouyer 	    cp->config_header.page_length,
   3986  1.1  bouyer 	    cp->config_header.page_number,
   3987  1.1  bouyer 	    cp->config_header.page_type);
   3988  1.1  bouyer 
   3989  1.1  bouyer 	if (le16toh(cp->ioc_status) != MPII_IOCSTATUS_SUCCESS)
   3990  1.1  bouyer 		rv = 1;
   3991  1.1  bouyer 	else if (read)
   3992  1.1  bouyer 		bcopy(kva, page, len);
   3993  1.1  bouyer 
   3994  1.1  bouyer 	mpii_push_reply(sc, ccb->ccb_rcb);
   3995  1.1  bouyer 	mpii_put_ccb(sc, ccb);
   3996  1.1  bouyer 
   3997  1.1  bouyer 	return (rv);
   3998  1.1  bouyer }
   3999  1.1  bouyer 
   4000  1.1  bouyer static struct mpii_rcb *
   4001  1.1  bouyer mpii_reply(struct mpii_softc *sc, struct mpii_reply_descr *rdp)
   4002  1.1  bouyer {
   4003  1.1  bouyer 	struct mpii_rcb		*rcb = NULL;
   4004  1.1  bouyer 	u_int32_t		rfid;
   4005  1.1  bouyer 
   4006  1.1  bouyer 	DNPRINTF(MPII_D_INTR, "%s: mpii_reply\n", DEVNAME(sc));
   4007  1.1  bouyer 
   4008  1.1  bouyer 	if ((rdp->reply_flags & MPII_REPLY_DESCR_TYPE_MASK) ==
   4009  1.1  bouyer 	    MPII_REPLY_DESCR_ADDRESS_REPLY) {
   4010  1.1  bouyer 		rfid = (le32toh(rdp->frame_addr) -
   4011  1.1  bouyer 		    (u_int32_t)MPII_DMA_DVA(sc->sc_replies)) / MPII_REPLY_SIZE;
   4012  1.1  bouyer 
   4013  1.1  bouyer 		bus_dmamap_sync(sc->sc_dmat,
   4014  1.1  bouyer 		    MPII_DMA_MAP(sc->sc_replies), MPII_REPLY_SIZE * rfid,
   4015  1.1  bouyer 		    MPII_REPLY_SIZE, BUS_DMASYNC_POSTREAD);
   4016  1.1  bouyer 
   4017  1.1  bouyer 		rcb = &sc->sc_rcbs[rfid];
   4018  1.1  bouyer 	}
   4019  1.1  bouyer 
   4020  1.1  bouyer 	memset(rdp, 0xff, sizeof(*rdp));
   4021  1.1  bouyer 
   4022  1.1  bouyer 	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq),
   4023  1.1  bouyer 	    8 * sc->sc_reply_post_host_index, 8,
   4024  1.1  bouyer 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
   4025  1.1  bouyer 
   4026  1.1  bouyer 	return (rcb);
   4027  1.1  bouyer }
   4028  1.1  bouyer 
   4029  1.1  bouyer static struct mpii_dmamem *
   4030  1.1  bouyer mpii_dmamem_alloc(struct mpii_softc *sc, size_t size)
   4031  1.1  bouyer {
   4032  1.1  bouyer 	struct mpii_dmamem	*mdm;
   4033  1.1  bouyer 	int			nsegs;
   4034  1.1  bouyer 
   4035  1.1  bouyer 	mdm = malloc(sizeof(*mdm), M_DEVBUF, M_NOWAIT | M_ZERO);
   4036  1.1  bouyer 	if (mdm == NULL)
   4037  1.1  bouyer 	return (NULL);
   4038  1.1  bouyer 
   4039  1.1  bouyer 	mdm->mdm_size = size;
   4040  1.1  bouyer 
   4041  1.1  bouyer 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
   4042  1.1  bouyer 	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mdm->mdm_map) != 0)
   4043  1.1  bouyer 		goto mdmfree;
   4044  1.1  bouyer 
   4045  1.1  bouyer 	if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &mdm->mdm_seg,
   4046  1.1  bouyer 	    1, &nsegs, BUS_DMA_NOWAIT) != 0) goto destroy;
   4047  1.1  bouyer 
   4048  1.1  bouyer 	if (bus_dmamem_map(sc->sc_dmat, &mdm->mdm_seg, nsegs, size,
   4049  1.1  bouyer 	    &mdm->mdm_kva, BUS_DMA_NOWAIT) != 0)
   4050  1.1  bouyer 		goto free;
   4051  1.1  bouyer 
   4052  1.1  bouyer 	if (bus_dmamap_load(sc->sc_dmat, mdm->mdm_map, mdm->mdm_kva, size,
   4053  1.1  bouyer 	    NULL, BUS_DMA_NOWAIT) != 0)
   4054  1.1  bouyer 		goto unmap;
   4055  1.1  bouyer 
   4056  1.1  bouyer 	DNPRINTF(MPII_D_MEM,
   4057  1.1  bouyer 	    "  kva: %p  dva: 0x%" PRIx64 "  map: %p  size: %" PRId64 "\n",
   4058  1.1  bouyer 	    mdm->mdm_kva, (uint64_t)mdm->mdm_map->dm_segs[0].ds_addr,
   4059  1.1  bouyer 	    mdm->mdm_map, (uint64_t)size);
   4060  1.1  bouyer 
   4061  1.1  bouyer 	bzero(mdm->mdm_kva, size);
   4062  1.1  bouyer 
   4063  1.1  bouyer 	return (mdm);
   4064  1.1  bouyer 
   4065  1.1  bouyer unmap:
   4066  1.1  bouyer 	bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, size);
   4067  1.1  bouyer free:
   4068  1.1  bouyer 	bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1);
   4069  1.1  bouyer destroy:
   4070  1.1  bouyer 	bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map);
   4071  1.1  bouyer mdmfree:
   4072  1.1  bouyer 	free(mdm, M_DEVBUF);
   4073  1.1  bouyer 
   4074  1.1  bouyer 	return (NULL);
   4075  1.1  bouyer }
   4076  1.1  bouyer 
   4077  1.1  bouyer static void
   4078  1.1  bouyer mpii_dmamem_free(struct mpii_softc *sc, struct mpii_dmamem *mdm)
   4079  1.1  bouyer {
   4080  1.1  bouyer 	DNPRINTF(MPII_D_MEM, "%s: mpii_dmamem_free %p\n", DEVNAME(sc), mdm);
   4081  1.1  bouyer 
   4082  1.1  bouyer 	bus_dmamap_unload(sc->sc_dmat, mdm->mdm_map);
   4083  1.1  bouyer 	bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, mdm->mdm_size);
   4084  1.1  bouyer 	bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1);
   4085  1.1  bouyer 	bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map);
   4086  1.1  bouyer 	free(mdm, M_DEVBUF);
   4087  1.1  bouyer }
   4088  1.1  bouyer 
   4089  1.1  bouyer static int
   4090  1.1  bouyer mpii_alloc_dev(struct mpii_softc *sc)
   4091  1.1  bouyer {
   4092  1.1  bouyer 	sc->sc_devs = malloc(sc->sc_max_devices *
   4093  1.1  bouyer 	    sizeof(struct mpii_device *), M_DEVBUF, M_NOWAIT | M_ZERO);
   4094  1.1  bouyer 	if (sc->sc_devs == NULL)
   4095  1.1  bouyer 		return (1);
   4096  1.1  bouyer 	return (0);
   4097  1.1  bouyer }
   4098  1.1  bouyer 
   4099  1.1  bouyer static int
   4100  1.1  bouyer mpii_insert_dev(struct mpii_softc *sc, struct mpii_device *dev)
   4101  1.1  bouyer {
   4102  1.1  bouyer 	int slot = dev->slot; 	/* initial hint */
   4103  1.1  bouyer 
   4104  1.1  bouyer 	if (!dev || slot < 0)
   4105  1.1  bouyer 		return (1);
   4106  1.1  bouyer 	while (slot < sc->sc_max_devices && sc->sc_devs[slot] != NULL)
   4107  1.1  bouyer 		slot++;
   4108  1.1  bouyer 	if (slot >= sc->sc_max_devices)
   4109  1.1  bouyer 		return (1);
   4110  1.1  bouyer 	dev->slot = slot;
   4111  1.1  bouyer 	sc->sc_devs[slot] = dev;
   4112  1.1  bouyer 	return (0);
   4113  1.1  bouyer }
   4114  1.1  bouyer 
   4115  1.1  bouyer static int
   4116  1.1  bouyer mpii_remove_dev(struct mpii_softc *sc, struct mpii_device *dev)
   4117  1.1  bouyer {
   4118  1.1  bouyer 	int			i;
   4119  1.1  bouyer 
   4120  1.1  bouyer 	if (!dev)
   4121  1.1  bouyer 		return (1);
   4122  1.1  bouyer 	for (i = 0; i < sc->sc_max_devices;  i++)
   4123  1.1  bouyer 		if (sc->sc_devs[i] &&
   4124  1.1  bouyer 		    sc->sc_devs[i]->dev_handle == dev->dev_handle) {
   4125  1.1  bouyer 			sc->sc_devs[i] = NULL;
   4126  1.1  bouyer 			return (0);
   4127  1.1  bouyer 		}
   4128  1.1  bouyer 	return (1);
   4129  1.1  bouyer }
   4130  1.1  bouyer 
   4131  1.1  bouyer static struct mpii_device *
   4132  1.1  bouyer mpii_find_dev(struct mpii_softc *sc, u_int16_t handle)
   4133  1.1  bouyer {
   4134  1.1  bouyer 	int			i;
   4135  1.1  bouyer 
   4136  1.1  bouyer 	for (i = 0; i < sc->sc_max_devices;  i++)
   4137  1.1  bouyer 		if (sc->sc_devs[i] && sc->sc_devs[i]->dev_handle == handle)
   4138  1.1  bouyer 			return (sc->sc_devs[i]);
   4139  1.1  bouyer 	return (NULL);
   4140  1.1  bouyer }
   4141  1.1  bouyer 
   4142  1.1  bouyer static int
   4143  1.1  bouyer mpii_alloc_ccbs(struct mpii_softc *sc)
   4144  1.1  bouyer {
   4145  1.1  bouyer 	struct mpii_ccb		*ccb;
   4146  1.1  bouyer 	u_int8_t		*cmd;
   4147  1.1  bouyer 	int			i;
   4148  1.1  bouyer 
   4149  1.1  bouyer 	SIMPLEQ_INIT(&sc->sc_ccb_free);
   4150  1.1  bouyer 
   4151  1.1  bouyer 	sc->sc_ccbs = malloc(sizeof(*ccb) * (sc->sc_request_depth-1),
   4152  1.1  bouyer 	    M_DEVBUF, M_NOWAIT | M_ZERO);
   4153  1.1  bouyer 	if (sc->sc_ccbs == NULL) {
   4154  1.1  bouyer 		printf("%s: unable to allocate ccbs\n", DEVNAME(sc));
   4155  1.1  bouyer 		return (1);
   4156  1.1  bouyer 	}
   4157  1.1  bouyer 
   4158  1.1  bouyer 	sc->sc_requests = mpii_dmamem_alloc(sc,
   4159  1.1  bouyer 	    MPII_REQUEST_SIZE * sc->sc_request_depth);
   4160  1.1  bouyer 	if (sc->sc_requests == NULL) {
   4161  1.1  bouyer 		printf("%s: unable to allocate ccb dmamem\n", DEVNAME(sc));
   4162  1.1  bouyer 		goto free_ccbs;
   4163  1.1  bouyer 	}
   4164  1.1  bouyer 	cmd = MPII_DMA_KVA(sc->sc_requests);
   4165  1.1  bouyer 	bzero(cmd, MPII_REQUEST_SIZE * sc->sc_request_depth);
   4166  1.1  bouyer 
   4167  1.1  bouyer 	/*
   4168  1.1  bouyer 	 * we have sc->sc_request_depth system request message
   4169  1.1  bouyer 	 * frames, but smid zero cannot be used. so we then
   4170  1.1  bouyer 	 * have (sc->sc_request_depth - 1) number of ccbs
   4171  1.1  bouyer 	 */
   4172  1.1  bouyer 	for (i = 1; i < sc->sc_request_depth; i++) {
   4173  1.1  bouyer 		ccb = &sc->sc_ccbs[i - 1];
   4174  1.1  bouyer 
   4175  1.1  bouyer 		if (bus_dmamap_create(sc->sc_dmat, MAXPHYS,
   4176  1.1  bouyer 		    sc->sc_max_sgl_len, MAXPHYS, 0,
   4177  1.1  bouyer 		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
   4178  1.1  bouyer 		    &ccb->ccb_dmamap) != 0) {
   4179  1.1  bouyer 			printf("%s: unable to create dma map\n", DEVNAME(sc));
   4180  1.1  bouyer 			goto free_maps;
   4181  1.1  bouyer 		}
   4182  1.1  bouyer 
   4183  1.1  bouyer 		ccb->ccb_sc = sc;
   4184  1.1  bouyer 		ccb->ccb_smid = i;
   4185  1.1  bouyer 		ccb->ccb_offset = MPII_REQUEST_SIZE * i;
   4186  1.1  bouyer 
   4187  1.1  bouyer 		ccb->ccb_cmd = &cmd[ccb->ccb_offset];
   4188  1.1  bouyer 		ccb->ccb_cmd_dva = (u_int32_t)MPII_DMA_DVA(sc->sc_requests) +
   4189  1.1  bouyer 		    ccb->ccb_offset;
   4190  1.1  bouyer 
   4191  1.1  bouyer 		DNPRINTF(MPII_D_CCB, "%s: mpii_alloc_ccbs(%d) ccb: %p map: %p "
   4192  1.1  bouyer 		    "sc: %p smid: %#x offs: %#" PRIx64 " cmd: %#" PRIx64 " dva: %#" PRIx64 "\n",
   4193  1.1  bouyer 		    DEVNAME(sc), i, ccb, ccb->ccb_dmamap, ccb->ccb_sc,
   4194  1.1  bouyer 		    ccb->ccb_smid, (uint64_t)ccb->ccb_offset,
   4195  1.1  bouyer 		    (uint64_t)ccb->ccb_cmd, (uint64_t)ccb->ccb_cmd_dva);
   4196  1.1  bouyer 
   4197  1.1  bouyer 		mpii_put_ccb(sc, ccb);
   4198  1.1  bouyer 	}
   4199  1.1  bouyer 
   4200  1.1  bouyer 	return (0);
   4201  1.1  bouyer 
   4202  1.1  bouyer free_maps:
   4203  1.1  bouyer 	while ((ccb = mpii_get_ccb(sc, MPII_NOSLEEP)) != NULL)
   4204  1.1  bouyer 		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
   4205  1.1  bouyer 
   4206  1.1  bouyer 	mpii_dmamem_free(sc, sc->sc_requests);
   4207  1.1  bouyer free_ccbs:
   4208  1.1  bouyer 	free(sc->sc_ccbs, M_DEVBUF);
   4209  1.1  bouyer 
   4210  1.1  bouyer 	return (1);
   4211  1.1  bouyer }
   4212  1.1  bouyer 
   4213  1.1  bouyer static void
   4214  1.1  bouyer mpii_put_ccb(struct mpii_softc *sc, struct mpii_ccb *ccb)
   4215  1.1  bouyer {
   4216  1.1  bouyer 	KASSERT(ccb->ccb_sc == sc);
   4217  1.1  bouyer 	DNPRINTF(MPII_D_CCB, "%s: mpii_put_ccb %p\n", DEVNAME(sc), ccb);
   4218  1.1  bouyer 
   4219  1.1  bouyer 	ccb->ccb_state = MPII_CCB_FREE;
   4220  1.1  bouyer 	ccb->ccb_cookie = NULL;
   4221  1.1  bouyer 	ccb->ccb_done = NULL;
   4222  1.1  bouyer 	ccb->ccb_rcb = NULL;
   4223  1.1  bouyer 	bzero(ccb->ccb_cmd, MPII_REQUEST_SIZE);
   4224  1.1  bouyer 
   4225  1.1  bouyer 	mutex_enter(&sc->sc_ccb_free_mtx);
   4226  1.1  bouyer 	SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ccb, u.ccb_link);
   4227  1.1  bouyer 	cv_signal(&sc->sc_ccb_free_cv);
   4228  1.1  bouyer 	mutex_exit(&sc->sc_ccb_free_mtx);
   4229  1.1  bouyer }
   4230  1.1  bouyer 
   4231  1.1  bouyer static struct mpii_ccb *
   4232  1.1  bouyer mpii_get_ccb(struct mpii_softc *sc, int flags)
   4233  1.1  bouyer {
   4234  1.1  bouyer 	struct mpii_ccb		*ccb;
   4235  1.1  bouyer 
   4236  1.1  bouyer 	mutex_enter(&sc->sc_ccb_free_mtx);
   4237  1.1  bouyer 	while ((ccb = SIMPLEQ_FIRST(&sc->sc_ccb_free)) == NULL) {
   4238  1.1  bouyer 		if (flags & MPII_NOSLEEP)
   4239  1.1  bouyer 			break;
   4240  1.1  bouyer 		cv_wait(&sc->sc_ccb_free_cv, &sc->sc_ccb_free_mtx);
   4241  1.1  bouyer 	}
   4242  1.1  bouyer 
   4243  1.1  bouyer 	if (ccb != NULL) {
   4244  1.1  bouyer 		SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, u.ccb_link);
   4245  1.1  bouyer 		ccb->ccb_state = MPII_CCB_READY;
   4246  1.1  bouyer 		KASSERT(ccb->ccb_sc == sc);
   4247  1.1  bouyer 	}
   4248  1.1  bouyer 	mutex_exit(&sc->sc_ccb_free_mtx);
   4249  1.1  bouyer 
   4250  1.1  bouyer 	DNPRINTF(MPII_D_CCB, "%s: mpii_get_ccb %p\n", DEVNAME(sc), ccb);
   4251  1.1  bouyer 
   4252  1.1  bouyer 	return (ccb);
   4253  1.1  bouyer }
   4254  1.1  bouyer 
   4255  1.1  bouyer static int
   4256  1.1  bouyer mpii_alloc_replies(struct mpii_softc *sc)
   4257  1.1  bouyer {
   4258  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_alloc_replies\n", DEVNAME(sc));
   4259  1.1  bouyer 
   4260  1.1  bouyer 	sc->sc_rcbs = malloc(sc->sc_num_reply_frames * sizeof(struct mpii_rcb),
   4261  1.1  bouyer 	    M_DEVBUF, M_NOWAIT);
   4262  1.1  bouyer 	if (sc->sc_rcbs == NULL)
   4263  1.1  bouyer 		return (1);
   4264  1.1  bouyer 
   4265  1.1  bouyer 	sc->sc_replies = mpii_dmamem_alloc(sc, MPII_REPLY_SIZE *
   4266  1.1  bouyer 	    sc->sc_num_reply_frames);
   4267  1.1  bouyer 	if (sc->sc_replies == NULL) {
   4268  1.1  bouyer 		free(sc->sc_rcbs, M_DEVBUF);
   4269  1.1  bouyer 		return (1);
   4270  1.1  bouyer 	}
   4271  1.1  bouyer 
   4272  1.1  bouyer 	return (0);
   4273  1.1  bouyer }
   4274  1.1  bouyer 
   4275  1.1  bouyer static void
   4276  1.1  bouyer mpii_push_replies(struct mpii_softc *sc)
   4277  1.1  bouyer {
   4278  1.1  bouyer 	struct mpii_rcb		*rcb;
   4279  1.1  bouyer 	char			*kva = MPII_DMA_KVA(sc->sc_replies);
   4280  1.1  bouyer 	int			i;
   4281  1.1  bouyer 
   4282  1.1  bouyer 	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_replies),
   4283  1.1  bouyer 	    0, MPII_REPLY_SIZE * sc->sc_num_reply_frames, BUS_DMASYNC_PREREAD);
   4284  1.1  bouyer 
   4285  1.1  bouyer 	for (i = 0; i < sc->sc_num_reply_frames; i++) {
   4286  1.1  bouyer 		rcb = &sc->sc_rcbs[i];
   4287  1.1  bouyer 
   4288  1.1  bouyer 		rcb->rcb_reply = kva + MPII_REPLY_SIZE * i;
   4289  1.1  bouyer 		rcb->rcb_reply_dva = (u_int32_t)MPII_DMA_DVA(sc->sc_replies) +
   4290  1.1  bouyer 		    MPII_REPLY_SIZE * i;
   4291  1.1  bouyer 		mpii_push_reply(sc, rcb);
   4292  1.1  bouyer 	}
   4293  1.1  bouyer }
   4294  1.1  bouyer 
   4295  1.1  bouyer static void
   4296  1.1  bouyer mpii_start(struct mpii_softc *sc, struct mpii_ccb *ccb)
   4297  1.1  bouyer {
   4298  1.1  bouyer 	struct mpii_request_header	*rhp;
   4299  1.1  bouyer 	struct mpii_request_descr	descr;
   4300  1.1  bouyer 	u_int32_t			*rdp = (u_int32_t *)&descr;
   4301  1.1  bouyer 
   4302  1.1  bouyer 	DNPRINTF(MPII_D_RW, "%s: mpii_start %#" PRIx64 "\n", DEVNAME(sc),
   4303  1.1  bouyer 	    (uint64_t)ccb->ccb_cmd_dva);
   4304  1.1  bouyer 
   4305  1.1  bouyer 	rhp = ccb->ccb_cmd;
   4306  1.1  bouyer 
   4307  1.1  bouyer 	bzero(&descr, sizeof(descr));
   4308  1.1  bouyer 
   4309  1.1  bouyer 	switch (rhp->function) {
   4310  1.1  bouyer 	case MPII_FUNCTION_SCSI_IO_REQUEST:
   4311  1.1  bouyer 		descr.request_flags = MPII_REQ_DESCR_SCSI_IO;
   4312  1.1  bouyer 		descr.dev_handle = htole16(ccb->ccb_dev_handle);
   4313  1.1  bouyer 		break;
   4314  1.1  bouyer 	case MPII_FUNCTION_SCSI_TASK_MGMT:
   4315  1.1  bouyer 		descr.request_flags = MPII_REQ_DESCR_HIGH_PRIORITY;
   4316  1.1  bouyer 		break;
   4317  1.1  bouyer 	default:
   4318  1.1  bouyer 		descr.request_flags = MPII_REQ_DESCR_DEFAULT;
   4319  1.1  bouyer 	}
   4320  1.1  bouyer 
   4321  1.1  bouyer 	descr.vf_id = sc->sc_vf_id;
   4322  1.1  bouyer 	descr.smid = htole16(ccb->ccb_smid);
   4323  1.1  bouyer 
   4324  1.1  bouyer 	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_requests),
   4325  1.1  bouyer 	    ccb->ccb_offset, MPII_REQUEST_SIZE,
   4326  1.1  bouyer 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
   4327  1.1  bouyer 
   4328  1.1  bouyer 	ccb->ccb_state = MPII_CCB_QUEUED;
   4329  1.1  bouyer 
   4330  1.1  bouyer 	DNPRINTF(MPII_D_RW, "%s:   MPII_REQ_DESCR_POST_LOW (0x%08x) write "
   4331  1.1  bouyer 	    "0x%08x\n", DEVNAME(sc), MPII_REQ_DESCR_POST_LOW, *rdp);
   4332  1.1  bouyer 
   4333  1.1  bouyer 	DNPRINTF(MPII_D_RW, "%s:   MPII_REQ_DESCR_POST_HIGH (0x%08x) write "
   4334  1.1  bouyer 	    "0x%08x\n", DEVNAME(sc), MPII_REQ_DESCR_POST_HIGH, *(rdp+1));
   4335  1.1  bouyer 
   4336  1.1  bouyer 	mutex_enter(&sc->sc_req_mtx);
   4337  1.1  bouyer 	mpii_write(sc, MPII_REQ_DESCR_POST_LOW, htole32(*rdp));
   4338  1.1  bouyer 	mpii_write(sc, MPII_REQ_DESCR_POST_HIGH, htole32(*(rdp+1)));
   4339  1.1  bouyer 	mutex_exit(&sc->sc_req_mtx);
   4340  1.1  bouyer }
   4341  1.1  bouyer 
   4342  1.1  bouyer static int
   4343  1.1  bouyer mpii_poll(struct mpii_softc *sc, struct mpii_ccb *ccb)
   4344  1.1  bouyer {
   4345  1.1  bouyer 	void				(*done)(struct mpii_ccb *);
   4346  1.1  bouyer 	void				*cookie;
   4347  1.1  bouyer 	int				rv = 1;
   4348  1.1  bouyer 
   4349  1.1  bouyer 	DNPRINTF(MPII_D_INTR, "%s: mpii_complete\n", DEVNAME(sc));
   4350  1.1  bouyer 
   4351  1.1  bouyer 	done = ccb->ccb_done;
   4352  1.1  bouyer 	cookie = ccb->ccb_cookie;
   4353  1.1  bouyer 
   4354  1.1  bouyer 	ccb->ccb_done = mpii_poll_done;
   4355  1.1  bouyer 	ccb->ccb_cookie = &rv;
   4356  1.1  bouyer 
   4357  1.1  bouyer 	mpii_start(sc, ccb);
   4358  1.1  bouyer 
   4359  1.1  bouyer 	while (rv == 1) {
   4360  1.1  bouyer 		/* avoid excessive polling */
   4361  1.1  bouyer 		if (mpii_reply_waiting(sc))
   4362  1.1  bouyer 			mpii_intr(sc);
   4363  1.1  bouyer 		else
   4364  1.1  bouyer 			delay(10);
   4365  1.1  bouyer 	}
   4366  1.1  bouyer 
   4367  1.1  bouyer 	ccb->ccb_cookie = cookie;
   4368  1.1  bouyer 	done(ccb);
   4369  1.1  bouyer 
   4370  1.1  bouyer 	return (0);
   4371  1.1  bouyer }
   4372  1.1  bouyer 
   4373  1.1  bouyer static void
   4374  1.1  bouyer mpii_poll_done(struct mpii_ccb *ccb)
   4375  1.1  bouyer {
   4376  1.1  bouyer 	int				*rv = ccb->ccb_cookie;
   4377  1.1  bouyer 
   4378  1.1  bouyer 	*rv = 0;
   4379  1.1  bouyer }
   4380  1.1  bouyer 
   4381  1.1  bouyer static int
   4382  1.1  bouyer mpii_alloc_queues(struct mpii_softc *sc)
   4383  1.1  bouyer {
   4384  1.1  bouyer 	u_int32_t		*kva;
   4385  1.1  bouyer 	u_int64_t		*kva64;
   4386  1.1  bouyer 	int			i;
   4387  1.1  bouyer 
   4388  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_alloc_queues\n", DEVNAME(sc));
   4389  1.1  bouyer 
   4390  1.1  bouyer 	sc->sc_reply_freeq = mpii_dmamem_alloc(sc,
   4391  1.1  bouyer 	    sc->sc_reply_free_qdepth * 4);
   4392  1.1  bouyer 	if (sc->sc_reply_freeq == NULL)
   4393  1.1  bouyer 		return (1);
   4394  1.1  bouyer 
   4395  1.1  bouyer 	kva = MPII_DMA_KVA(sc->sc_reply_freeq);
   4396  1.1  bouyer 	for (i = 0; i < sc->sc_num_reply_frames; i++) {
   4397  1.1  bouyer 		kva[i] = (u_int32_t)MPII_DMA_DVA(sc->sc_replies) +
   4398  1.1  bouyer 		    MPII_REPLY_SIZE * i;
   4399  1.1  bouyer 
   4400  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s:   %d:  %p = 0x%08x\n",
   4401  1.1  bouyer 		    DEVNAME(sc), i,
   4402  1.1  bouyer 		    &kva[i], (u_int)MPII_DMA_DVA(sc->sc_replies) +
   4403  1.1  bouyer 		    MPII_REPLY_SIZE * i);
   4404  1.1  bouyer 	}
   4405  1.1  bouyer 
   4406  1.1  bouyer 	sc->sc_reply_postq =
   4407  1.1  bouyer 	    mpii_dmamem_alloc(sc, sc->sc_reply_post_qdepth * 8);
   4408  1.1  bouyer 	if (sc->sc_reply_postq == NULL)
   4409  1.1  bouyer 		goto free_reply_freeq;
   4410  1.1  bouyer 	sc->sc_reply_postq_kva = MPII_DMA_KVA(sc->sc_reply_postq);
   4411  1.1  bouyer 
   4412  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  populating reply post descriptor queue\n",
   4413  1.1  bouyer 	    DEVNAME(sc));
   4414  1.1  bouyer 	kva64 = (u_int64_t *)MPII_DMA_KVA(sc->sc_reply_postq);
   4415  1.1  bouyer 	for (i = 0; i < sc->sc_reply_post_qdepth; i++) {
   4416  1.1  bouyer 		kva64[i] = 0xffffffffffffffffllu;
   4417  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s:    %d:  %p = 0x%" PRIx64 "\n",
   4418  1.1  bouyer 		    DEVNAME(sc), i, &kva64[i], kva64[i]);
   4419  1.1  bouyer 	}
   4420  1.1  bouyer 
   4421  1.1  bouyer 	return (0);
   4422  1.1  bouyer 
   4423  1.1  bouyer free_reply_freeq:
   4424  1.1  bouyer 
   4425  1.1  bouyer 	mpii_dmamem_free(sc, sc->sc_reply_freeq);
   4426  1.1  bouyer 	return (1);
   4427  1.1  bouyer }
   4428  1.1  bouyer 
   4429  1.1  bouyer static void
   4430  1.1  bouyer mpii_init_queues(struct mpii_softc *sc)
   4431  1.1  bouyer {
   4432  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "%s:  mpii_init_queues\n", DEVNAME(sc));
   4433  1.1  bouyer 
   4434  1.1  bouyer 	sc->sc_reply_free_host_index = sc->sc_reply_free_qdepth - 1;
   4435  1.1  bouyer 	sc->sc_reply_post_host_index = 0;
   4436  1.1  bouyer 	mpii_write_reply_free(sc, sc->sc_reply_free_host_index);
   4437  1.1  bouyer 	mpii_write_reply_post(sc, sc->sc_reply_post_host_index);
   4438  1.1  bouyer }
   4439  1.1  bouyer 
   4440  1.1  bouyer static void
   4441  1.1  bouyer mpii_wait(struct mpii_softc *sc, struct mpii_ccb *ccb)
   4442  1.1  bouyer {
   4443  1.1  bouyer 	struct mpii_ccb_wait	mpii_ccb_wait;
   4444  1.1  bouyer 	void			(*done)(struct mpii_ccb *);
   4445  1.1  bouyer 	void			*cookie;
   4446  1.1  bouyer 
   4447  1.1  bouyer 	done = ccb->ccb_done;
   4448  1.1  bouyer 	cookie = ccb->ccb_cookie;
   4449  1.1  bouyer 
   4450  1.1  bouyer 	ccb->ccb_done = mpii_wait_done;
   4451  1.1  bouyer 	ccb->ccb_cookie = &mpii_ccb_wait;
   4452  1.1  bouyer 
   4453  1.1  bouyer 	mutex_init(&mpii_ccb_wait.mpii_ccbw_mtx, MUTEX_DEFAULT, IPL_BIO);
   4454  1.1  bouyer 	cv_init(&mpii_ccb_wait.mpii_ccbw_cv, "mpii_wait");
   4455  1.1  bouyer 
   4456  1.1  bouyer 	/* XXX this will wait forever for the ccb to complete */
   4457  1.1  bouyer 
   4458  1.1  bouyer 	mpii_start(sc, ccb);
   4459  1.1  bouyer 
   4460  1.1  bouyer 	mutex_enter(&mpii_ccb_wait.mpii_ccbw_mtx);
   4461  1.1  bouyer 	while (ccb->ccb_cookie != NULL) {
   4462  1.1  bouyer 		cv_wait(&mpii_ccb_wait.mpii_ccbw_cv,
   4463  1.1  bouyer 		    &mpii_ccb_wait.mpii_ccbw_mtx);
   4464  1.1  bouyer 	}
   4465  1.1  bouyer 	mutex_exit(&mpii_ccb_wait.mpii_ccbw_mtx);
   4466  1.1  bouyer 	mutex_destroy(&mpii_ccb_wait.mpii_ccbw_mtx);
   4467  1.1  bouyer 	cv_destroy(&mpii_ccb_wait.mpii_ccbw_cv);
   4468  1.1  bouyer 
   4469  1.1  bouyer 	ccb->ccb_cookie = cookie;
   4470  1.1  bouyer 	done(ccb);
   4471  1.1  bouyer }
   4472  1.1  bouyer 
   4473  1.1  bouyer static void
   4474  1.1  bouyer mpii_wait_done(struct mpii_ccb *ccb)
   4475  1.1  bouyer {
   4476  1.1  bouyer 	struct mpii_ccb_wait	*mpii_ccb_waitp = ccb->ccb_cookie;
   4477  1.1  bouyer 
   4478  1.1  bouyer 	mutex_enter(&mpii_ccb_waitp->mpii_ccbw_mtx);
   4479  1.1  bouyer 	ccb->ccb_cookie = NULL;
   4480  1.1  bouyer 	cv_signal(&mpii_ccb_waitp->mpii_ccbw_cv);
   4481  1.1  bouyer 	mutex_exit(&mpii_ccb_waitp->mpii_ccbw_mtx);
   4482  1.1  bouyer }
   4483  1.1  bouyer 
   4484  1.1  bouyer static void
   4485  1.1  bouyer mpii_minphys(struct buf *bp)
   4486  1.1  bouyer {
   4487  1.1  bouyer 	DNPRINTF(MPII_D_MISC, "mpii_minphys: %d\n", bp->b_bcount);
   4488  1.1  bouyer 
   4489  1.1  bouyer 	/* XXX currently using MPII_MAXFER = MAXPHYS */
   4490  1.1  bouyer 	if (bp->b_bcount > MPII_MAXFER) {
   4491  1.1  bouyer 		bp->b_bcount = MPII_MAXFER;
   4492  1.1  bouyer 		minphys(bp);
   4493  1.1  bouyer 	}
   4494  1.1  bouyer }
   4495  1.1  bouyer 
   4496  1.1  bouyer static void
   4497  1.1  bouyer mpii_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
   4498  1.1  bouyer     void *arg)
   4499  1.1  bouyer {
   4500  1.1  bouyer 	struct scsipi_periph	*periph;
   4501  1.1  bouyer 	struct scsipi_xfer	*xs;
   4502  1.1  bouyer 	struct scsipi_adapter	*adapt = chan->chan_adapter;
   4503  1.1  bouyer 	struct mpii_softc	*sc = device_private(adapt->adapt_dev);
   4504  1.1  bouyer 	struct mpii_ccb		*ccb;
   4505  1.1  bouyer 	struct mpii_ccb_bundle	*mcb;
   4506  1.1  bouyer 	struct mpii_msg_scsi_io	*io;
   4507  1.1  bouyer 	struct mpii_device	*dev;
   4508  1.1  bouyer 	int			target;
   4509  1.1  bouyer 	int timeout;
   4510  1.1  bouyer 
   4511  1.1  bouyer 	DNPRINTF(MPII_D_CMD, "%s: mpii_scsipi_request\n", DEVNAME(sc));
   4512  1.1  bouyer 	switch (req) {
   4513  1.1  bouyer 	case ADAPTER_REQ_GROW_RESOURCES:
   4514  1.1  bouyer 		/* Not supported. */
   4515  1.1  bouyer 		return;
   4516  1.1  bouyer 	case ADAPTER_REQ_SET_XFER_MODE:
   4517  1.1  bouyer 	{
   4518  1.1  bouyer 		struct scsipi_xfer_mode *xm = arg;
   4519  1.1  bouyer 		xm->xm_mode = PERIPH_CAP_TQING;
   4520  1.1  bouyer 		xm->xm_period = 0;
   4521  1.1  bouyer 		xm->xm_offset = 0;
   4522  1.1  bouyer 		scsipi_async_event(&sc->sc_chan, ASYNC_EVENT_XFER_MODE, xm);
   4523  1.1  bouyer 		return;
   4524  1.1  bouyer 	}
   4525  1.1  bouyer 	case ADAPTER_REQ_RUN_XFER:
   4526  1.1  bouyer 		break;
   4527  1.1  bouyer 	}
   4528  1.1  bouyer 
   4529  1.1  bouyer 	xs = arg;
   4530  1.1  bouyer 	periph = xs->xs_periph;
   4531  1.1  bouyer 	target = periph->periph_target;
   4532  1.1  bouyer 
   4533  1.1  bouyer 	if (xs->cmdlen > MPII_CDB_LEN) {
   4534  1.1  bouyer 		DNPRINTF(MPII_D_CMD, "%s: CBD too big %d\n",
   4535  1.1  bouyer 		    DEVNAME(sc), xs->cmdlen);
   4536  1.1  bouyer 		bzero(&xs->sense, sizeof(xs->sense));
   4537  1.1  bouyer 		xs->sense.scsi_sense.response_code =
   4538  1.1  bouyer 		    SSD_RCODE_VALID | SSD_RCODE_CURRENT;
   4539  1.1  bouyer 		xs->sense.scsi_sense.flags = SKEY_ILLEGAL_REQUEST;
   4540  1.1  bouyer 		xs->sense.scsi_sense.asc = 0x20;
   4541  1.1  bouyer 		xs->error = XS_SENSE;
   4542  1.1  bouyer 		scsipi_done(xs);
   4543  1.1  bouyer 		return;
   4544  1.1  bouyer 	}
   4545  1.1  bouyer 
   4546  1.1  bouyer 	if ((dev = sc->sc_devs[target]) == NULL) {
   4547  1.1  bouyer 		/* device no longer exists */
   4548  1.1  bouyer 		xs->error = XS_SELTIMEOUT;
   4549  1.1  bouyer 		scsipi_done(xs);
   4550  1.1  bouyer 		return;
   4551  1.1  bouyer 	}
   4552  1.1  bouyer 
   4553  1.1  bouyer 	ccb = mpii_get_ccb(sc, MPII_NOSLEEP);
   4554  1.1  bouyer 	if (ccb == NULL) {
   4555  1.1  bouyer 		xs->error = XS_RESOURCE_SHORTAGE;
   4556  1.1  bouyer 		scsipi_done(xs);
   4557  1.1  bouyer 		return;
   4558  1.1  bouyer 	}
   4559  1.1  bouyer 
   4560  1.1  bouyer 	DNPRINTF(MPII_D_CMD, "%s: ccb_smid: %d xs->xs_control: 0x%x\n",
   4561  1.1  bouyer 	    DEVNAME(sc), ccb->ccb_smid, xs->xs_control);
   4562  1.1  bouyer 
   4563  1.1  bouyer 	ccb->ccb_cookie = xs;
   4564  1.1  bouyer 	ccb->ccb_done = mpii_scsi_cmd_done;
   4565  1.1  bouyer 	ccb->ccb_dev_handle = dev->dev_handle;
   4566  1.1  bouyer 
   4567  1.1  bouyer 	mcb = ccb->ccb_cmd;
   4568  1.1  bouyer 	io = &mcb->mcb_io;
   4569  1.1  bouyer 
   4570  1.1  bouyer 	io->function = MPII_FUNCTION_SCSI_IO_REQUEST;
   4571  1.1  bouyer 	io->sense_buffer_length = sizeof(xs->sense);
   4572  1.1  bouyer 	io->sgl_offset0 = 24; /* XXX fix this */
   4573  1.1  bouyer 	io->io_flags = htole16(xs->cmdlen);
   4574  1.1  bouyer 	io->dev_handle = htole16(ccb->ccb_dev_handle);
   4575  1.1  bouyer 	io->lun[0] = htobe16(periph->periph_lun);
   4576  1.1  bouyer 
   4577  1.1  bouyer 	switch (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
   4578  1.1  bouyer 	case XS_CTL_DATA_IN:
   4579  1.1  bouyer 		io->direction = MPII_SCSIIO_DIR_READ;
   4580  1.1  bouyer 		break;
   4581  1.1  bouyer 	case XS_CTL_DATA_OUT:
   4582  1.1  bouyer 		io->direction = MPII_SCSIIO_DIR_WRITE;
   4583  1.1  bouyer 		break;
   4584  1.1  bouyer 	default:
   4585  1.1  bouyer 		io->direction = MPII_SCSIIO_DIR_NONE;
   4586  1.1  bouyer 	}
   4587  1.1  bouyer 
   4588  1.1  bouyer 	io->tagging = MPII_SCSIIO_ATTR_SIMPLE_Q;
   4589  1.1  bouyer 
   4590  1.1  bouyer 	memcpy(io->cdb, xs->cmd, xs->cmdlen);
   4591  1.1  bouyer 
   4592  1.1  bouyer 	io->data_length = htole32(xs->datalen);
   4593  1.1  bouyer 
   4594  1.1  bouyer 	io->sense_buffer_low_address = htole32(ccb->ccb_cmd_dva +
   4595  1.1  bouyer 	    ((u_int8_t *)&mcb->mcb_sense - (u_int8_t *)mcb));
   4596  1.1  bouyer 
   4597  1.1  bouyer 	if (mpii_load_xs(ccb) != 0) {
   4598  1.1  bouyer 		xs->error = XS_DRIVER_STUFFUP;
   4599  1.1  bouyer 		mpii_put_ccb(sc, ccb);
   4600  1.1  bouyer 		scsipi_done(xs);
   4601  1.1  bouyer 		return;
   4602  1.1  bouyer 	}
   4603  1.1  bouyer 
   4604  1.1  bouyer 	DNPRINTF(MPII_D_CMD, "%s:  sizeof(mpii_msg_scsi_io): %ld "
   4605  1.1  bouyer 	    "sizeof(mpii_ccb_bundle): %ld sge offset: 0x%02lx\n",
   4606  1.1  bouyer 	    DEVNAME(sc), sizeof(struct mpii_msg_scsi_io),
   4607  1.1  bouyer 	    sizeof(struct mpii_ccb_bundle),
   4608  1.1  bouyer 	    (u_int8_t *)&mcb->mcb_sgl[0] - (u_int8_t *)mcb);
   4609  1.1  bouyer 
   4610  1.1  bouyer 	DNPRINTF(MPII_D_CMD, "%s   sgl[0]: 0x%04x 0%04x 0x%04x\n",
   4611  1.1  bouyer 	    DEVNAME(sc), mcb->mcb_sgl[0].sg_hdr, mcb->mcb_sgl[0].sg_lo_addr,
   4612  1.1  bouyer 	    mcb->mcb_sgl[0].sg_hi_addr);
   4613  1.1  bouyer 
   4614  1.1  bouyer 	DNPRINTF(MPII_D_CMD, "%s:  Offset0: 0x%02x\n", DEVNAME(sc),
   4615  1.1  bouyer 	    io->sgl_offset0);
   4616  1.1  bouyer 
   4617  1.1  bouyer 	if (xs->xs_control & XS_CTL_POLL) {
   4618  1.1  bouyer 		if (mpii_poll(sc, ccb) != 0) {
   4619  1.1  bouyer 			xs->error = XS_DRIVER_STUFFUP;
   4620  1.1  bouyer 			mpii_put_ccb(sc, ccb);
   4621  1.1  bouyer 			scsipi_done(xs);
   4622  1.1  bouyer 		}
   4623  1.1  bouyer 		return;
   4624  1.1  bouyer 	}
   4625  1.1  bouyer 	timeout = mstohz(xs->timeout);
   4626  1.1  bouyer 	if (timeout == 0)
   4627  1.1  bouyer 		timeout = 1;
   4628  1.1  bouyer 	callout_reset(&xs->xs_callout, timeout, mpii_scsi_cmd_tmo, ccb);
   4629  1.1  bouyer 
   4630  1.1  bouyer 	DNPRINTF(MPII_D_CMD, "%s:    mpii_scsipi_request(): opcode: %02x "
   4631  1.1  bouyer 	    "datalen: %d\n", DEVNAME(sc), xs->cmd->opcode, xs->datalen);
   4632  1.1  bouyer 
   4633  1.1  bouyer 	mpii_start(sc, ccb);
   4634  1.1  bouyer }
   4635  1.1  bouyer 
   4636  1.1  bouyer static void
   4637  1.1  bouyer mpii_scsi_cmd_tmo(void *xccb)
   4638  1.1  bouyer {
   4639  1.1  bouyer 	struct mpii_ccb		*ccb = xccb;
   4640  1.1  bouyer 	struct mpii_softc	*sc = ccb->ccb_sc;
   4641  1.1  bouyer 
   4642  1.1  bouyer 	printf("%s: mpii_scsi_cmd_tmo\n", DEVNAME(sc));
   4643  1.1  bouyer 
   4644  1.1  bouyer 	mutex_enter(&sc->sc_ccb_mtx);
   4645  1.1  bouyer 	if (ccb->ccb_state == MPII_CCB_QUEUED) {
   4646  1.1  bouyer 		ccb->ccb_state = MPII_CCB_TIMEOUT;
   4647  1.1  bouyer 		workqueue_enqueue(sc->sc_ssb_tmowk, &ccb->u.ccb_wk, NULL);
   4648  1.1  bouyer 	}
   4649  1.1  bouyer 	mutex_exit(&sc->sc_ccb_mtx);
   4650  1.1  bouyer }
   4651  1.1  bouyer 
   4652  1.1  bouyer static void
   4653  1.1  bouyer mpii_scsi_cmd_tmo_handler(struct work *wk, void *cookie)
   4654  1.1  bouyer {
   4655  1.1  bouyer 	struct mpii_softc			*sc = cookie;
   4656  1.1  bouyer 	struct mpii_ccb				*tccb;
   4657  1.1  bouyer 	struct mpii_ccb				*ccb;
   4658  1.1  bouyer 	struct mpii_msg_scsi_task_request	*stq;
   4659  1.1  bouyer 
   4660  1.1  bouyer 	ccb = (void *)wk;
   4661  1.1  bouyer 	tccb = mpii_get_ccb(sc, 0);
   4662  1.1  bouyer 
   4663  1.1  bouyer 	mutex_enter(&sc->sc_ccb_mtx);
   4664  1.1  bouyer 	if (ccb->ccb_state != MPII_CCB_TIMEOUT) {
   4665  1.1  bouyer 		mpii_put_ccb(sc, tccb);
   4666  1.1  bouyer 	}
   4667  1.1  bouyer 	/* should remove any other ccbs for the same dev handle */
   4668  1.1  bouyer 	mutex_exit(&sc->sc_ccb_mtx);
   4669  1.1  bouyer 
   4670  1.1  bouyer 	stq = tccb->ccb_cmd;
   4671  1.1  bouyer 	stq->function = MPII_FUNCTION_SCSI_TASK_MGMT;
   4672  1.1  bouyer 	stq->task_type = MPII_SCSI_TASK_TARGET_RESET;
   4673  1.1  bouyer 	stq->dev_handle = htole16(ccb->ccb_dev_handle);
   4674  1.1  bouyer 
   4675  1.1  bouyer 	tccb->ccb_done = mpii_scsi_cmd_tmo_done;
   4676  1.1  bouyer 	mpii_start(sc, tccb);
   4677  1.1  bouyer }
   4678  1.1  bouyer 
   4679  1.1  bouyer static void
   4680  1.1  bouyer mpii_scsi_cmd_tmo_done(struct mpii_ccb *tccb)
   4681  1.1  bouyer {
   4682  1.1  bouyer         mpii_put_ccb(tccb->ccb_sc, tccb);
   4683  1.1  bouyer }
   4684  1.1  bouyer 
   4685  1.3  kardel static u_int8_t
   4686  1.3  kardel map_scsi_status(u_int8_t mpii_scsi_status)
   4687  1.3  kardel {
   4688  1.3  kardel 	u_int8_t scsi_status;
   4689  1.3  kardel 
   4690  1.3  kardel 	switch (mpii_scsi_status)
   4691  1.3  kardel 	{
   4692  1.3  kardel 	case MPII_SCSIIO_ERR_STATUS_SUCCESS:
   4693  1.3  kardel 		scsi_status = SCSI_OK;
   4694  1.3  kardel 		break;
   4695  1.3  kardel 
   4696  1.3  kardel 	case MPII_SCSIIO_ERR_STATUS_CHECK_COND:
   4697  1.3  kardel 		scsi_status = SCSI_CHECK;
   4698  1.3  kardel 		break;
   4699  1.3  kardel 
   4700  1.3  kardel 	case MPII_SCSIIO_ERR_STATUS_BUSY:
   4701  1.3  kardel 		scsi_status = SCSI_BUSY;
   4702  1.3  kardel 		break;
   4703  1.3  kardel 
   4704  1.3  kardel 	case MPII_SCSIIO_ERR_STATUS_INTERMEDIATE:
   4705  1.3  kardel 		scsi_status = SCSI_INTERM;
   4706  1.3  kardel 		break;
   4707  1.3  kardel 
   4708  1.3  kardel 	case MPII_SCSIIO_ERR_STATUS_INTERMEDIATE_CONDMET:
   4709  1.3  kardel 		scsi_status = SCSI_INTERM;
   4710  1.3  kardel 		break;
   4711  1.3  kardel 
   4712  1.3  kardel 	case MPII_SCSIIO_ERR_STATUS_RESERVATION_CONFLICT:
   4713  1.3  kardel 		scsi_status = SCSI_RESV_CONFLICT;
   4714  1.3  kardel 		break;
   4715  1.3  kardel 
   4716  1.3  kardel 	case MPII_SCSIIO_ERR_STATUS_CMD_TERM:
   4717  1.3  kardel 	case MPII_SCSIIO_ERR_STATUS_TASK_ABORTED:
   4718  1.3  kardel 		scsi_status = SCSI_TERMINATED;
   4719  1.3  kardel 		break;
   4720  1.3  kardel 
   4721  1.3  kardel 	case MPII_SCSIIO_ERR_STATUS_TASK_SET_FULL:
   4722  1.3  kardel 		scsi_status = SCSI_QUEUE_FULL;
   4723  1.3  kardel 		break;
   4724  1.3  kardel 
   4725  1.3  kardel 	case MPII_SCSIIO_ERR_STATUS_ACA_ACTIVE:
   4726  1.3  kardel 		scsi_status = SCSI_ACA_ACTIVE;
   4727  1.3  kardel 		break;
   4728  1.3  kardel 
   4729  1.3  kardel 	default:
   4730  1.3  kardel 		/* XXX: for the lack of anything better and other than OK */
   4731  1.3  kardel 		scsi_status = 0xFF;
   4732  1.3  kardel 		break;
   4733  1.3  kardel 	}
   4734  1.3  kardel 
   4735  1.3  kardel 	return scsi_status;
   4736  1.3  kardel }
   4737  1.1  bouyer 
   4738  1.1  bouyer static void
   4739  1.1  bouyer mpii_scsi_cmd_done(struct mpii_ccb *ccb)
   4740  1.1  bouyer {
   4741  1.1  bouyer 	struct mpii_msg_scsi_io_error	*sie;
   4742  1.1  bouyer 	struct mpii_softc	*sc = ccb->ccb_sc;
   4743  1.1  bouyer 	struct scsipi_xfer	*xs = ccb->ccb_cookie;
   4744  1.1  bouyer 	struct mpii_ccb_bundle	*mcb = ccb->ccb_cmd;
   4745  1.1  bouyer 	bus_dmamap_t		dmap = ccb->ccb_dmamap;
   4746  1.1  bouyer 	bool			timeout = 0;
   4747  1.1  bouyer 
   4748  1.1  bouyer 	callout_stop(&xs->xs_callout);
   4749  1.1  bouyer 	mutex_enter(&sc->sc_ccb_mtx);
   4750  1.1  bouyer 	if (ccb->ccb_state == MPII_CCB_TIMEOUT)
   4751  1.1  bouyer 		timeout = 1;
   4752  1.1  bouyer 	ccb->ccb_state = MPII_CCB_READY;
   4753  1.1  bouyer 	mutex_exit(&sc->sc_ccb_mtx);
   4754  1.1  bouyer 
   4755  1.1  bouyer 	if (xs->datalen != 0) {
   4756  1.1  bouyer 		bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
   4757  1.1  bouyer 		    (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_POSTREAD :
   4758  1.1  bouyer 		    BUS_DMASYNC_POSTWRITE);
   4759  1.1  bouyer 
   4760  1.1  bouyer 		bus_dmamap_unload(sc->sc_dmat, dmap);
   4761  1.1  bouyer 	}
   4762  1.1  bouyer 
   4763  1.1  bouyer 	xs->error = XS_NOERROR;
   4764  1.1  bouyer 	xs->resid = 0;
   4765  1.1  bouyer 
   4766  1.1  bouyer 	if (ccb->ccb_rcb == NULL) {
   4767  1.1  bouyer 		/* no scsi error, we're ok so drop out early */
   4768  1.1  bouyer 		xs->status = SCSI_OK;
   4769  1.1  bouyer 		mpii_put_ccb(sc, ccb);
   4770  1.1  bouyer 		scsipi_done(xs);
   4771  1.1  bouyer 		return;
   4772  1.1  bouyer 	}
   4773  1.1  bouyer 
   4774  1.1  bouyer 	sie = ccb->ccb_rcb->rcb_reply;
   4775  1.1  bouyer 
   4776  1.1  bouyer 	DNPRINTF(MPII_D_CMD, "%s: mpii_scsi_cmd_done xs cmd: 0x%02x len: %d "
   4777  1.1  bouyer 	    "xs_control 0x%x\n", DEVNAME(sc), xs->cmd->opcode, xs->datalen,
   4778  1.1  bouyer 	    xs->xs_control);
   4779  1.1  bouyer 	DNPRINTF(MPII_D_CMD, "%s:  dev_handle: %d msg_length: %d "
   4780  1.1  bouyer 	    "function: 0x%02x\n", DEVNAME(sc), le16toh(sie->dev_handle),
   4781  1.1  bouyer 	    sie->msg_length, sie->function);
   4782  1.1  bouyer 	DNPRINTF(MPII_D_CMD, "%s:  vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc),
   4783  1.1  bouyer 	    sie->vp_id, sie->vf_id);
   4784  1.1  bouyer 	DNPRINTF(MPII_D_CMD, "%s:  scsi_status: 0x%02x scsi_state: 0x%02x "
   4785  1.1  bouyer 	    "ioc_status: 0x%04x\n", DEVNAME(sc), sie->scsi_status,
   4786  1.1  bouyer 	    sie->scsi_state, le16toh(sie->ioc_status));
   4787  1.1  bouyer 	DNPRINTF(MPII_D_CMD, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
   4788  1.1  bouyer 	    le32toh(sie->ioc_loginfo));
   4789  1.1  bouyer 	DNPRINTF(MPII_D_CMD, "%s:  transfer_count: %d\n", DEVNAME(sc),
   4790  1.1  bouyer 	    le32toh(sie->transfer_count));
   4791  1.1  bouyer 	DNPRINTF(MPII_D_CMD, "%s:  sense_count: %d\n", DEVNAME(sc),
   4792  1.1  bouyer 	    le32toh(sie->sense_count));
   4793  1.1  bouyer 	DNPRINTF(MPII_D_CMD, "%s:  response_info: 0x%08x\n", DEVNAME(sc),
   4794  1.1  bouyer 	    le32toh(sie->response_info));
   4795  1.1  bouyer 	DNPRINTF(MPII_D_CMD, "%s:  task_tag: 0x%04x\n", DEVNAME(sc),
   4796  1.1  bouyer 	    le16toh(sie->task_tag));
   4797  1.1  bouyer 	DNPRINTF(MPII_D_CMD, "%s:  bidirectional_transfer_count: 0x%08x\n",
   4798  1.1  bouyer 	    DEVNAME(sc), le32toh(sie->bidirectional_transfer_count));
   4799  1.1  bouyer 
   4800  1.3  kardel 	xs->status = map_scsi_status(sie->scsi_status);
   4801  1.3  kardel 
   4802  1.1  bouyer 	switch (le16toh(sie->ioc_status) & MPII_IOCSTATUS_MASK) {
   4803  1.1  bouyer 	case MPII_IOCSTATUS_SCSI_DATA_UNDERRUN:
   4804  1.3  kardel 		switch (sie->scsi_status) {
   4805  1.3  kardel 		case MPII_SCSIIO_ERR_STATUS_CHECK_COND:
   4806  1.3  kardel 			xs->error = XS_SENSE;
   4807  1.3  kardel 			/*FALLTHROUGH*/
   4808  1.3  kardel 		case MPII_SCSIIO_ERR_STATUS_SUCCESS:
   4809  1.1  bouyer 			xs->resid = xs->datalen - le32toh(sie->transfer_count);
   4810  1.1  bouyer 			break;
   4811  1.3  kardel 
   4812  1.1  bouyer 		default:
   4813  1.1  bouyer 			xs->error = XS_DRIVER_STUFFUP;
   4814  1.1  bouyer 			break;
   4815  1.1  bouyer 		}
   4816  1.1  bouyer 		break;
   4817  1.3  kardel 
   4818  1.1  bouyer 	case MPII_IOCSTATUS_SUCCESS:
   4819  1.1  bouyer 	case MPII_IOCSTATUS_SCSI_RECOVERED_ERROR:
   4820  1.3  kardel 		switch (sie->scsi_status) {
   4821  1.3  kardel 		case MPII_SCSIIO_ERR_STATUS_SUCCESS:
   4822  1.3  kardel 			/*
   4823  1.3  kardel 			 * xs->resid = 0; - already set above
   4824  1.3  kardel 			 *
   4825  1.3  kardel 			 * XXX: check whether UNDERUN strategy
   4826  1.3  kardel 			 * would be appropriate here too.
   4827  1.3  kardel 			 * that would allow joining these cases.
   4828  1.3  kardel 			 */
   4829  1.1  bouyer 			break;
   4830  1.1  bouyer 
   4831  1.3  kardel 		case MPII_SCSIIO_ERR_STATUS_CHECK_COND:
   4832  1.1  bouyer 			xs->error = XS_SENSE;
   4833  1.1  bouyer 			break;
   4834  1.3  kardel 
   4835  1.3  kardel 		case MPII_SCSIIO_ERR_STATUS_BUSY:
   4836  1.3  kardel 		case MPII_SCSIIO_ERR_STATUS_TASK_SET_FULL:
   4837  1.1  bouyer 			xs->error = XS_BUSY;
   4838  1.1  bouyer 			break;
   4839  1.1  bouyer 
   4840  1.1  bouyer 		default:
   4841  1.1  bouyer 			xs->error = XS_DRIVER_STUFFUP;
   4842  1.1  bouyer 		}
   4843  1.1  bouyer 		break;
   4844  1.1  bouyer 
   4845  1.1  bouyer 	case MPII_IOCSTATUS_BUSY:
   4846  1.1  bouyer 	case MPII_IOCSTATUS_INSUFFICIENT_RESOURCES:
   4847  1.1  bouyer 		xs->error = XS_BUSY;
   4848  1.1  bouyer 		break;
   4849  1.1  bouyer 
   4850  1.1  bouyer 	case MPII_IOCSTATUS_SCSI_IOC_TERMINATED:
   4851  1.1  bouyer 	case MPII_IOCSTATUS_SCSI_TASK_TERMINATED:
   4852  1.1  bouyer 		xs->error = timeout ? XS_TIMEOUT : XS_RESET;
   4853  1.1  bouyer 		break;
   4854  1.1  bouyer 
   4855  1.1  bouyer 	case MPII_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
   4856  1.1  bouyer 	case MPII_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
   4857  1.1  bouyer 		xs->error = XS_SELTIMEOUT;
   4858  1.1  bouyer 		break;
   4859  1.1  bouyer 
   4860  1.1  bouyer 	default:
   4861  1.1  bouyer 		xs->error = XS_DRIVER_STUFFUP;
   4862  1.1  bouyer 		break;
   4863  1.1  bouyer 	}
   4864  1.1  bouyer 
   4865  1.1  bouyer 	if (sie->scsi_state & MPII_SCSIIO_ERR_STATE_AUTOSENSE_VALID)
   4866  1.1  bouyer 		memcpy(&xs->sense, &mcb->mcb_sense, sizeof(xs->sense));
   4867  1.1  bouyer 
   4868  1.1  bouyer 	DNPRINTF(MPII_D_CMD, "%s:  xs err: %d status: %#x\n", DEVNAME(sc),
   4869  1.1  bouyer 	    xs->error, xs->status);
   4870  1.1  bouyer 
   4871  1.1  bouyer 	mpii_push_reply(sc, ccb->ccb_rcb);
   4872  1.1  bouyer 	mpii_put_ccb(sc, ccb);
   4873  1.1  bouyer 	scsipi_done(xs);
   4874  1.1  bouyer }
   4875  1.1  bouyer 
   4876  1.1  bouyer #if 0
   4877  1.1  bouyer static int
   4878  1.1  bouyer mpii_ioctl_cache(struct scsi_link *link, u_long cmd, struct dk_cache *dc)
   4879  1.1  bouyer {
   4880  1.1  bouyer 	struct mpii_softc *sc = (struct mpii_softc *)link->adapter_softc;
   4881  1.1  bouyer 	struct mpii_device *dev = sc->sc_devs[link->target];
   4882  1.1  bouyer 	struct mpii_cfg_raid_vol_pg0 *vpg;
   4883  1.1  bouyer 	struct mpii_msg_raid_action_request *req;
   4884  1.1  bouyer  	struct mpii_msg_raid_action_reply *rep;
   4885  1.1  bouyer 	struct mpii_cfg_hdr hdr;
   4886  1.1  bouyer 	struct mpii_ccb	*ccb;
   4887  1.1  bouyer 	u_int32_t addr = MPII_CFG_RAID_VOL_ADDR_HANDLE | dev->dev_handle;
   4888  1.1  bouyer 	size_t pagelen;
   4889  1.1  bouyer 	int rv = 0;
   4890  1.1  bouyer 	int enabled;
   4891  1.1  bouyer 
   4892  1.1  bouyer 	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
   4893  1.1  bouyer 	    addr, MPII_PG_POLL, &hdr) != 0)
   4894  1.1  bouyer 		return (EINVAL);
   4895  1.1  bouyer 
   4896  1.1  bouyer 	pagelen = hdr.page_length * 4;
   4897  1.1  bouyer 	vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_CANFAIL | M_ZERO);
   4898  1.1  bouyer 	if (vpg == NULL)
   4899  1.1  bouyer 		return (ENOMEM);
   4900  1.1  bouyer 
   4901  1.1  bouyer 	if (mpii_req_cfg_page(sc, addr, MPII_PG_POLL, &hdr, 1,
   4902  1.1  bouyer 	    vpg, pagelen) != 0) {
   4903  1.1  bouyer 		rv = EINVAL;
   4904  1.1  bouyer 		goto done;
   4905  1.1  bouyer 		free(vpg, M_TEMP);
   4906  1.1  bouyer 		return (EINVAL);
   4907  1.1  bouyer 	}
   4908  1.1  bouyer 
   4909  1.1  bouyer 	enabled = ((le16toh(vpg->volume_settings) &
   4910  1.1  bouyer 	    MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_MASK) ==
   4911  1.1  bouyer 	    MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_ENABLED) ? 1 : 0;
   4912  1.1  bouyer 
   4913  1.1  bouyer 	if (cmd == DIOCGCACHE) {
   4914  1.1  bouyer 		dc->wrcache = enabled;
   4915  1.1  bouyer 		dc->rdcache = 0;
   4916  1.1  bouyer 		goto done;
   4917  1.1  bouyer 	} /* else DIOCSCACHE */
   4918  1.1  bouyer 
   4919  1.1  bouyer 	if (dc->rdcache) {
   4920  1.1  bouyer 		rv = EOPNOTSUPP;
   4921  1.1  bouyer 		goto done;
   4922  1.1  bouyer 	}
   4923  1.1  bouyer 
   4924  1.1  bouyer 	if (((dc->wrcache) ? 1 : 0) == enabled)
   4925  1.1  bouyer 		goto done;
   4926  1.1  bouyer 
   4927  1.1  bouyer 	ccb = mpii_get_ccb(sc, MPII_NOSLEEP);
   4928  1.1  bouyer 	if (ccb == NULL) {
   4929  1.1  bouyer 		rv = ENOMEM;
   4930  1.1  bouyer 		goto done;
   4931  1.1  bouyer 	}
   4932  1.1  bouyer 
   4933  1.1  bouyer 	ccb->ccb_done = mpii_empty_done;
   4934  1.1  bouyer 
   4935  1.1  bouyer 	req = ccb->ccb_cmd;
   4936  1.1  bouyer 	bzero(req, sizeof(*req));
   4937  1.1  bouyer 	req->function = MPII_FUNCTION_RAID_ACTION;
   4938  1.1  bouyer 	req->action = MPII_RAID_ACTION_CHANGE_VOL_WRITE_CACHE;
   4939  1.1  bouyer 	req->vol_dev_handle = htole16(dev->dev_handle);
   4940  1.1  bouyer 	req->action_data = htole32(dc->wrcache ?
   4941  1.1  bouyer 	    MPII_RAID_VOL_WRITE_CACHE_ENABLE :
   4942  1.1  bouyer 	    MPII_RAID_VOL_WRITE_CACHE_DISABLE);
   4943  1.1  bouyer 
   4944  1.1  bouyer 	if (mpii_poll(sc, ccb) != 0) {
   4945  1.1  bouyer 		rv = EIO;
   4946  1.1  bouyer 		goto done;
   4947  1.1  bouyer 	}
   4948  1.1  bouyer 
   4949  1.1  bouyer 	if (ccb->ccb_rcb != NULL) {
   4950  1.1  bouyer 		rep = ccb->ccb_rcb->rcb_reply;
   4951  1.1  bouyer 		if ((rep->ioc_status != MPII_IOCSTATUS_SUCCESS) ||
   4952  1.1  bouyer 		    ((rep->action_data[0] &
   4953  1.1  bouyer 		     MPII_RAID_VOL_WRITE_CACHE_MASK) !=
   4954  1.1  bouyer 		    (dc->wrcache ? MPII_RAID_VOL_WRITE_CACHE_ENABLE :
   4955  1.1  bouyer 		     MPII_RAID_VOL_WRITE_CACHE_DISABLE)))
   4956  1.1  bouyer 			rv = EINVAL;
   4957  1.1  bouyer 		mpii_push_reply(sc, ccb->ccb_rcb);
   4958  1.1  bouyer 	}
   4959  1.1  bouyer 
   4960  1.1  bouyer 	mpii_put_ccb(sc, ccb);
   4961  1.1  bouyer 
   4962  1.1  bouyer done:
   4963  1.1  bouyer 	free(vpg, M_TEMP);
   4964  1.1  bouyer 	return (rv);
   4965  1.1  bouyer }
   4966  1.1  bouyer #endif
   4967  1.1  bouyer static int
   4968  1.1  bouyer mpii_cache_enable(struct mpii_softc *sc, struct mpii_device *dev)
   4969  1.1  bouyer {
   4970  1.1  bouyer 	struct mpii_cfg_raid_vol_pg0 *vpg;
   4971  1.1  bouyer 	struct mpii_msg_raid_action_request *req;
   4972  1.1  bouyer  	struct mpii_msg_raid_action_reply *rep;
   4973  1.1  bouyer 	struct mpii_cfg_hdr hdr;
   4974  1.1  bouyer 	struct mpii_ccb	*ccb;
   4975  1.1  bouyer 	u_int32_t addr = MPII_CFG_RAID_VOL_ADDR_HANDLE | dev->dev_handle;
   4976  1.1  bouyer 	size_t pagelen;
   4977  1.1  bouyer 	int rv = 0;
   4978  1.1  bouyer 	int enabled;
   4979  1.1  bouyer 
   4980  1.1  bouyer 	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
   4981  1.1  bouyer 	    addr, MPII_PG_POLL, &hdr) != 0)
   4982  1.1  bouyer 		return (EINVAL);
   4983  1.1  bouyer 
   4984  1.1  bouyer 	pagelen = hdr.page_length * 4;
   4985  1.1  bouyer 	vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_CANFAIL | M_ZERO);
   4986  1.1  bouyer 	if (vpg == NULL)
   4987  1.1  bouyer 		return (ENOMEM);
   4988  1.1  bouyer 
   4989  1.1  bouyer 	if (mpii_req_cfg_page(sc, addr, MPII_PG_POLL, &hdr, 1,
   4990  1.1  bouyer 	    vpg, pagelen) != 0) {
   4991  1.1  bouyer 		rv = EINVAL;
   4992  1.1  bouyer 		goto done;
   4993  1.1  bouyer 		free(vpg, M_TEMP);
   4994  1.1  bouyer 		return (EINVAL);
   4995  1.1  bouyer 	}
   4996  1.1  bouyer 
   4997  1.1  bouyer 	enabled = ((le16toh(vpg->volume_settings) &
   4998  1.1  bouyer 	    MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_MASK) ==
   4999  1.1  bouyer 	    MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_ENABLED) ? 1 : 0;
   5000  1.1  bouyer 	aprint_normal_dev(sc->sc_dev, "target %d cache %s", dev->slot,
   5001  1.1  bouyer 	    enabled ? "enabled" : "disabled, enabling");
   5002  1.1  bouyer 	aprint_normal("\n");
   5003  1.1  bouyer 
   5004  1.1  bouyer 	if (enabled == 0)
   5005  1.1  bouyer 		goto done;
   5006  1.1  bouyer 
   5007  1.1  bouyer 	ccb = mpii_get_ccb(sc, MPII_NOSLEEP);
   5008  1.1  bouyer 	if (ccb == NULL) {
   5009  1.1  bouyer 		rv = ENOMEM;
   5010  1.1  bouyer 		goto done;
   5011  1.1  bouyer 	}
   5012  1.1  bouyer 
   5013  1.1  bouyer 	ccb->ccb_done = mpii_empty_done;
   5014  1.1  bouyer 
   5015  1.1  bouyer 	req = ccb->ccb_cmd;
   5016  1.1  bouyer 	bzero(req, sizeof(*req));
   5017  1.1  bouyer 	req->function = MPII_FUNCTION_RAID_ACTION;
   5018  1.1  bouyer 	req->action = MPII_RAID_ACTION_CHANGE_VOL_WRITE_CACHE;
   5019  1.1  bouyer 	req->vol_dev_handle = htole16(dev->dev_handle);
   5020  1.1  bouyer 	req->action_data = htole32(
   5021  1.1  bouyer 	    MPII_RAID_VOL_WRITE_CACHE_ENABLE);
   5022  1.1  bouyer 
   5023  1.1  bouyer 	if (mpii_poll(sc, ccb) != 0) {
   5024  1.1  bouyer 		rv = EIO;
   5025  1.1  bouyer 		goto done;
   5026  1.1  bouyer 	}
   5027  1.1  bouyer 
   5028  1.1  bouyer 	if (ccb->ccb_rcb != NULL) {
   5029  1.1  bouyer 		rep = ccb->ccb_rcb->rcb_reply;
   5030  1.1  bouyer 		if ((rep->ioc_status != MPII_IOCSTATUS_SUCCESS) ||
   5031  1.1  bouyer 		    ((rep->action_data[0] &
   5032  1.1  bouyer 		     MPII_RAID_VOL_WRITE_CACHE_MASK) !=
   5033  1.1  bouyer 		     MPII_RAID_VOL_WRITE_CACHE_ENABLE))
   5034  1.1  bouyer 			rv = EINVAL;
   5035  1.1  bouyer 		mpii_push_reply(sc, ccb->ccb_rcb);
   5036  1.1  bouyer 	}
   5037  1.1  bouyer 
   5038  1.1  bouyer 	mpii_put_ccb(sc, ccb);
   5039  1.1  bouyer 
   5040  1.1  bouyer done:
   5041  1.1  bouyer 	free(vpg, M_TEMP);
   5042  1.1  bouyer 	if (rv) {
   5043  1.1  bouyer 		aprint_error_dev(sc->sc_dev,
   5044  1.1  bouyer 		    "enabling cache on target %d failed (%d)\n",
   5045  1.1  bouyer 		    dev->slot, rv);
   5046  1.1  bouyer 	}
   5047  1.1  bouyer 	return (rv);
   5048  1.1  bouyer }
   5049  1.1  bouyer 
   5050  1.1  bouyer #if NBIO > 0
   5051  1.1  bouyer static int
   5052  1.1  bouyer mpii_ioctl(device_t dev, u_long cmd, void *addr)
   5053  1.1  bouyer {
   5054  1.1  bouyer 	struct mpii_softc	*sc = device_private(dev);
   5055  1.1  bouyer 	int			s, error = 0;
   5056  1.1  bouyer 
   5057  1.1  bouyer 	DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl ", DEVNAME(sc));
   5058  1.1  bouyer 	KERNEL_LOCK(1, curlwp);
   5059  1.1  bouyer 	s = splbio();
   5060  1.1  bouyer 
   5061  1.1  bouyer 	switch (cmd) {
   5062  1.1  bouyer 	case BIOCINQ:
   5063  1.1  bouyer 		DNPRINTF(MPII_D_IOCTL, "inq\n");
   5064  1.1  bouyer 		error = mpii_ioctl_inq(sc, (struct bioc_inq *)addr);
   5065  1.1  bouyer 		break;
   5066  1.1  bouyer 	case BIOCVOL:
   5067  1.1  bouyer 		DNPRINTF(MPII_D_IOCTL, "vol\n");
   5068  1.1  bouyer 		error = mpii_ioctl_vol(sc, (struct bioc_vol *)addr);
   5069  1.1  bouyer 		break;
   5070  1.1  bouyer 	case BIOCDISK:
   5071  1.1  bouyer 		DNPRINTF(MPII_D_IOCTL, "disk\n");
   5072  1.1  bouyer 		error = mpii_ioctl_disk(sc, (struct bioc_disk *)addr);
   5073  1.1  bouyer 		break;
   5074  1.1  bouyer 	default:
   5075  1.1  bouyer 		DNPRINTF(MPII_D_IOCTL, " invalid ioctl\n");
   5076  1.1  bouyer 		error = EINVAL;
   5077  1.1  bouyer 	}
   5078  1.1  bouyer 
   5079  1.1  bouyer 	splx(s);
   5080  1.1  bouyer 	KERNEL_UNLOCK_ONE(curlwp);
   5081  1.1  bouyer 	return (error);
   5082  1.1  bouyer }
   5083  1.1  bouyer 
   5084  1.1  bouyer static int
   5085  1.1  bouyer mpii_ioctl_inq(struct mpii_softc *sc, struct bioc_inq *bi)
   5086  1.1  bouyer {
   5087  1.1  bouyer 	int			i;
   5088  1.1  bouyer 
   5089  1.1  bouyer 	DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl_inq\n", DEVNAME(sc));
   5090  1.1  bouyer 
   5091  1.1  bouyer 	strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev));
   5092  1.1  bouyer 	for (i = 0; i < sc->sc_max_devices; i++)
   5093  1.1  bouyer 		if (sc->sc_devs[i] &&
   5094  1.1  bouyer 		    ISSET(sc->sc_devs[i]->flags, MPII_DF_VOLUME))
   5095  1.1  bouyer 			bi->bi_novol++;
   5096  1.1  bouyer 	return (0);
   5097  1.1  bouyer }
   5098  1.1  bouyer 
   5099  1.1  bouyer static int
   5100  1.1  bouyer mpii_ioctl_vol(struct mpii_softc *sc, struct bioc_vol *bv)
   5101  1.1  bouyer {
   5102  1.1  bouyer 	struct mpii_cfg_raid_vol_pg0	*vpg;
   5103  1.1  bouyer 	struct mpii_cfg_hdr		hdr;
   5104  1.1  bouyer 	struct mpii_device		*dev;
   5105  1.1  bouyer 	struct scsipi_periph 		*periph;
   5106  1.1  bouyer 	size_t				pagelen;
   5107  1.1  bouyer 	u_int16_t			volh;
   5108  1.1  bouyer 	int				rv, hcnt = 0;
   5109  1.1  bouyer 
   5110  1.1  bouyer 	DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl_vol %d\n",
   5111  1.1  bouyer 	    DEVNAME(sc), bv->bv_volid);
   5112  1.1  bouyer 
   5113  1.1  bouyer 	if ((dev = mpii_find_vol(sc, bv->bv_volid)) == NULL)
   5114  1.1  bouyer 		return (ENODEV);
   5115  1.1  bouyer 	volh = dev->dev_handle;
   5116  1.1  bouyer 
   5117  1.1  bouyer 	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
   5118  1.1  bouyer 	    MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0, &hdr) != 0) {
   5119  1.1  bouyer 		printf("%s: unable to fetch header for raid volume page 0\n",
   5120  1.1  bouyer 		    DEVNAME(sc));
   5121  1.1  bouyer 		return (EINVAL);
   5122  1.1  bouyer 	}
   5123  1.1  bouyer 
   5124  1.1  bouyer 	pagelen = hdr.page_length * 4;
   5125  1.1  bouyer 	vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_CANFAIL | M_ZERO);
   5126  1.1  bouyer 	if (vpg == NULL) {
   5127  1.1  bouyer 		printf("%s: unable to allocate space for raid "
   5128  1.1  bouyer 		    "volume page 0\n", DEVNAME(sc));
   5129  1.1  bouyer 		return (ENOMEM);
   5130  1.1  bouyer 	}
   5131  1.1  bouyer 
   5132  1.1  bouyer 	if (mpii_req_cfg_page(sc, MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0,
   5133  1.1  bouyer 	    &hdr, 1, vpg, pagelen) != 0) {
   5134  1.1  bouyer 		printf("%s: unable to fetch raid volume page 0\n",
   5135  1.1  bouyer 		    DEVNAME(sc));
   5136  1.1  bouyer 		free(vpg, M_TEMP);
   5137  1.1  bouyer 		return (EINVAL);
   5138  1.1  bouyer 	}
   5139  1.1  bouyer 
   5140  1.1  bouyer 	switch (vpg->volume_state) {
   5141  1.1  bouyer 	case MPII_CFG_RAID_VOL_0_STATE_ONLINE:
   5142  1.1  bouyer 	case MPII_CFG_RAID_VOL_0_STATE_OPTIMAL:
   5143  1.1  bouyer 		bv->bv_status = BIOC_SVONLINE;
   5144  1.1  bouyer 		break;
   5145  1.1  bouyer 	case MPII_CFG_RAID_VOL_0_STATE_DEGRADED:
   5146  1.1  bouyer 		if (ISSET(le32toh(vpg->volume_status),
   5147  1.1  bouyer 		    MPII_CFG_RAID_VOL_0_STATUS_RESYNC)) {
   5148  1.1  bouyer 			bv->bv_status = BIOC_SVREBUILD;
   5149  1.1  bouyer 			bv->bv_percent = dev->percent;
   5150  1.1  bouyer 		} else
   5151  1.1  bouyer 			bv->bv_status = BIOC_SVDEGRADED;
   5152  1.1  bouyer 		break;
   5153  1.1  bouyer 	case MPII_CFG_RAID_VOL_0_STATE_FAILED:
   5154  1.1  bouyer 		bv->bv_status = BIOC_SVOFFLINE;
   5155  1.1  bouyer 		break;
   5156  1.1  bouyer 	case MPII_CFG_RAID_VOL_0_STATE_INITIALIZING:
   5157  1.1  bouyer 		bv->bv_status = BIOC_SVBUILDING;
   5158  1.1  bouyer 		break;
   5159  1.1  bouyer 	case MPII_CFG_RAID_VOL_0_STATE_MISSING:
   5160  1.1  bouyer 	default:
   5161  1.1  bouyer 		bv->bv_status = BIOC_SVINVALID;
   5162  1.1  bouyer 		break;
   5163  1.1  bouyer 	}
   5164  1.1  bouyer 
   5165  1.1  bouyer 	switch (vpg->volume_type) {
   5166  1.1  bouyer 	case MPII_CFG_RAID_VOL_0_TYPE_RAID0:
   5167  1.1  bouyer 		bv->bv_level = 0;
   5168  1.1  bouyer 		break;
   5169  1.1  bouyer 	case MPII_CFG_RAID_VOL_0_TYPE_RAID1:
   5170  1.1  bouyer 		bv->bv_level = 1;
   5171  1.1  bouyer 		break;
   5172  1.1  bouyer 	case MPII_CFG_RAID_VOL_0_TYPE_RAID1E:
   5173  1.1  bouyer 	case MPII_CFG_RAID_VOL_0_TYPE_RAID10:
   5174  1.1  bouyer 		bv->bv_level = 10;
   5175  1.1  bouyer 		break;
   5176  1.1  bouyer 	default:
   5177  1.1  bouyer 		bv->bv_level = -1;
   5178  1.1  bouyer 	}
   5179  1.1  bouyer 
   5180  1.1  bouyer 	if ((rv = mpii_bio_hs(sc, NULL, 0, vpg->hot_spare_pool, &hcnt)) != 0) {
   5181  1.1  bouyer 		free(vpg, M_TEMP);
   5182  1.1  bouyer 		return (rv);
   5183  1.1  bouyer 	}
   5184  1.1  bouyer 
   5185  1.1  bouyer 	bv->bv_nodisk = vpg->num_phys_disks + hcnt;
   5186  1.1  bouyer 
   5187  1.1  bouyer 	bv->bv_size = le64toh(vpg->max_lba) * le16toh(vpg->block_size);
   5188  1.1  bouyer 
   5189  1.1  bouyer 	periph = scsipi_lookup_periph(&sc->sc_chan, dev->slot, 0);
   5190  1.1  bouyer 	if (periph != NULL) {
   5191  1.1  bouyer 		if (periph->periph_dev == NULL) {
   5192  1.1  bouyer 			snprintf(bv->bv_dev, sizeof(bv->bv_dev), "%s:%d",
   5193  1.1  bouyer 			    DEVNAME(sc), dev->slot);
   5194  1.1  bouyer 		} else {
   5195  1.1  bouyer 			strlcpy(bv->bv_dev, device_xname(periph->periph_dev),
   5196  1.1  bouyer 			    sizeof(bv->bv_dev));
   5197  1.1  bouyer 		}
   5198  1.1  bouyer 	}
   5199  1.1  bouyer 
   5200  1.1  bouyer 	free(vpg, M_TEMP);
   5201  1.1  bouyer 	return (0);
   5202  1.1  bouyer }
   5203  1.1  bouyer 
   5204  1.1  bouyer static int
   5205  1.1  bouyer mpii_ioctl_disk(struct mpii_softc *sc, struct bioc_disk *bd)
   5206  1.1  bouyer {
   5207  1.1  bouyer 	struct mpii_cfg_raid_vol_pg0		*vpg;
   5208  1.1  bouyer 	struct mpii_cfg_raid_vol_pg0_physdisk	*pd;
   5209  1.1  bouyer 	struct mpii_cfg_hdr			hdr;
   5210  1.1  bouyer 	struct mpii_device			*dev;
   5211  1.1  bouyer 	size_t					pagelen;
   5212  1.1  bouyer 	u_int16_t				volh;
   5213  1.1  bouyer 	u_int8_t				dn;
   5214  1.1  bouyer 
   5215  1.1  bouyer 	DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl_disk %d/%d\n",
   5216  1.1  bouyer 	    DEVNAME(sc), bd->bd_volid, bd->bd_diskid);
   5217  1.1  bouyer 
   5218  1.1  bouyer 	if ((dev = mpii_find_vol(sc, bd->bd_volid)) == NULL)
   5219  1.1  bouyer 		return (ENODEV);
   5220  1.1  bouyer 	volh = dev->dev_handle;
   5221  1.1  bouyer 
   5222  1.1  bouyer 	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
   5223  1.1  bouyer 	    MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0, &hdr) != 0) {
   5224  1.1  bouyer 		printf("%s: unable to fetch header for raid volume page 0\n",
   5225  1.1  bouyer 		    DEVNAME(sc));
   5226  1.1  bouyer 		return (EINVAL);
   5227  1.1  bouyer 	}
   5228  1.1  bouyer 
   5229  1.1  bouyer 	pagelen = hdr.page_length * 4;
   5230  1.1  bouyer 	vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_CANFAIL | M_ZERO);
   5231  1.1  bouyer 	if (vpg == NULL) {
   5232  1.1  bouyer 		printf("%s: unable to allocate space for raid "
   5233  1.1  bouyer 		    "volume page 0\n", DEVNAME(sc));
   5234  1.1  bouyer 		return (ENOMEM);
   5235  1.1  bouyer 	}
   5236  1.1  bouyer 
   5237  1.1  bouyer 	if (mpii_req_cfg_page(sc, MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0,
   5238  1.1  bouyer 	    &hdr, 1, vpg, pagelen) != 0) {
   5239  1.1  bouyer 		printf("%s: unable to fetch raid volume page 0\n",
   5240  1.1  bouyer 		    DEVNAME(sc));
   5241  1.1  bouyer 		free(vpg, M_TEMP);
   5242  1.1  bouyer 		return (EINVAL);
   5243  1.1  bouyer 	}
   5244  1.1  bouyer 
   5245  1.1  bouyer 	if (bd->bd_diskid >= vpg->num_phys_disks) {
   5246  1.1  bouyer 		int		nvdsk = vpg->num_phys_disks;
   5247  1.1  bouyer 		int		hsmap = vpg->hot_spare_pool;
   5248  1.1  bouyer 
   5249  1.1  bouyer 		free(vpg, M_TEMP);
   5250  1.1  bouyer 		return (mpii_bio_hs(sc, bd, nvdsk, hsmap, NULL));
   5251  1.1  bouyer 	}
   5252  1.1  bouyer 
   5253  1.1  bouyer 	pd = (struct mpii_cfg_raid_vol_pg0_physdisk *)(vpg + 1) +
   5254  1.1  bouyer 	    bd->bd_diskid;
   5255  1.1  bouyer 	dn = pd->phys_disk_num;
   5256  1.1  bouyer 
   5257  1.1  bouyer 	free(vpg, M_TEMP);
   5258  1.1  bouyer 	return (mpii_bio_disk(sc, bd, dn));
   5259  1.1  bouyer }
   5260  1.1  bouyer 
   5261  1.1  bouyer static int
   5262  1.1  bouyer mpii_bio_hs(struct mpii_softc *sc, struct bioc_disk *bd, int nvdsk,
   5263  1.1  bouyer      int hsmap, int *hscnt)
   5264  1.1  bouyer {
   5265  1.1  bouyer 	struct mpii_cfg_raid_config_pg0	*cpg;
   5266  1.1  bouyer 	struct mpii_raid_config_element	*el;
   5267  1.1  bouyer 	struct mpii_ecfg_hdr		ehdr;
   5268  1.1  bouyer 	size_t				pagelen;
   5269  1.1  bouyer 	int				i, nhs = 0;
   5270  1.1  bouyer 
   5271  1.1  bouyer 	if (bd) {
   5272  1.1  bouyer 		DNPRINTF(MPII_D_IOCTL, "%s: mpii_bio_hs %d\n", DEVNAME(sc),
   5273  1.1  bouyer 		    bd->bd_diskid - nvdsk);
   5274  1.1  bouyer 	} else {
   5275  1.1  bouyer 		DNPRINTF(MPII_D_IOCTL, "%s: mpii_bio_hs\n", DEVNAME(sc));
   5276  1.1  bouyer 	}
   5277  1.1  bouyer 
   5278  1.1  bouyer 	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_CONFIG,
   5279  1.1  bouyer 	    0, MPII_CFG_RAID_CONFIG_ACTIVE_CONFIG, MPII_PG_EXTENDED,
   5280  1.1  bouyer 	    &ehdr) != 0) {
   5281  1.1  bouyer 		printf("%s: unable to fetch header for raid config page 0\n",
   5282  1.1  bouyer 		    DEVNAME(sc));
   5283  1.1  bouyer 		return (EINVAL);
   5284  1.1  bouyer 	}
   5285  1.1  bouyer 
   5286  1.1  bouyer 	pagelen = le16toh(ehdr.ext_page_length) * 4;
   5287  1.1  bouyer 	cpg = malloc(pagelen, M_TEMP, M_WAITOK | M_CANFAIL | M_ZERO);
   5288  1.1  bouyer 	if (cpg == NULL) {
   5289  1.1  bouyer 		printf("%s: unable to allocate space for raid config page 0\n",
   5290  1.1  bouyer 		    DEVNAME(sc));
   5291  1.1  bouyer 		return (ENOMEM);
   5292  1.1  bouyer 	}
   5293  1.1  bouyer 
   5294  1.1  bouyer 	if (mpii_req_cfg_page(sc, MPII_CFG_RAID_CONFIG_ACTIVE_CONFIG,
   5295  1.1  bouyer 	    MPII_PG_EXTENDED, &ehdr, 1, cpg, pagelen) != 0) {
   5296  1.1  bouyer 		printf("%s: unable to fetch raid config page 0\n",
   5297  1.1  bouyer 		    DEVNAME(sc));
   5298  1.1  bouyer 		free(cpg, M_TEMP);
   5299  1.1  bouyer 		return (EINVAL);
   5300  1.1  bouyer 	}
   5301  1.1  bouyer 
   5302  1.1  bouyer 	el = (struct mpii_raid_config_element *)(cpg + 1);
   5303  1.1  bouyer 	for (i = 0; i < cpg->num_elements; i++, el++) {
   5304  1.1  bouyer 		if (ISSET(le16toh(el->element_flags),
   5305  1.1  bouyer 		    MPII_RAID_CONFIG_ELEMENT_FLAG_HSP_PHYS_DISK) &&
   5306  1.1  bouyer 		    el->hot_spare_pool == hsmap) {
   5307  1.1  bouyer 			/*
   5308  1.1  bouyer 			 * diskid comparison is based on the idea that all
   5309  1.1  bouyer 			 * disks are counted by the bio(4) in sequence, thus
   5310  1.1  bouyer 			 * substracting the number of disks in the volume
   5311  1.1  bouyer 			 * from the diskid yields us a "relative" hotspare
   5312  1.1  bouyer 			 * number, which is good enough for us.
   5313  1.1  bouyer 			 */
   5314  1.1  bouyer 			if (bd != NULL && bd->bd_diskid == nhs + nvdsk) {
   5315  1.1  bouyer 				u_int8_t dn = el->phys_disk_num;
   5316  1.1  bouyer 
   5317  1.1  bouyer 				free(cpg, M_TEMP);
   5318  1.1  bouyer 				return (mpii_bio_disk(sc, bd, dn));
   5319  1.1  bouyer 			}
   5320  1.1  bouyer 			nhs++;
   5321  1.1  bouyer 		}
   5322  1.1  bouyer 	}
   5323  1.1  bouyer 
   5324  1.1  bouyer 	if (hscnt)
   5325  1.1  bouyer 		*hscnt = nhs;
   5326  1.1  bouyer 
   5327  1.1  bouyer 	free(cpg, M_TEMP);
   5328  1.1  bouyer 	return (0);
   5329  1.1  bouyer }
   5330  1.1  bouyer 
   5331  1.1  bouyer static int
   5332  1.1  bouyer mpii_bio_disk(struct mpii_softc *sc, struct bioc_disk *bd, u_int8_t dn)
   5333  1.1  bouyer {
   5334  1.1  bouyer 	struct mpii_cfg_raid_physdisk_pg0	*ppg;
   5335  1.1  bouyer 	struct mpii_cfg_hdr			hdr;
   5336  1.1  bouyer 	struct mpii_device			*dev;
   5337  1.1  bouyer 	int					len;
   5338  1.1  bouyer 
   5339  1.1  bouyer 	DNPRINTF(MPII_D_IOCTL, "%s: mpii_bio_disk %d\n", DEVNAME(sc),
   5340  1.1  bouyer 	    bd->bd_diskid);
   5341  1.1  bouyer 
   5342  1.1  bouyer 	ppg = malloc(sizeof(*ppg), M_TEMP, M_WAITOK | M_CANFAIL | M_ZERO);
   5343  1.1  bouyer 	if (ppg == NULL) {
   5344  1.1  bouyer 		printf("%s: unable to allocate space for raid physical disk "
   5345  1.1  bouyer 		    "page 0\n", DEVNAME(sc));
   5346  1.1  bouyer 		return (ENOMEM);
   5347  1.1  bouyer 	}
   5348  1.1  bouyer 
   5349  1.1  bouyer 	hdr.page_version = 0;
   5350  1.1  bouyer 	hdr.page_length = sizeof(*ppg) / 4;
   5351  1.1  bouyer 	hdr.page_number = 0;
   5352  1.1  bouyer 	hdr.page_type = MPII_CONFIG_REQ_PAGE_TYPE_RAID_PD;
   5353  1.1  bouyer 
   5354  1.1  bouyer 	if (mpii_req_cfg_page(sc, MPII_CFG_RAID_PHYS_DISK_ADDR_NUMBER | dn, 0,
   5355  1.1  bouyer 	    &hdr, 1, ppg, sizeof(*ppg)) != 0) {
   5356  1.1  bouyer 		printf("%s: unable to fetch raid drive page 0\n",
   5357  1.1  bouyer 		    DEVNAME(sc));
   5358  1.1  bouyer 		free(ppg, M_TEMP);
   5359  1.1  bouyer 		return (EINVAL);
   5360  1.1  bouyer 	}
   5361  1.1  bouyer 
   5362  1.1  bouyer 	bd->bd_target = ppg->phys_disk_num;
   5363  1.1  bouyer 
   5364  1.1  bouyer 	if ((dev = mpii_find_dev(sc, le16toh(ppg->dev_handle))) == NULL) {
   5365  1.1  bouyer 		bd->bd_status = BIOC_SDINVALID;
   5366  1.1  bouyer 		free(ppg, M_TEMP);
   5367  1.1  bouyer 		return (0);
   5368  1.1  bouyer 	}
   5369  1.1  bouyer 
   5370  1.1  bouyer 	switch (ppg->phys_disk_state) {
   5371  1.1  bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_ONLINE:
   5372  1.1  bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_OPTIMAL:
   5373  1.1  bouyer 		bd->bd_status = BIOC_SDONLINE;
   5374  1.1  bouyer 		break;
   5375  1.1  bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_OFFLINE:
   5376  1.1  bouyer 		if (ppg->offline_reason ==
   5377  1.1  bouyer 		    MPII_CFG_RAID_PHYDISK_0_OFFLINE_FAILED ||
   5378  1.1  bouyer 		    ppg->offline_reason ==
   5379  1.1  bouyer 		    MPII_CFG_RAID_PHYDISK_0_OFFLINE_FAILEDREQ)
   5380  1.1  bouyer 			bd->bd_status = BIOC_SDFAILED;
   5381  1.1  bouyer 		else
   5382  1.1  bouyer 			bd->bd_status = BIOC_SDOFFLINE;
   5383  1.1  bouyer 		break;
   5384  1.1  bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_DEGRADED:
   5385  1.1  bouyer 		bd->bd_status = BIOC_SDFAILED;
   5386  1.1  bouyer 		break;
   5387  1.1  bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_REBUILDING:
   5388  1.1  bouyer 		bd->bd_status = BIOC_SDREBUILD;
   5389  1.1  bouyer 		break;
   5390  1.1  bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_HOTSPARE:
   5391  1.1  bouyer 		bd->bd_status = BIOC_SDHOTSPARE;
   5392  1.1  bouyer 		break;
   5393  1.1  bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_NOTCONFIGURED:
   5394  1.1  bouyer 		bd->bd_status = BIOC_SDUNUSED;
   5395  1.1  bouyer 		break;
   5396  1.1  bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_NOTCOMPATIBLE:
   5397  1.1  bouyer 	default:
   5398  1.1  bouyer 		bd->bd_status = BIOC_SDINVALID;
   5399  1.1  bouyer 		break;
   5400  1.1  bouyer 	}
   5401  1.1  bouyer 
   5402  1.1  bouyer 	bd->bd_size = le64toh(ppg->dev_max_lba) * le16toh(ppg->block_size);
   5403  1.1  bouyer 
   5404  1.1  bouyer 	scsipi_strvis(bd->bd_vendor, sizeof(bd->bd_vendor),
   5405  1.1  bouyer 	    ppg->vendor_id, sizeof(ppg->vendor_id));
   5406  1.1  bouyer 	len = strlen(bd->bd_vendor);
   5407  1.1  bouyer 	bd->bd_vendor[len] = ' ';
   5408  1.1  bouyer 	scsipi_strvis(&bd->bd_vendor[len + 1], sizeof(ppg->vendor_id) - len - 1,
   5409  1.1  bouyer 	    ppg->product_id, sizeof(ppg->product_id));
   5410  1.1  bouyer 	scsipi_strvis(bd->bd_serial, sizeof(bd->bd_serial),
   5411  1.1  bouyer 	    ppg->serial, sizeof(ppg->serial));
   5412  1.1  bouyer 
   5413  1.1  bouyer 	free(ppg, M_TEMP);
   5414  1.1  bouyer 	return (0);
   5415  1.1  bouyer }
   5416  1.1  bouyer 
   5417  1.1  bouyer static struct mpii_device *
   5418  1.1  bouyer mpii_find_vol(struct mpii_softc *sc, int volid)
   5419  1.1  bouyer {
   5420  1.1  bouyer 	struct mpii_device	*dev = NULL;
   5421  1.1  bouyer 
   5422  1.1  bouyer 	if (sc->sc_vd_id_low + volid >= sc->sc_max_devices)
   5423  1.1  bouyer 		return (NULL);
   5424  1.1  bouyer 	dev = sc->sc_devs[sc->sc_vd_id_low + volid];
   5425  1.1  bouyer 	if (dev && ISSET(dev->flags, MPII_DF_VOLUME))
   5426  1.1  bouyer 		return (dev);
   5427  1.1  bouyer 	return (NULL);
   5428  1.1  bouyer }
   5429  1.1  bouyer 
   5430  1.1  bouyer /*
   5431  1.1  bouyer  * Non-sleeping lightweight version of the mpii_ioctl_vol
   5432  1.1  bouyer  */
   5433  1.1  bouyer static int
   5434  1.1  bouyer mpii_bio_volstate(struct mpii_softc *sc, struct bioc_vol *bv)
   5435  1.1  bouyer {
   5436  1.1  bouyer 	struct mpii_cfg_raid_vol_pg0	*vpg;
   5437  1.1  bouyer 	struct mpii_cfg_hdr		hdr;
   5438  1.1  bouyer 	struct mpii_device		*dev = NULL;
   5439  1.1  bouyer 	size_t				pagelen;
   5440  1.1  bouyer 	u_int16_t			volh;
   5441  1.1  bouyer 
   5442  1.1  bouyer 	if ((dev = mpii_find_vol(sc, bv->bv_volid)) == NULL)
   5443  1.1  bouyer 		return (ENODEV);
   5444  1.1  bouyer 	volh = dev->dev_handle;
   5445  1.1  bouyer 
   5446  1.1  bouyer 	if (mpii_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
   5447  1.1  bouyer 	    MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, &hdr) != 0) {
   5448  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: unable to fetch header for raid "
   5449  1.1  bouyer 		    "volume page 0\n", DEVNAME(sc));
   5450  1.1  bouyer 		return (EINVAL);
   5451  1.1  bouyer 	}
   5452  1.1  bouyer 
   5453  1.1  bouyer 	pagelen = hdr.page_length * 4;
   5454  1.1  bouyer 	vpg = malloc(pagelen, M_TEMP, M_NOWAIT | M_ZERO);
   5455  1.1  bouyer 	if (vpg == NULL) {
   5456  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: unable to allocate space for raid "
   5457  1.1  bouyer 		    "volume page 0\n", DEVNAME(sc));
   5458  1.1  bouyer 		return (ENOMEM);
   5459  1.1  bouyer 	}
   5460  1.1  bouyer 
   5461  1.1  bouyer 	if (mpii_cfg_page(sc, MPII_CFG_RAID_VOL_ADDR_HANDLE | volh,
   5462  1.1  bouyer 	    &hdr, 1, vpg, pagelen) != 0) {
   5463  1.1  bouyer 		DNPRINTF(MPII_D_MISC, "%s: unable to fetch raid volume "
   5464  1.1  bouyer 		    "page 0\n", DEVNAME(sc));
   5465  1.1  bouyer 		free(vpg, M_TEMP);
   5466  1.1  bouyer 		return (EINVAL);
   5467  1.1  bouyer 	}
   5468  1.1  bouyer 
   5469  1.1  bouyer 	switch (vpg->volume_state) {
   5470  1.1  bouyer 	case MPII_CFG_RAID_VOL_0_STATE_ONLINE:
   5471  1.1  bouyer 	case MPII_CFG_RAID_VOL_0_STATE_OPTIMAL:
   5472  1.1  bouyer 		bv->bv_status = BIOC_SVONLINE;
   5473  1.1  bouyer 		break;
   5474  1.1  bouyer 	case MPII_CFG_RAID_VOL_0_STATE_DEGRADED:
   5475  1.1  bouyer 		if (ISSET(le32toh(vpg->volume_status),
   5476  1.1  bouyer 		    MPII_CFG_RAID_VOL_0_STATUS_RESYNC))
   5477  1.1  bouyer 			bv->bv_status = BIOC_SVREBUILD;
   5478  1.1  bouyer 		else
   5479  1.1  bouyer 			bv->bv_status = BIOC_SVDEGRADED;
   5480  1.1  bouyer 		break;
   5481  1.1  bouyer 	case MPII_CFG_RAID_VOL_0_STATE_FAILED:
   5482  1.1  bouyer 		bv->bv_status = BIOC_SVOFFLINE;
   5483  1.1  bouyer 		break;
   5484  1.1  bouyer 	case MPII_CFG_RAID_VOL_0_STATE_INITIALIZING:
   5485  1.1  bouyer 		bv->bv_status = BIOC_SVBUILDING;
   5486  1.1  bouyer 		break;
   5487  1.1  bouyer 	case MPII_CFG_RAID_VOL_0_STATE_MISSING:
   5488  1.1  bouyer 	default:
   5489  1.1  bouyer 		bv->bv_status = BIOC_SVINVALID;
   5490  1.1  bouyer 		break;
   5491  1.1  bouyer 	}
   5492  1.1  bouyer 
   5493  1.1  bouyer 	free(vpg, M_TEMP);
   5494  1.1  bouyer 	return (0);
   5495  1.1  bouyer }
   5496  1.1  bouyer 
   5497  1.1  bouyer static int
   5498  1.1  bouyer mpii_create_sensors(struct mpii_softc *sc)
   5499  1.1  bouyer {
   5500  1.1  bouyer 	int			i, rv;
   5501  1.1  bouyer 
   5502  1.1  bouyer 	sc->sc_sme = sysmon_envsys_create();
   5503  1.1  bouyer 	sc->sc_sensors = malloc(sizeof(envsys_data_t) * sc->sc_vd_count,
   5504  1.1  bouyer 	    M_DEVBUF, M_NOWAIT | M_ZERO);
   5505  1.1  bouyer 	if (sc->sc_sensors == NULL) {
   5506  1.1  bouyer 		aprint_error_dev(sc->sc_dev,
   5507  1.1  bouyer 		    "can't allocate envsys_data_t\n");
   5508  1.1  bouyer 		return (1);
   5509  1.1  bouyer 	}
   5510  1.1  bouyer 
   5511  1.1  bouyer 	for (i = 0; i < sc->sc_vd_count; i++) {
   5512  1.1  bouyer 		sc->sc_sensors[i].units = ENVSYS_DRIVE;
   5513  1.1  bouyer 		sc->sc_sensors[i].state = ENVSYS_SINVALID;
   5514  1.1  bouyer 		sc->sc_sensors[i].value_cur = ENVSYS_DRIVE_EMPTY;
   5515  1.1  bouyer 		/* Enable monitoring for drive state changes */
   5516  1.1  bouyer 		sc->sc_sensors[i].flags |= ENVSYS_FMONSTCHANGED;
   5517  1.1  bouyer 
   5518  1.1  bouyer 		/* logical drives */
   5519  1.1  bouyer 		snprintf(sc->sc_sensors[i].desc,
   5520  1.1  bouyer 		    sizeof(sc->sc_sensors[i].desc), "%s:%d",
   5521  1.1  bouyer 		    DEVNAME(sc), i);
   5522  1.1  bouyer 		if ((rv = sysmon_envsys_sensor_attach(sc->sc_sme,
   5523  1.1  bouyer 		    &sc->sc_sensors[i])) != 0) {
   5524  1.1  bouyer 			aprint_error_dev(sc->sc_dev,
   5525  1.1  bouyer 			    "unable to attach sensor (rv = %d)\n", rv);
   5526  1.1  bouyer 			goto out;
   5527  1.1  bouyer 		}
   5528  1.1  bouyer 	}
   5529  1.1  bouyer 	sc->sc_sme->sme_name =  DEVNAME(sc);
   5530  1.1  bouyer 	sc->sc_sme->sme_cookie = sc;
   5531  1.1  bouyer 	sc->sc_sme->sme_refresh = mpii_refresh_sensors;
   5532  1.1  bouyer 
   5533  1.1  bouyer 	rv = sysmon_envsys_register(sc->sc_sme);
   5534  1.1  bouyer 
   5535  1.1  bouyer 	if (rv != 0) {
   5536  1.1  bouyer 		aprint_error_dev(sc->sc_dev,
   5537  1.1  bouyer 		    "unable to register with sysmon (rv = %d)\n", rv);
   5538  1.1  bouyer 		goto out;
   5539  1.1  bouyer 	}
   5540  1.1  bouyer 	return 0;
   5541  1.1  bouyer 
   5542  1.1  bouyer out:
   5543  1.1  bouyer 	free(sc->sc_sensors, M_DEVBUF);
   5544  1.1  bouyer 	sysmon_envsys_destroy(sc->sc_sme);
   5545  1.1  bouyer 	sc->sc_sme = NULL;
   5546  1.1  bouyer 	return EINVAL;
   5547  1.1  bouyer }
   5548  1.1  bouyer 
   5549  1.1  bouyer static int
   5550  1.1  bouyer mpii_destroy_sensors(struct mpii_softc *sc)
   5551  1.1  bouyer {
   5552  1.1  bouyer 	if (sc->sc_sme == NULL)
   5553  1.1  bouyer 		return 0;
   5554  1.1  bouyer 	sysmon_envsys_unregister(sc->sc_sme);
   5555  1.1  bouyer 	sc->sc_sme = NULL;
   5556  1.1  bouyer 	free(sc->sc_sensors, M_DEVBUF);
   5557  1.1  bouyer 	return 0;
   5558  1.1  bouyer }
   5559  1.1  bouyer 
   5560  1.1  bouyer static void
   5561  1.1  bouyer mpii_refresh_sensors(struct sysmon_envsys *sme, envsys_data_t *edata)
   5562  1.1  bouyer {
   5563  1.1  bouyer 	struct mpii_softc	*sc = sc = sme->sme_cookie;
   5564  1.1  bouyer 	struct bioc_vol		bv;
   5565  1.1  bouyer 	int			s, error;
   5566  1.1  bouyer 
   5567  1.1  bouyer 	bzero(&bv, sizeof(bv));
   5568  1.1  bouyer 	bv.bv_volid = edata->sensor;
   5569  1.1  bouyer 	KERNEL_LOCK(1, curlwp);
   5570  1.1  bouyer 	s = splbio();
   5571  1.1  bouyer 	error = mpii_bio_volstate(sc, &bv);
   5572  1.1  bouyer 	splx(s);
   5573  1.1  bouyer 	KERNEL_UNLOCK_ONE(curlwp);
   5574  1.1  bouyer 	if (error)
   5575  1.1  bouyer 		return;
   5576  1.1  bouyer 	switch(bv.bv_status) {
   5577  1.1  bouyer 	case BIOC_SVOFFLINE:
   5578  1.1  bouyer 		edata->value_cur = ENVSYS_DRIVE_FAIL;
   5579  1.1  bouyer 		edata->state = ENVSYS_SCRITICAL;
   5580  1.1  bouyer 		break;
   5581  1.1  bouyer 	case BIOC_SVDEGRADED:
   5582  1.1  bouyer 		edata->value_cur = ENVSYS_DRIVE_PFAIL;
   5583  1.1  bouyer 		edata->state = ENVSYS_SCRITICAL;
   5584  1.1  bouyer 		break;
   5585  1.1  bouyer 	case BIOC_SVREBUILD:
   5586  1.1  bouyer 		edata->value_cur = ENVSYS_DRIVE_REBUILD;
   5587  1.1  bouyer 		edata->state = ENVSYS_SVALID;
   5588  1.1  bouyer 		break;
   5589  1.1  bouyer 	case BIOC_SVONLINE:
   5590  1.1  bouyer 		edata->value_cur = ENVSYS_DRIVE_ONLINE;
   5591  1.1  bouyer 		edata->state = ENVSYS_SVALID;
   5592  1.1  bouyer 		break;
   5593  1.1  bouyer 	case BIOC_SVINVALID:
   5594  1.1  bouyer 		/* FALLTHROUGH */
   5595  1.1  bouyer 	default:
   5596  1.1  bouyer 		edata->value_cur = 0; /* unknown */
   5597  1.1  bouyer 		edata->state = ENVSYS_SINVALID;
   5598  1.1  bouyer 	}
   5599  1.1  bouyer }
   5600  1.1  bouyer #endif /* NBIO > 0 */
   5601