Home | History | Annotate | Line # | Download | only in pci
mpii.c revision 1.12
      1  1.12  jdolecek /* $NetBSD: mpii.c,v 1.12 2018/10/14 17:37:40 jdolecek 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.12  jdolecek __KERNEL_RCSID(0, "$NetBSD: mpii.c,v 1.12 2018/10/14 17:37:40 jdolecek 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.5  christos 	char intrbuf[PCI_INTRSTR_LEN];
   2138   1.1    bouyer 
   2139   1.1    bouyer 	pci_aprint_devinfo(pa, NULL);
   2140   1.1    bouyer 
   2141   1.1    bouyer 	sc->sc_pc = pa->pa_pc;
   2142   1.1    bouyer 	sc->sc_tag = pa->pa_tag;
   2143   1.1    bouyer 	sc->sc_dmat = pa->pa_dmat;
   2144   1.1    bouyer 	sc->sc_dev = self;
   2145   1.1    bouyer 
   2146   1.1    bouyer 	mutex_init(&sc->sc_req_mtx, MUTEX_DEFAULT, IPL_BIO);
   2147   1.1    bouyer 	mutex_init(&sc->sc_rep_mtx, MUTEX_DEFAULT, IPL_BIO);
   2148   1.1    bouyer 	mutex_init(&sc->sc_ccb_free_mtx, MUTEX_DEFAULT, IPL_BIO);
   2149   1.1    bouyer 	cv_init(&sc->sc_ccb_free_cv, "mpii_ccbs");
   2150   1.1    bouyer 	mutex_init(&sc->sc_ccb_mtx, MUTEX_DEFAULT, IPL_BIO);
   2151   1.1    bouyer 
   2152   1.1    bouyer 	snprintf(wkname, sizeof(wkname), "%s_tmo", DEVNAME(sc));
   2153   1.1    bouyer 	if (workqueue_create(&sc->sc_ssb_tmowk, wkname,
   2154   1.1    bouyer 	    mpii_scsi_cmd_tmo_handler, sc, PRI_NONE, IPL_BIO, WQ_MPSAFE) != 0) {
   2155   1.1    bouyer 		aprint_error_dev(self, "can't create %s workqueue\n", wkname);
   2156   1.1    bouyer 		return;
   2157   1.1    bouyer 	}
   2158   1.1    bouyer 
   2159   1.1    bouyer 	snprintf(wkname, sizeof(wkname), "%s_evt", DEVNAME(sc));
   2160   1.1    bouyer 	if (workqueue_create(&sc->sc_ssb_evt_ackwk, wkname,
   2161   1.1    bouyer 	    mpii_eventack, sc, PRI_NONE, IPL_BIO, WQ_MPSAFE) != 0) {
   2162   1.1    bouyer 		aprint_error_dev(self, "can't create %s workqueue\n", wkname);
   2163   1.1    bouyer 		return;
   2164   1.1    bouyer 	}
   2165   1.1    bouyer 
   2166   1.1    bouyer 	/* find the appropriate memory base */
   2167   1.1    bouyer 	for (r = PCI_MAPREG_START; r < PCI_MAPREG_END; r += sizeof(memtype)) {
   2168   1.1    bouyer 		memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, r);
   2169   1.1    bouyer 		if ((memtype & PCI_MAPREG_TYPE_MASK) == PCI_MAPREG_TYPE_MEM)
   2170   1.1    bouyer 			break;
   2171   1.1    bouyer 	}
   2172   1.1    bouyer 	if (r >= PCI_MAPREG_END) {
   2173   1.1    bouyer 		aprint_error_dev(self,
   2174   1.1    bouyer 		    "unable to locate system interface registers\n");
   2175   1.1    bouyer 		return;
   2176   1.1    bouyer 	}
   2177   1.1    bouyer 
   2178   1.1    bouyer 	if (pci_mapreg_map(pa, r, memtype, 0, &sc->sc_iot, &sc->sc_ioh,
   2179   1.1    bouyer 	    NULL, &sc->sc_ios) != 0) {
   2180   1.1    bouyer 		aprint_error_dev(self,
   2181   1.1    bouyer 		    "unable to map system interface registers\n");
   2182   1.1    bouyer 		return;
   2183   1.1    bouyer 	}
   2184   1.1    bouyer 
   2185   1.1    bouyer 	/* disable the expansion rom */
   2186   1.1    bouyer 	PWRITE(sc, PCI_MAPREG_ROM,
   2187   1.1    bouyer 	    PREAD(sc, PCI_MAPREG_ROM) & ~PCI_MAPREG_ROM_ENABLE);
   2188   1.1    bouyer 
   2189   1.1    bouyer 	/* disable interrupts */
   2190   1.1    bouyer 	mpii_write(sc, MPII_INTR_MASK,
   2191   1.1    bouyer 	    MPII_INTR_MASK_RESET | MPII_INTR_MASK_REPLY |
   2192   1.1    bouyer 	    MPII_INTR_MASK_DOORBELL);
   2193   1.1    bouyer 
   2194   1.1    bouyer 	/* hook up the interrupt */
   2195   1.1    bouyer 	if (pci_intr_map(pa, &ih) != 0) {
   2196   1.1    bouyer 		aprint_error_dev(self, "unable to map interrupt\n");
   2197   1.1    bouyer 		goto unmap;
   2198   1.1    bouyer 	}
   2199   1.5  christos 	intrstr = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf));
   2200   1.1    bouyer 
   2201   1.1    bouyer 	if (mpii_init(sc) != 0) {
   2202   1.1    bouyer 		aprint_error_dev(self, "unable to initialize ioc\n");
   2203   1.1    bouyer 		goto unmap;
   2204   1.1    bouyer 	}
   2205   1.1    bouyer 
   2206   1.1    bouyer 	if (mpii_iocfacts(sc) != 0) {
   2207   1.1    bouyer 		aprint_error_dev(self, "unable to get iocfacts\n");
   2208   1.1    bouyer 		goto unmap;
   2209   1.1    bouyer 	}
   2210   1.1    bouyer 
   2211   1.1    bouyer 	if (mpii_alloc_ccbs(sc) != 0) {
   2212   1.1    bouyer 		/* error already printed */
   2213   1.1    bouyer 		goto unmap;
   2214   1.1    bouyer 	}
   2215   1.1    bouyer 
   2216   1.1    bouyer 	if (mpii_alloc_replies(sc) != 0) {
   2217   1.1    bouyer 		aprint_error_dev(self, "unable to allocated reply space\n");
   2218   1.1    bouyer 		goto free_ccbs;
   2219   1.1    bouyer 	}
   2220   1.1    bouyer 
   2221   1.1    bouyer 	if (mpii_alloc_queues(sc) != 0) {
   2222   1.1    bouyer 		aprint_error_dev(self, "unable to allocate reply queues\n");
   2223   1.1    bouyer 		goto free_replies;
   2224   1.1    bouyer 	}
   2225   1.1    bouyer 
   2226   1.1    bouyer 	if (mpii_iocinit(sc) != 0) {
   2227   1.1    bouyer 		aprint_error_dev(self, "unable to send iocinit\n");
   2228   1.1    bouyer 		goto free_queues;
   2229   1.1    bouyer 	}
   2230   1.1    bouyer 
   2231   1.1    bouyer 	if (mpii_wait_eq(sc, MPII_DOORBELL, MPII_DOORBELL_STATE,
   2232   1.1    bouyer 	    MPII_DOORBELL_STATE_OPER) != 0) {
   2233   1.1    bouyer 		aprint_error_dev(self, "state: 0x%08x\n",
   2234   1.1    bouyer 			mpii_read_db(sc) & MPII_DOORBELL_STATE);
   2235   1.1    bouyer 		aprint_error_dev(self, "operational state timeout\n");
   2236   1.1    bouyer 		goto free_queues;
   2237   1.1    bouyer 	}
   2238   1.1    bouyer 
   2239   1.1    bouyer 	mpii_push_replies(sc);
   2240   1.1    bouyer 	mpii_init_queues(sc);
   2241   1.1    bouyer 
   2242   1.1    bouyer 	if (mpii_portfacts(sc) != 0) {
   2243   1.1    bouyer 		aprint_error_dev(self, "unable to get portfacts\n");
   2244   1.1    bouyer 		goto free_queues;
   2245   1.1    bouyer 	}
   2246   1.1    bouyer 
   2247   1.1    bouyer 	if (mpii_get_ioc_pg8(sc) != 0) {
   2248   1.1    bouyer 		aprint_error_dev(self, "unable to get ioc page 8\n");
   2249   1.1    bouyer 		goto free_queues;
   2250   1.1    bouyer 	}
   2251   1.1    bouyer 
   2252   1.1    bouyer 	if (mpii_cfg_coalescing(sc) != 0) {
   2253   1.1    bouyer 		aprint_error_dev(self, "unable to configure coalescing\n");
   2254   1.1    bouyer 		goto free_queues;
   2255   1.1    bouyer 	}
   2256   1.1    bouyer 
   2257   1.1    bouyer 	/* XXX bail on unsupported porttype? */
   2258   1.1    bouyer 	if ((sc->sc_porttype == MPII_PORTFACTS_PORTTYPE_SAS_PHYSICAL) ||
   2259   1.1    bouyer 	    (sc->sc_porttype == MPII_PORTFACTS_PORTTYPE_SAS_VIRTUAL)) {
   2260   1.1    bouyer 		if (mpii_eventnotify(sc) != 0) {
   2261   1.1    bouyer 			aprint_error_dev(self, "unable to enable events\n");
   2262   1.1    bouyer 			goto free_queues;
   2263   1.1    bouyer 		}
   2264   1.1    bouyer 	}
   2265   1.1    bouyer 
   2266   1.1    bouyer 	if (mpii_alloc_dev(sc) != 0) {
   2267   1.1    bouyer 		aprint_error_dev(self,
   2268   1.1    bouyer 		    "unable to allocate memory for mpii_device\n");
   2269   1.1    bouyer 		goto free_queues;
   2270   1.1    bouyer 	}
   2271   1.1    bouyer 
   2272   1.1    bouyer 	if (mpii_portenable(sc) != 0) {
   2273   1.1    bouyer 		aprint_error_dev(self, "unable to enable port\n");
   2274   1.1    bouyer 		goto free_dev;
   2275   1.1    bouyer 	}
   2276   1.1    bouyer 
   2277   1.1    bouyer 	sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_BIO,
   2278   1.1    bouyer 	    mpii_intr, sc);
   2279   1.1    bouyer 	if (sc->sc_ih == NULL) {
   2280   1.1    bouyer 		aprint_error_dev(self, "can't establish interrupt");
   2281   1.1    bouyer 		if (intrstr)
   2282   1.1    bouyer 			aprint_error(" at %s", intrstr);
   2283   1.1    bouyer 		aprint_error("\n");
   2284   1.1    bouyer 		goto free_dev;
   2285   1.1    bouyer 	}
   2286   1.1    bouyer 
   2287   1.1    bouyer 	memset(adapt, 0, sizeof(*adapt));
   2288   1.1    bouyer 	adapt->adapt_dev = sc->sc_dev;
   2289   1.1    bouyer 	adapt->adapt_nchannels = 1;
   2290   1.1    bouyer 	adapt->adapt_openings = sc->sc_request_depth - 1;
   2291   1.1    bouyer 	adapt->adapt_max_periph = adapt->adapt_openings;
   2292   1.1    bouyer 	adapt->adapt_request = mpii_scsipi_request;
   2293   1.1    bouyer 	adapt->adapt_minphys = mpii_minphys;
   2294   1.1    bouyer 
   2295   1.1    bouyer 	memset(chan, 0, sizeof(*chan));
   2296   1.1    bouyer 	chan->chan_adapter = adapt;
   2297   1.1    bouyer 	chan->chan_bustype = &scsi_sas_bustype;
   2298   1.1    bouyer 	chan->chan_channel = 0;
   2299   1.1    bouyer 	chan->chan_flags = 0;
   2300   1.2    kardel 	chan->chan_nluns = 8;
   2301   1.1    bouyer 	chan->chan_ntargets = sc->sc_max_devices;
   2302   1.1    bouyer 	chan->chan_id = -1;
   2303   1.1    bouyer 
   2304   1.1    bouyer 	mpii_rescan(self, "scsi", NULL);
   2305   1.1    bouyer 
   2306   1.1    bouyer 	/* enable interrupts */
   2307   1.1    bouyer 	mpii_write(sc, MPII_INTR_MASK, MPII_INTR_MASK_DOORBELL
   2308   1.1    bouyer 	    | MPII_INTR_MASK_RESET);
   2309   1.1    bouyer 
   2310   1.1    bouyer #if NBIO > 0
   2311   1.1    bouyer 	if (ISSET(sc->sc_flags, MPII_F_RAID)) {
   2312   1.1    bouyer 		if (bio_register(sc->sc_dev, mpii_ioctl) != 0)
   2313   1.1    bouyer 			panic("%s: controller registration failed",
   2314   1.1    bouyer 			    DEVNAME(sc));
   2315   1.1    bouyer 
   2316   1.1    bouyer 		if (mpii_create_sensors(sc) != 0)
   2317   1.1    bouyer 			aprint_error_dev(self, "unable to create sensors\n");
   2318   1.1    bouyer 	}
   2319   1.1    bouyer #endif
   2320   1.1    bouyer 
   2321   1.1    bouyer 	return;
   2322   1.1    bouyer 
   2323   1.1    bouyer free_dev:
   2324   1.1    bouyer 	if (sc->sc_devs)
   2325   1.1    bouyer 		free(sc->sc_devs, M_DEVBUF);
   2326   1.1    bouyer 
   2327   1.1    bouyer free_queues:
   2328   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_freeq),
   2329   1.1    bouyer      	    0, sc->sc_reply_free_qdepth * 4, BUS_DMASYNC_POSTREAD);
   2330   1.1    bouyer 	mpii_dmamem_free(sc, sc->sc_reply_freeq);
   2331   1.1    bouyer 
   2332   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq),
   2333   1.1    bouyer 	    0, sc->sc_reply_post_qdepth * 8, BUS_DMASYNC_POSTREAD);
   2334   1.1    bouyer 	mpii_dmamem_free(sc, sc->sc_reply_postq);
   2335   1.1    bouyer 
   2336   1.1    bouyer free_replies:
   2337   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_replies),
   2338   1.1    bouyer 		0, PAGE_SIZE, BUS_DMASYNC_POSTREAD);
   2339   1.1    bouyer 	mpii_dmamem_free(sc, sc->sc_replies);
   2340   1.1    bouyer 
   2341   1.1    bouyer free_ccbs:
   2342   1.1    bouyer 	while ((ccb = mpii_get_ccb(sc, MPII_NOSLEEP)) != NULL)
   2343   1.1    bouyer 		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
   2344   1.1    bouyer 	mpii_dmamem_free(sc, sc->sc_requests);
   2345   1.1    bouyer 	free(sc->sc_ccbs, M_DEVBUF);
   2346   1.1    bouyer 
   2347   1.1    bouyer unmap:
   2348   1.1    bouyer 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
   2349   1.1    bouyer 	sc->sc_ios = 0;
   2350   1.1    bouyer }
   2351   1.1    bouyer 
   2352   1.1    bouyer static int
   2353   1.1    bouyer mpii_detach(device_t self, int flags)
   2354   1.1    bouyer {
   2355   1.1    bouyer 	struct mpii_softc		*sc = device_private(self);
   2356   1.1    bouyer 	int error;
   2357   1.1    bouyer 	struct mpii_ccb *ccb;
   2358   1.1    bouyer 
   2359   1.1    bouyer 	if ((error = config_detach_children(sc->sc_dev, flags)) != 0)
   2360   1.1    bouyer 		return error;
   2361   1.1    bouyer 
   2362   1.1    bouyer #if NBIO > 0
   2363   1.1    bouyer 	mpii_destroy_sensors(sc);
   2364   1.1    bouyer 	bio_unregister(sc->sc_dev);
   2365   1.1    bouyer #endif /* NBIO > 0 */
   2366   1.1    bouyer 
   2367   1.1    bouyer 	if (sc->sc_ih != NULL) {
   2368   1.1    bouyer 		if (sc->sc_devs)
   2369   1.1    bouyer 			free(sc->sc_devs, M_DEVBUF);
   2370   1.1    bouyer 
   2371   1.1    bouyer 		bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_freeq),
   2372   1.1    bouyer 		    0, sc->sc_reply_free_qdepth * 4, BUS_DMASYNC_POSTREAD);
   2373   1.1    bouyer 		mpii_dmamem_free(sc, sc->sc_reply_freeq);
   2374   1.1    bouyer 
   2375   1.1    bouyer 		bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq),
   2376   1.1    bouyer 		    0, sc->sc_reply_post_qdepth * 8, BUS_DMASYNC_POSTREAD);
   2377   1.1    bouyer 		mpii_dmamem_free(sc, sc->sc_reply_postq);
   2378   1.1    bouyer 
   2379   1.1    bouyer 		bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_replies),
   2380   1.1    bouyer 			0, PAGE_SIZE, BUS_DMASYNC_POSTREAD);
   2381   1.1    bouyer 		mpii_dmamem_free(sc, sc->sc_replies);
   2382   1.1    bouyer 
   2383   1.1    bouyer 		while ((ccb = mpii_get_ccb(sc, MPII_NOSLEEP)) != NULL)
   2384   1.1    bouyer 			bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
   2385   1.1    bouyer 		mpii_dmamem_free(sc, sc->sc_requests);
   2386   1.1    bouyer 		free(sc->sc_ccbs, M_DEVBUF);
   2387   1.1    bouyer 
   2388   1.1    bouyer 		pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
   2389   1.1    bouyer 		sc->sc_ih = NULL;
   2390   1.1    bouyer 	}
   2391   1.1    bouyer 	if (sc->sc_ios != 0) {
   2392   1.1    bouyer 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
   2393   1.1    bouyer 		sc->sc_ios = 0;
   2394   1.1    bouyer 	}
   2395   1.1    bouyer 
   2396   1.1    bouyer 	return (0);
   2397   1.1    bouyer }
   2398   1.1    bouyer 
   2399   1.1    bouyer static int
   2400   1.1    bouyer mpii_rescan(device_t self, const char *ifattr, const int *locators)
   2401   1.1    bouyer {
   2402   1.1    bouyer 	struct mpii_softc *sc = device_private(self);
   2403   1.1    bouyer 
   2404   1.1    bouyer 	if (sc->sc_child != NULL)
   2405   1.1    bouyer 		return 0;
   2406   1.1    bouyer 
   2407   1.1    bouyer 	sc->sc_child = config_found_sm_loc(self, ifattr, locators, &sc->sc_chan,
   2408   1.1    bouyer 	    scsiprint, NULL);
   2409   1.1    bouyer 
   2410   1.1    bouyer 	return 0;
   2411   1.1    bouyer }
   2412   1.1    bouyer 
   2413   1.1    bouyer static void
   2414   1.1    bouyer mpii_childdetached(device_t self, device_t child)
   2415   1.1    bouyer {
   2416   1.1    bouyer         struct mpii_softc *sc = device_private(self);
   2417   1.1    bouyer 
   2418   1.1    bouyer         KASSERT(self == sc->sc_dev);
   2419   1.1    bouyer         KASSERT(child == sc->sc_child);
   2420   1.1    bouyer 
   2421   1.1    bouyer         if (child == sc->sc_child)
   2422   1.1    bouyer                 sc->sc_child = NULL;
   2423   1.1    bouyer }
   2424   1.1    bouyer 
   2425   1.1    bouyer static int
   2426   1.1    bouyer mpii_intr(void *arg)
   2427   1.1    bouyer {
   2428   1.1    bouyer 	struct mpii_rcb_list		evts = SIMPLEQ_HEAD_INITIALIZER(evts);
   2429   1.1    bouyer 	struct mpii_ccb_list		ccbs = SIMPLEQ_HEAD_INITIALIZER(ccbs);
   2430   1.1    bouyer 	struct mpii_softc		*sc = arg;
   2431   1.1    bouyer 	struct mpii_reply_descr		*postq = sc->sc_reply_postq_kva, *rdp;
   2432   1.1    bouyer 	struct mpii_ccb			*ccb;
   2433   1.1    bouyer 	struct mpii_rcb			*rcb;
   2434   1.1    bouyer 	int				smid;
   2435   1.1    bouyer 	int				rv = 0;
   2436   1.1    bouyer 
   2437   1.1    bouyer 	mutex_enter(&sc->sc_rep_mtx);
   2438   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat,
   2439   1.1    bouyer 	    MPII_DMA_MAP(sc->sc_reply_postq),
   2440   1.1    bouyer 	    0, 8 * sc->sc_reply_post_qdepth,
   2441   1.1    bouyer 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
   2442   1.1    bouyer 
   2443   1.1    bouyer 	for (;;) {
   2444   1.1    bouyer 		rdp = &postq[sc->sc_reply_post_host_index];
   2445   1.1    bouyer 		if ((rdp->reply_flags & MPII_REPLY_DESCR_TYPE_MASK) ==
   2446   1.1    bouyer 		    MPII_REPLY_DESCR_UNUSED)
   2447   1.1    bouyer 			break;
   2448   1.1    bouyer 		if (rdp->data == 0xffffffff) {
   2449   1.1    bouyer 			/*
   2450   1.1    bouyer 			 * ioc is still writing to the reply post queue
   2451   1.1    bouyer 			 * race condition - bail!
   2452   1.1    bouyer 			 */
   2453   1.1    bouyer 			break;
   2454   1.1    bouyer 		}
   2455   1.1    bouyer 
   2456   1.1    bouyer 		smid = le16toh(rdp->smid);
   2457   1.1    bouyer 		rcb = mpii_reply(sc, rdp);
   2458   1.1    bouyer 
   2459   1.1    bouyer 		if (smid) {
   2460   1.1    bouyer 			ccb = &sc->sc_ccbs[smid - 1];
   2461   1.1    bouyer 			ccb->ccb_state = MPII_CCB_READY;
   2462   1.1    bouyer 			ccb->ccb_rcb = rcb;
   2463   1.1    bouyer 			SIMPLEQ_INSERT_TAIL(&ccbs, ccb, u.ccb_link);
   2464   1.1    bouyer 		} else
   2465   1.1    bouyer 			SIMPLEQ_INSERT_TAIL(&evts, rcb, u.rcb_link);
   2466   1.1    bouyer 
   2467   1.1    bouyer 		sc->sc_reply_post_host_index++;
   2468   1.1    bouyer 		sc->sc_reply_post_host_index %= sc->sc_reply_post_qdepth;
   2469   1.1    bouyer 		rv = 1;
   2470   1.1    bouyer 	}
   2471   1.1    bouyer 
   2472   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat,
   2473   1.1    bouyer 	    MPII_DMA_MAP(sc->sc_reply_postq),
   2474   1.1    bouyer 	    0, 8 * sc->sc_reply_post_qdepth,
   2475   1.1    bouyer 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
   2476   1.1    bouyer 
   2477   1.1    bouyer 	if (rv)
   2478   1.1    bouyer 		mpii_write_reply_post(sc, sc->sc_reply_post_host_index);
   2479   1.1    bouyer 
   2480   1.1    bouyer 	mutex_exit(&sc->sc_rep_mtx);
   2481   1.1    bouyer 
   2482   1.1    bouyer 	if (rv == 0)
   2483   1.1    bouyer 		return (0);
   2484   1.1    bouyer 
   2485   1.1    bouyer 	while ((ccb = SIMPLEQ_FIRST(&ccbs)) != NULL) {
   2486   1.1    bouyer 		SIMPLEQ_REMOVE_HEAD(&ccbs, u.ccb_link);
   2487   1.1    bouyer 		ccb->ccb_done(ccb);
   2488   1.1    bouyer 	}
   2489   1.1    bouyer 	while ((rcb = SIMPLEQ_FIRST(&evts)) != NULL) {
   2490   1.1    bouyer 		SIMPLEQ_REMOVE_HEAD(&evts, u.rcb_link);
   2491   1.1    bouyer 		mpii_event_process(sc, rcb);
   2492   1.1    bouyer 	}
   2493   1.1    bouyer 
   2494   1.1    bouyer 	return (1);
   2495   1.1    bouyer }
   2496   1.1    bouyer 
   2497   1.1    bouyer static int
   2498   1.1    bouyer mpii_load_xs(struct mpii_ccb *ccb)
   2499   1.1    bouyer {
   2500   1.1    bouyer 	struct mpii_softc	*sc = ccb->ccb_sc;
   2501   1.1    bouyer 	struct scsipi_xfer	*xs = ccb->ccb_cookie;
   2502   1.1    bouyer 	struct mpii_ccb_bundle	*mcb = ccb->ccb_cmd;
   2503   1.1    bouyer 	struct mpii_msg_scsi_io	*io = &mcb->mcb_io;
   2504   1.1    bouyer 	struct mpii_sge		*sge = NULL, *nsge = &mcb->mcb_sgl[0];
   2505   1.1    bouyer 	struct mpii_sge		*ce = NULL, *nce = NULL;
   2506   1.1    bouyer 	u_int64_t		ce_dva;
   2507   1.1    bouyer 	bus_dmamap_t		dmap = ccb->ccb_dmamap;
   2508   1.1    bouyer 	u_int32_t		addr, flags;
   2509   1.1    bouyer 	int			i, error;
   2510   1.1    bouyer 
   2511   1.1    bouyer 	/* zero length transfer still requires an SGE */
   2512   1.1    bouyer 	if (xs->datalen == 0) {
   2513   1.1    bouyer 		nsge->sg_hdr = htole32(MPII_SGE_FL_TYPE_SIMPLE |
   2514   1.1    bouyer 		    MPII_SGE_FL_LAST | MPII_SGE_FL_EOB | MPII_SGE_FL_EOL);
   2515   1.1    bouyer 		return (0);
   2516   1.1    bouyer 	}
   2517   1.1    bouyer 
   2518   1.1    bouyer 	error = bus_dmamap_load(sc->sc_dmat, dmap,
   2519   1.1    bouyer 	    xs->data, xs->datalen, NULL, (xs->xs_control & XS_CTL_NOSLEEP) ?
   2520   1.1    bouyer 	      BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
   2521   1.1    bouyer 	if (error) {
   2522   1.1    bouyer 		aprint_error_dev(sc->sc_dev, "error %d loading dmamap\n",
   2523   1.1    bouyer 		    error);
   2524   1.1    bouyer 		return (1);
   2525   1.1    bouyer 	}
   2526   1.1    bouyer 
   2527   1.1    bouyer 	/* safe default staring flags */
   2528   1.1    bouyer 	flags = MPII_SGE_FL_TYPE_SIMPLE | MPII_SGE_FL_SIZE_64;
   2529   1.1    bouyer 	/* if data out */
   2530   1.1    bouyer 	if (xs->xs_control & XS_CTL_DATA_OUT)
   2531   1.1    bouyer 		flags |= MPII_SGE_FL_DIR_OUT;
   2532   1.1    bouyer 
   2533   1.1    bouyer 	/* we will have to exceed the SGEs we can cram into the request frame */
   2534   1.1    bouyer 	if (dmap->dm_nsegs > sc->sc_first_sgl_len) {
   2535   1.1    bouyer 		ce = &mcb->mcb_sgl[sc->sc_first_sgl_len - 1];
   2536   1.1    bouyer 		io->chain_offset = ((u_int8_t *)ce - (u_int8_t *)io) / 4;
   2537   1.1    bouyer 	}
   2538   1.1    bouyer 
   2539   1.1    bouyer 	for (i = 0; i < dmap->dm_nsegs; i++) {
   2540   1.1    bouyer 		if (nsge == ce) {
   2541   1.1    bouyer 			nsge++;
   2542   1.1    bouyer 			sge->sg_hdr |= htole32(MPII_SGE_FL_LAST);
   2543   1.1    bouyer 
   2544   1.1    bouyer 			DNPRINTF(MPII_D_DMA, "%s:   - 0x%08x 0x%08x 0x%08x\n",
   2545   1.1    bouyer 			    DEVNAME(sc), sge->sg_hdr,
   2546   1.1    bouyer 			    sge->sg_hi_addr, sge->sg_lo_addr);
   2547   1.1    bouyer 
   2548   1.1    bouyer 			if ((dmap->dm_nsegs - i) > sc->sc_chain_len) {
   2549   1.1    bouyer 				nce = &nsge[sc->sc_chain_len - 1];
   2550   1.1    bouyer 				addr = ((u_int8_t *)nce - (u_int8_t *)nsge) / 4;
   2551   1.1    bouyer 				addr = addr << 16 |
   2552   1.1    bouyer 				    sizeof(struct mpii_sge) * sc->sc_chain_len;
   2553   1.1    bouyer 			} else {
   2554   1.1    bouyer 				nce = NULL;
   2555   1.1    bouyer 				addr = sizeof(struct mpii_sge) *
   2556   1.1    bouyer 				    (dmap->dm_nsegs - i);
   2557   1.1    bouyer 			}
   2558   1.1    bouyer 
   2559   1.1    bouyer 			ce->sg_hdr = htole32(MPII_SGE_FL_TYPE_CHAIN |
   2560   1.1    bouyer 			    MPII_SGE_FL_SIZE_64 | addr);
   2561   1.1    bouyer 
   2562   1.1    bouyer 			ce_dva = ccb->ccb_cmd_dva +
   2563   1.1    bouyer 			    ((u_int8_t *)nsge - (u_int8_t *)mcb);
   2564   1.1    bouyer 
   2565   1.1    bouyer 			addr = (u_int32_t)(ce_dva >> 32);
   2566   1.1    bouyer 			ce->sg_hi_addr = htole32(addr);
   2567   1.1    bouyer 			addr = (u_int32_t)ce_dva;
   2568   1.1    bouyer 			ce->sg_lo_addr = htole32(addr);
   2569   1.1    bouyer 
   2570   1.1    bouyer 			DNPRINTF(MPII_D_DMA, "%s:  ce: 0x%08x 0x%08x 0x%08x\n",
   2571   1.1    bouyer 			    DEVNAME(sc), ce->sg_hdr, ce->sg_hi_addr,
   2572   1.1    bouyer 			    ce->sg_lo_addr);
   2573   1.1    bouyer 
   2574   1.1    bouyer 			ce = nce;
   2575   1.1    bouyer 		}
   2576   1.1    bouyer 
   2577   1.1    bouyer 		DNPRINTF(MPII_D_DMA, "%s:  %d: %" PRId64 " 0x%016" PRIx64 "\n",
   2578   1.1    bouyer 		    DEVNAME(sc), i, (int64_t)dmap->dm_segs[i].ds_len,
   2579   1.1    bouyer 		    (u_int64_t)dmap->dm_segs[i].ds_addr);
   2580   1.1    bouyer 
   2581   1.1    bouyer 		sge = nsge;
   2582   1.1    bouyer 
   2583   1.1    bouyer 		sge->sg_hdr = htole32(flags | dmap->dm_segs[i].ds_len);
   2584   1.1    bouyer 		addr = (u_int32_t)((u_int64_t)dmap->dm_segs[i].ds_addr >> 32);
   2585   1.1    bouyer 		sge->sg_hi_addr = htole32(addr);
   2586   1.1    bouyer 		addr = (u_int32_t)dmap->dm_segs[i].ds_addr;
   2587   1.1    bouyer 		sge->sg_lo_addr = htole32(addr);
   2588   1.1    bouyer 
   2589   1.1    bouyer 		DNPRINTF(MPII_D_DMA, "%s:  %d: 0x%08x 0x%08x 0x%08x\n",
   2590   1.1    bouyer 		    DEVNAME(sc), i, sge->sg_hdr, sge->sg_hi_addr,
   2591   1.1    bouyer 		    sge->sg_lo_addr);
   2592   1.1    bouyer 
   2593   1.1    bouyer 		nsge = sge + 1;
   2594   1.1    bouyer 	}
   2595   1.1    bouyer 
   2596   1.1    bouyer 	/* terminate list */
   2597   1.1    bouyer 	sge->sg_hdr |= htole32(MPII_SGE_FL_LAST | MPII_SGE_FL_EOB |
   2598   1.1    bouyer 	    MPII_SGE_FL_EOL);
   2599   1.1    bouyer 
   2600   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
   2601   1.1    bouyer 	    (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD :
   2602   1.1    bouyer 	    BUS_DMASYNC_PREWRITE);
   2603   1.1    bouyer 
   2604   1.1    bouyer 	return (0);
   2605   1.1    bouyer }
   2606   1.1    bouyer 
   2607   1.1    bouyer static u_int32_t
   2608   1.1    bouyer mpii_read(struct mpii_softc *sc, bus_size_t r)
   2609   1.1    bouyer {
   2610   1.1    bouyer 	u_int32_t			rv;
   2611   1.1    bouyer 
   2612   1.1    bouyer 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
   2613   1.1    bouyer 	    BUS_SPACE_BARRIER_READ);
   2614   1.1    bouyer 	rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
   2615   1.1    bouyer 
   2616   1.1    bouyer 	DNPRINTF(MPII_D_RW, "%s: mpii_read %#" PRIx64 " %#x\n", DEVNAME(sc),
   2617   1.1    bouyer 	    (uint64_t)r, rv);
   2618   1.1    bouyer 
   2619   1.1    bouyer 	return (rv);
   2620   1.1    bouyer }
   2621   1.1    bouyer 
   2622   1.1    bouyer static void
   2623   1.1    bouyer mpii_write(struct mpii_softc *sc, bus_size_t r, u_int32_t v)
   2624   1.1    bouyer {
   2625   1.1    bouyer 	DNPRINTF(MPII_D_RW, "%s: mpii_write %#" PRIx64 " %#x\n", DEVNAME(sc),
   2626   1.1    bouyer 	    (uint64_t)r, v);
   2627   1.1    bouyer 
   2628   1.1    bouyer 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
   2629   1.1    bouyer 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
   2630   1.1    bouyer 	    BUS_SPACE_BARRIER_WRITE);
   2631   1.1    bouyer }
   2632   1.1    bouyer 
   2633   1.1    bouyer 
   2634   1.1    bouyer static int
   2635   1.1    bouyer mpii_wait_eq(struct mpii_softc *sc, bus_size_t r, u_int32_t mask,
   2636   1.1    bouyer     u_int32_t target)
   2637   1.1    bouyer {
   2638   1.1    bouyer 	int			i;
   2639   1.1    bouyer 
   2640   1.1    bouyer 	DNPRINTF(MPII_D_RW, "%s: mpii_wait_eq %#" PRIx64 " %#x %#x\n",
   2641   1.1    bouyer 	    DEVNAME(sc), (uint64_t)r, mask, target);
   2642   1.1    bouyer 
   2643   1.1    bouyer 	for (i = 0; i < 15000; i++) {
   2644   1.1    bouyer 		if ((mpii_read(sc, r) & mask) == target)
   2645   1.1    bouyer 			return (0);
   2646   1.1    bouyer 		delay(1000);
   2647   1.1    bouyer 	}
   2648   1.1    bouyer 
   2649   1.1    bouyer 	return (1);
   2650   1.1    bouyer }
   2651   1.1    bouyer 
   2652   1.1    bouyer static int
   2653   1.1    bouyer mpii_wait_ne(struct mpii_softc *sc, bus_size_t r, u_int32_t mask,
   2654   1.1    bouyer     u_int32_t target)
   2655   1.1    bouyer {
   2656   1.1    bouyer 	int			i;
   2657   1.1    bouyer 
   2658   1.1    bouyer 	DNPRINTF(MPII_D_RW, "%s: mpii_wait_ne %#" PRIx64 " %#x %#x\n",
   2659   1.1    bouyer 	    DEVNAME(sc), (uint64_t)r, mask, target);
   2660   1.1    bouyer 
   2661   1.1    bouyer 	for (i = 0; i < 15000; i++) {
   2662   1.1    bouyer 		if ((mpii_read(sc, r) & mask) != target)
   2663   1.1    bouyer 			return (0);
   2664   1.1    bouyer 		delay(1000);
   2665   1.1    bouyer 	}
   2666   1.1    bouyer 
   2667   1.1    bouyer 	return (1);
   2668   1.1    bouyer }
   2669   1.1    bouyer 
   2670   1.1    bouyer 
   2671   1.1    bouyer static int
   2672   1.1    bouyer mpii_init(struct mpii_softc *sc)
   2673   1.1    bouyer {
   2674   1.1    bouyer 	u_int32_t		db;
   2675   1.1    bouyer 	int			i;
   2676   1.1    bouyer 
   2677   1.1    bouyer 	/* spin until the ioc leaves the reset state */
   2678   1.1    bouyer 	if (mpii_wait_ne(sc, MPII_DOORBELL, MPII_DOORBELL_STATE,
   2679   1.1    bouyer 	    MPII_DOORBELL_STATE_RESET) != 0) {
   2680   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_init timeout waiting to leave "
   2681   1.1    bouyer 		    "reset state\n", DEVNAME(sc));
   2682   1.1    bouyer 		return (1);
   2683   1.1    bouyer 	}
   2684   1.1    bouyer 
   2685   1.1    bouyer 	/* check current ownership */
   2686   1.1    bouyer 	db = mpii_read_db(sc);
   2687   1.1    bouyer 	if ((db & MPII_DOORBELL_WHOINIT) == MPII_DOORBELL_WHOINIT_PCIPEER) {
   2688   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_init initialised by pci peer\n",
   2689   1.1    bouyer 		    DEVNAME(sc));
   2690   1.1    bouyer 		return (0);
   2691   1.1    bouyer 	}
   2692   1.1    bouyer 
   2693   1.1    bouyer 	for (i = 0; i < 5; i++) {
   2694   1.1    bouyer 		switch (db & MPII_DOORBELL_STATE) {
   2695   1.1    bouyer 		case MPII_DOORBELL_STATE_READY:
   2696   1.1    bouyer 			DNPRINTF(MPII_D_MISC, "%s: mpii_init ioc is ready\n",
   2697   1.1    bouyer 			    DEVNAME(sc));
   2698   1.1    bouyer 			return (0);
   2699   1.1    bouyer 
   2700   1.1    bouyer 		case MPII_DOORBELL_STATE_OPER:
   2701   1.1    bouyer 			DNPRINTF(MPII_D_MISC, "%s: mpii_init ioc is oper\n",
   2702   1.1    bouyer 			    DEVNAME(sc));
   2703   1.1    bouyer 			if (sc->sc_ioc_event_replay)
   2704   1.1    bouyer 				mpii_reset_soft(sc);
   2705   1.1    bouyer 			else
   2706   1.1    bouyer 				mpii_reset_hard(sc);
   2707   1.1    bouyer 			break;
   2708   1.1    bouyer 
   2709   1.1    bouyer 		case MPII_DOORBELL_STATE_FAULT:
   2710   1.1    bouyer 			DNPRINTF(MPII_D_MISC, "%s: mpii_init ioc is being "
   2711   1.1    bouyer 			    "reset hard\n" , DEVNAME(sc));
   2712   1.1    bouyer 			mpii_reset_hard(sc);
   2713   1.1    bouyer 			break;
   2714   1.1    bouyer 
   2715   1.1    bouyer 		case MPII_DOORBELL_STATE_RESET:
   2716   1.1    bouyer 			DNPRINTF(MPII_D_MISC, "%s: mpii_init waiting to come "
   2717   1.1    bouyer 			    "out of reset\n", DEVNAME(sc));
   2718   1.1    bouyer 			if (mpii_wait_ne(sc, MPII_DOORBELL, MPII_DOORBELL_STATE,
   2719   1.1    bouyer 			    MPII_DOORBELL_STATE_RESET) != 0)
   2720   1.1    bouyer 				return (1);
   2721   1.1    bouyer 			break;
   2722   1.1    bouyer 		}
   2723   1.1    bouyer 		db = mpii_read_db(sc);
   2724   1.1    bouyer 	}
   2725   1.1    bouyer 
   2726   1.1    bouyer 	return (1);
   2727   1.1    bouyer }
   2728   1.1    bouyer 
   2729   1.1    bouyer static int
   2730   1.1    bouyer mpii_reset_soft(struct mpii_softc *sc)
   2731   1.1    bouyer {
   2732   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_reset_soft\n", DEVNAME(sc));
   2733   1.1    bouyer 
   2734   1.1    bouyer 	if (mpii_read_db(sc) & MPII_DOORBELL_INUSE) {
   2735   1.1    bouyer 		return (1);
   2736   1.1    bouyer 	}
   2737   1.1    bouyer 
   2738   1.1    bouyer 	mpii_write_db(sc,
   2739   1.1    bouyer 	    MPII_DOORBELL_FUNCTION(MPII_FUNCTION_IOC_MESSAGE_UNIT_RESET));
   2740   1.1    bouyer 
   2741   1.1    bouyer 	/* XXX LSI waits 15 sec */
   2742   1.1    bouyer 	if (mpii_wait_db_ack(sc) != 0)
   2743   1.1    bouyer 		return (1);
   2744   1.1    bouyer 
   2745   1.1    bouyer 	/* XXX LSI waits 15 sec */
   2746   1.1    bouyer 	if (mpii_wait_eq(sc, MPII_DOORBELL, MPII_DOORBELL_STATE,
   2747   1.1    bouyer 	    MPII_DOORBELL_STATE_READY) != 0)
   2748   1.1    bouyer 		return (1);
   2749   1.1    bouyer 
   2750   1.1    bouyer 	/* XXX wait for Sys2IOCDB bit to clear in HIS?? */
   2751   1.1    bouyer 
   2752   1.1    bouyer 	return (0);
   2753   1.1    bouyer }
   2754   1.1    bouyer 
   2755   1.1    bouyer static int
   2756   1.1    bouyer mpii_reset_hard(struct mpii_softc *sc)
   2757   1.1    bouyer {
   2758   1.1    bouyer 	u_int16_t		i;
   2759   1.1    bouyer 
   2760   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_reset_hard\n", DEVNAME(sc));
   2761   1.1    bouyer 
   2762   1.1    bouyer 	mpii_write_intr(sc, 0);
   2763   1.1    bouyer 
   2764   1.1    bouyer 	/* enable diagnostic register */
   2765   1.1    bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_FLUSH);
   2766   1.1    bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_1);
   2767   1.1    bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_2);
   2768   1.1    bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_3);
   2769   1.1    bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_4);
   2770   1.1    bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_5);
   2771   1.1    bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_6);
   2772   1.1    bouyer 
   2773   1.1    bouyer 	delay(100);
   2774   1.1    bouyer 
   2775   1.1    bouyer 	if ((mpii_read(sc, MPII_HOSTDIAG) & MPII_HOSTDIAG_DWRE) == 0) {
   2776   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_reset_hard failure to enable "
   2777   1.1    bouyer 		    "diagnostic read/write\n", DEVNAME(sc));
   2778   1.1    bouyer 		return(1);
   2779   1.1    bouyer 	}
   2780   1.1    bouyer 
   2781   1.1    bouyer 	/* reset ioc */
   2782   1.1    bouyer 	mpii_write(sc, MPII_HOSTDIAG, MPII_HOSTDIAG_RESET_ADAPTER);
   2783   1.1    bouyer 
   2784   1.1    bouyer 	/* 240 milliseconds */
   2785   1.1    bouyer 	delay(240000);
   2786   1.1    bouyer 
   2787   1.1    bouyer 
   2788   1.1    bouyer 	/* XXX this whole function should be more robust */
   2789   1.1    bouyer 
   2790   1.1    bouyer 	/* XXX  read the host diagnostic reg until reset adapter bit clears ? */
   2791   1.1    bouyer 	for (i = 0; i < 30000; i++) {
   2792   1.1    bouyer 		if ((mpii_read(sc, MPII_HOSTDIAG) &
   2793   1.1    bouyer 		    MPII_HOSTDIAG_RESET_ADAPTER) == 0)
   2794   1.1    bouyer 			break;
   2795   1.1    bouyer 		delay(10000);
   2796   1.1    bouyer 	}
   2797   1.1    bouyer 
   2798   1.1    bouyer 	/* disable diagnostic register */
   2799   1.1    bouyer 	mpii_write(sc, MPII_WRITESEQ, 0xff);
   2800   1.1    bouyer 
   2801   1.1    bouyer 	/* XXX what else? */
   2802   1.1    bouyer 
   2803   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: done with mpii_reset_hard\n", DEVNAME(sc));
   2804   1.1    bouyer 
   2805   1.1    bouyer 	return(0);
   2806   1.1    bouyer }
   2807   1.1    bouyer 
   2808   1.1    bouyer static int
   2809   1.1    bouyer mpii_handshake_send(struct mpii_softc *sc, void *buf, size_t dwords)
   2810   1.1    bouyer {
   2811   1.1    bouyer 	u_int32_t		*query = buf;
   2812   1.1    bouyer 	int			i;
   2813   1.1    bouyer 
   2814   1.1    bouyer 	/* make sure the doorbell is not in use. */
   2815   1.1    bouyer 	if (mpii_read_db(sc) & MPII_DOORBELL_INUSE)
   2816   1.1    bouyer 		return (1);
   2817   1.1    bouyer 
   2818   1.1    bouyer 	/* clear pending doorbell interrupts */
   2819   1.1    bouyer 	if (mpii_read_intr(sc) & MPII_INTR_STATUS_IOC2SYSDB)
   2820   1.1    bouyer 		mpii_write_intr(sc, 0);
   2821   1.1    bouyer 
   2822   1.1    bouyer 	/*
   2823   1.1    bouyer 	 * first write the doorbell with the handshake function and the
   2824   1.1    bouyer 	 * dword count.
   2825   1.1    bouyer 	 */
   2826   1.1    bouyer 	mpii_write_db(sc, MPII_DOORBELL_FUNCTION(MPII_FUNCTION_HANDSHAKE) |
   2827   1.1    bouyer 	    MPII_DOORBELL_DWORDS(dwords));
   2828   1.1    bouyer 
   2829   1.1    bouyer 	/*
   2830   1.1    bouyer 	 * the doorbell used bit will be set because a doorbell function has
   2831   1.1    bouyer 	 * started. wait for the interrupt and then ack it.
   2832   1.1    bouyer 	 */
   2833   1.1    bouyer 	if (mpii_wait_db_int(sc) != 0)
   2834   1.1    bouyer 		return (1);
   2835   1.1    bouyer 	mpii_write_intr(sc, 0);
   2836   1.1    bouyer 
   2837   1.1    bouyer 	/* poll for the acknowledgement. */
   2838   1.1    bouyer 	if (mpii_wait_db_ack(sc) != 0)
   2839   1.1    bouyer 		return (1);
   2840   1.1    bouyer 
   2841   1.1    bouyer 	/* write the query through the doorbell. */
   2842   1.1    bouyer 	for (i = 0; i < dwords; i++) {
   2843   1.1    bouyer 		mpii_write_db(sc, htole32(query[i]));
   2844   1.1    bouyer 		if (mpii_wait_db_ack(sc) != 0)
   2845   1.1    bouyer 			return (1);
   2846   1.1    bouyer 	}
   2847   1.1    bouyer 
   2848   1.1    bouyer 	return (0);
   2849   1.1    bouyer }
   2850   1.1    bouyer 
   2851   1.1    bouyer static int
   2852   1.1    bouyer mpii_handshake_recv_dword(struct mpii_softc *sc, u_int32_t *dword)
   2853   1.1    bouyer {
   2854   1.1    bouyer 	u_int16_t		*words = (u_int16_t *)dword;
   2855   1.1    bouyer 	int			i;
   2856   1.1    bouyer 
   2857   1.1    bouyer 	for (i = 0; i < 2; i++) {
   2858   1.1    bouyer 		if (mpii_wait_db_int(sc) != 0)
   2859   1.1    bouyer 			return (1);
   2860   1.1    bouyer 		words[i] = le16toh(mpii_read_db(sc) & MPII_DOORBELL_DATA_MASK);
   2861   1.1    bouyer 		mpii_write_intr(sc, 0);
   2862   1.1    bouyer 	}
   2863   1.1    bouyer 
   2864   1.1    bouyer 	return (0);
   2865   1.1    bouyer }
   2866   1.1    bouyer 
   2867   1.1    bouyer static int
   2868   1.1    bouyer mpii_handshake_recv(struct mpii_softc *sc, void *buf, size_t dwords)
   2869   1.1    bouyer {
   2870   1.1    bouyer 	struct mpii_msg_reply	*reply = buf;
   2871   1.1    bouyer 	u_int32_t		*dbuf = buf, dummy;
   2872   1.1    bouyer 	int			i;
   2873   1.1    bouyer 
   2874   1.1    bouyer 	/* get the first dword so we can read the length out of the header. */
   2875   1.1    bouyer 	if (mpii_handshake_recv_dword(sc, &dbuf[0]) != 0)
   2876   1.1    bouyer 		return (1);
   2877   1.1    bouyer 
   2878   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s: mpii_handshake_recv dwords: %zd reply: %d\n",
   2879   1.1    bouyer 	    DEVNAME(sc), dwords, reply->msg_length);
   2880   1.1    bouyer 
   2881   1.1    bouyer 	/*
   2882   1.1    bouyer 	 * the total length, in dwords, is in the message length field of the
   2883   1.1    bouyer 	 * reply header.
   2884   1.1    bouyer 	 */
   2885   1.1    bouyer 	for (i = 1; i < MIN(dwords, reply->msg_length); i++) {
   2886   1.1    bouyer 		if (mpii_handshake_recv_dword(sc, &dbuf[i]) != 0)
   2887   1.1    bouyer 			return (1);
   2888   1.1    bouyer 	}
   2889   1.1    bouyer 
   2890   1.1    bouyer 	/* if there's extra stuff to come off the ioc, discard it */
   2891   1.1    bouyer 	while (i++ < reply->msg_length) {
   2892   1.1    bouyer 		if (mpii_handshake_recv_dword(sc, &dummy) != 0)
   2893   1.1    bouyer 			return (1);
   2894   1.1    bouyer 		DNPRINTF(MPII_D_CMD, "%s: mpii_handshake_recv dummy read: "
   2895   1.1    bouyer 		    "0x%08x\n", DEVNAME(sc), dummy);
   2896   1.1    bouyer 	}
   2897   1.1    bouyer 
   2898   1.1    bouyer 	/* wait for the doorbell used bit to be reset and clear the intr */
   2899   1.1    bouyer 	if (mpii_wait_db_int(sc) != 0)
   2900   1.1    bouyer 		return (1);
   2901   1.1    bouyer 
   2902   1.1    bouyer 	if (mpii_wait_eq(sc, MPII_DOORBELL, MPII_DOORBELL_INUSE, 0) != 0)
   2903   1.1    bouyer 		return (1);
   2904   1.1    bouyer 
   2905   1.1    bouyer 	mpii_write_intr(sc, 0);
   2906   1.1    bouyer 
   2907   1.1    bouyer 	return (0);
   2908   1.1    bouyer }
   2909   1.1    bouyer 
   2910   1.1    bouyer static void
   2911   1.1    bouyer mpii_empty_done(struct mpii_ccb *ccb)
   2912   1.1    bouyer {
   2913   1.1    bouyer 	/* nothing to do */
   2914   1.1    bouyer }
   2915   1.1    bouyer 
   2916   1.1    bouyer static int
   2917   1.1    bouyer mpii_iocfacts(struct mpii_softc *sc)
   2918   1.1    bouyer {
   2919   1.1    bouyer 	struct mpii_msg_iocfacts_request	ifq;
   2920   1.1    bouyer 	struct mpii_msg_iocfacts_reply		ifp;
   2921   1.1    bouyer 
   2922   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_iocfacts\n", DEVNAME(sc));
   2923   1.1    bouyer 
   2924   1.1    bouyer 	bzero(&ifq, sizeof(ifq));
   2925   1.1    bouyer 	bzero(&ifp, sizeof(ifp));
   2926   1.1    bouyer 
   2927   1.1    bouyer 	ifq.function = MPII_FUNCTION_IOC_FACTS;
   2928   1.1    bouyer 
   2929   1.1    bouyer 	if (mpii_handshake_send(sc, &ifq, dwordsof(ifq)) != 0) {
   2930   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_iocfacts send failed\n",
   2931   1.1    bouyer 		    DEVNAME(sc));
   2932   1.1    bouyer 		return (1);
   2933   1.1    bouyer 	}
   2934   1.1    bouyer 
   2935   1.1    bouyer 	if (mpii_handshake_recv(sc, &ifp, dwordsof(ifp)) != 0) {
   2936   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_iocfacts recv failed\n",
   2937   1.1    bouyer 		    DEVNAME(sc));
   2938   1.1    bouyer 		return (1);
   2939   1.1    bouyer 	}
   2940   1.1    bouyer 
   2941   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  func: 0x%02x length: %d msgver: %d.%d\n",
   2942   1.1    bouyer 	    DEVNAME(sc), ifp.function, ifp.msg_length,
   2943   1.1    bouyer 	    ifp.msg_version_maj, ifp.msg_version_min);
   2944   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  msgflags: 0x%02x iocnumber: 0x%02x "
   2945   1.1    bouyer 	    "headerver: %d.%d\n", DEVNAME(sc), ifp.msg_flags,
   2946   1.1    bouyer 	    ifp.ioc_number, ifp.header_version_unit,
   2947   1.1    bouyer 	    ifp.header_version_dev);
   2948   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc),
   2949   1.1    bouyer 	    ifp.vp_id, ifp.vf_id);
   2950   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  iocstatus: 0x%04x ioexceptions: 0x%04x\n",
   2951   1.1    bouyer 	    DEVNAME(sc), le16toh(ifp.ioc_status),
   2952   1.1    bouyer 	    le16toh(ifp.ioc_exceptions));
   2953   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  iocloginfo: 0x%08x\n", DEVNAME(sc),
   2954   1.1    bouyer 	    le32toh(ifp.ioc_loginfo));
   2955   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  numberofports: 0x%02x whoinit: 0x%02x "
   2956   1.1    bouyer 	    "maxchaindepth: %d\n", DEVNAME(sc), ifp.number_of_ports,
   2957   1.1    bouyer 	    ifp.whoinit, ifp.max_chain_depth);
   2958   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  productid: 0x%04x requestcredit: 0x%04x\n",
   2959   1.1    bouyer 	    DEVNAME(sc), le16toh(ifp.product_id), le16toh(ifp.request_credit));
   2960   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_capabilities: 0x%08x\n", DEVNAME(sc),
   2961   1.1    bouyer 	    le32toh(ifp.ioc_capabilities));
   2962   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  fw_version: %d.%d fw_version_unit: 0x%02x "
   2963   1.1    bouyer 	    "fw_version_dev: 0x%02x\n", DEVNAME(sc),
   2964   1.1    bouyer 	    ifp.fw_version_maj, ifp.fw_version_min,
   2965   1.1    bouyer 	    ifp.fw_version_unit, ifp.fw_version_dev);
   2966   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  iocrequestframesize: 0x%04x\n",
   2967   1.1    bouyer 	    DEVNAME(sc), le16toh(ifp.ioc_request_frame_size));
   2968   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  maxtargets: 0x%04x "
   2969   1.1    bouyer 	    "maxinitiators: 0x%04x\n", DEVNAME(sc),
   2970   1.1    bouyer 	    le16toh(ifp.max_targets), le16toh(ifp.max_initiators));
   2971   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  maxenclosures: 0x%04x "
   2972   1.1    bouyer 	    "maxsasexpanders: 0x%04x\n", DEVNAME(sc),
   2973   1.1    bouyer 	    le16toh(ifp.max_enclosures), le16toh(ifp.max_sas_expanders));
   2974   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  highprioritycredit: 0x%04x "
   2975   1.1    bouyer 	    "protocolflags: 0x%02x\n", DEVNAME(sc),
   2976   1.1    bouyer 	    le16toh(ifp.high_priority_credit), le16toh(ifp.protocol_flags));
   2977   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  maxvolumes: 0x%02x replyframesize: 0x%02x "
   2978   1.1    bouyer 	    "mrdpqd: 0x%04x\n", DEVNAME(sc), ifp.max_volumes,
   2979   1.1    bouyer 	    ifp.reply_frame_size,
   2980   1.1    bouyer 	    le16toh(ifp.max_reply_descriptor_post_queue_depth));
   2981   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  maxpersistententries: 0x%04x "
   2982   1.1    bouyer 	    "maxdevhandle: 0x%02x\n", DEVNAME(sc),
   2983   1.1    bouyer 	    le16toh(ifp.max_persistent_entries), le16toh(ifp.max_dev_handle));
   2984   1.1    bouyer 
   2985   1.1    bouyer 	sc->sc_maxchdepth = ifp.max_chain_depth;
   2986   1.1    bouyer 	sc->sc_ioc_number = ifp.ioc_number;
   2987   1.1    bouyer 	sc->sc_vf_id = ifp.vf_id;
   2988   1.1    bouyer 
   2989   1.1    bouyer 	sc->sc_num_ports = ifp.number_of_ports;
   2990   1.1    bouyer 	sc->sc_ioc_event_replay = (le32toh(ifp.ioc_capabilities) &
   2991   1.1    bouyer 	    MPII_IOCFACTS_CAPABILITY_EVENT_REPLAY) ? 1 : 0;
   2992   1.1    bouyer 	sc->sc_max_enclosures = le16toh(ifp.max_enclosures);
   2993   1.1    bouyer 	sc->sc_max_expanders = le16toh(ifp.max_sas_expanders);
   2994   1.1    bouyer 	sc->sc_max_volumes = ifp.max_volumes;
   2995   1.1    bouyer 	sc->sc_max_devices = ifp.max_volumes + le16toh(ifp.max_targets);
   2996   1.1    bouyer 	sc->sc_num_channels = 1;
   2997   1.1    bouyer 
   2998   1.1    bouyer 	if (ISSET(le32toh(ifp.ioc_capabilities),
   2999   1.1    bouyer 	    MPII_IOCFACTS_CAPABILITY_INTEGRATED_RAID))
   3000   1.1    bouyer 		SET(sc->sc_flags, MPII_F_RAID);
   3001   1.1    bouyer 
   3002   1.1    bouyer 	sc->sc_request_depth = MIN(le16toh(ifp.request_credit),
   3003   1.1    bouyer 	    MPII_MAX_REQUEST_CREDIT);
   3004   1.1    bouyer 
   3005   1.1    bouyer 	/* should not be multiple of 16 */
   3006   1.1    bouyer 	sc->sc_num_reply_frames = sc->sc_request_depth + 32;
   3007   1.1    bouyer 	if (!(sc->sc_num_reply_frames % 16))
   3008   1.1    bouyer 		sc->sc_num_reply_frames--;
   3009   1.1    bouyer 
   3010   1.1    bouyer 	/* must be multiple of 16 */
   3011   1.1    bouyer 	sc->sc_reply_free_qdepth = sc->sc_num_reply_frames +
   3012   1.1    bouyer 	    (16 - (sc->sc_num_reply_frames % 16));
   3013   1.1    bouyer 	sc->sc_reply_post_qdepth = ((sc->sc_request_depth +
   3014   1.1    bouyer 	    sc->sc_num_reply_frames + 1 + 15) / 16) * 16;
   3015   1.1    bouyer 
   3016   1.1    bouyer 	if (sc->sc_reply_post_qdepth >
   3017   1.1    bouyer 	    ifp.max_reply_descriptor_post_queue_depth)
   3018   1.1    bouyer 		sc->sc_reply_post_qdepth =
   3019   1.1    bouyer 		    ifp.max_reply_descriptor_post_queue_depth;
   3020   1.1    bouyer 
   3021   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: sc_request_depth: %d "
   3022   1.1    bouyer 	    "sc_num_reply_frames: %d sc_reply_free_qdepth: %d "
   3023   1.1    bouyer 	    "sc_reply_post_qdepth: %d\n", DEVNAME(sc), sc->sc_request_depth,
   3024   1.1    bouyer 	    sc->sc_num_reply_frames, sc->sc_reply_free_qdepth,
   3025   1.1    bouyer 	    sc->sc_reply_post_qdepth);
   3026   1.1    bouyer 
   3027   1.1    bouyer 	/*
   3028   1.1    bouyer 	 * you can fit sg elements on the end of the io cmd if they fit in the
   3029   1.1    bouyer 	 * request frame size.
   3030   1.1    bouyer 	 */
   3031   1.1    bouyer 
   3032   1.1    bouyer 	sc->sc_first_sgl_len = ((le16toh(ifp.ioc_request_frame_size) * 4) -
   3033   1.1    bouyer 	    sizeof(struct mpii_msg_scsi_io)) / sizeof(struct mpii_sge);
   3034   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:   first sgl len: %d\n", DEVNAME(sc),
   3035   1.1    bouyer 	    sc->sc_first_sgl_len);
   3036   1.1    bouyer 
   3037   1.1    bouyer 	sc->sc_chain_len = (le16toh(ifp.ioc_request_frame_size) * 4) /
   3038   1.1    bouyer 	    sizeof(struct mpii_sge);
   3039   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:   chain len: %d\n", DEVNAME(sc),
   3040   1.1    bouyer 	    sc->sc_chain_len);
   3041   1.1    bouyer 
   3042   1.1    bouyer 	/* the sgl tailing the io cmd loses an entry to the chain element. */
   3043   1.1    bouyer 	sc->sc_max_sgl_len = MPII_MAX_SGL - 1;
   3044   1.1    bouyer 	/* the sgl chains lose an entry for each chain element */
   3045   1.1    bouyer 	sc->sc_max_sgl_len -= (MPII_MAX_SGL - sc->sc_first_sgl_len) /
   3046   1.1    bouyer 	    sc->sc_chain_len;
   3047   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:   max sgl len: %d\n", DEVNAME(sc),
   3048   1.1    bouyer 	    sc->sc_max_sgl_len);
   3049   1.1    bouyer 
   3050   1.1    bouyer 	/* XXX we're ignoring the max chain depth */
   3051   1.1    bouyer 
   3052   1.1    bouyer 	return(0);
   3053   1.1    bouyer 
   3054   1.1    bouyer }
   3055   1.1    bouyer 
   3056   1.1    bouyer static int
   3057   1.1    bouyer mpii_iocinit(struct mpii_softc *sc)
   3058   1.1    bouyer {
   3059   1.1    bouyer 	struct mpii_msg_iocinit_request		iiq;
   3060   1.1    bouyer 	struct mpii_msg_iocinit_reply		iip;
   3061   1.1    bouyer 	u_int32_t				hi_addr;
   3062   1.1    bouyer 
   3063   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_iocinit\n", DEVNAME(sc));
   3064   1.1    bouyer 
   3065   1.1    bouyer 	bzero(&iiq, sizeof(iiq));
   3066   1.1    bouyer 	bzero(&iip, sizeof(iip));
   3067   1.1    bouyer 
   3068   1.1    bouyer 	iiq.function = MPII_FUNCTION_IOC_INIT;
   3069   1.1    bouyer 	iiq.whoinit = MPII_WHOINIT_HOST_DRIVER;
   3070   1.1    bouyer 
   3071   1.1    bouyer 	/* XXX JPG do something about vf_id */
   3072   1.1    bouyer 	iiq.vf_id = 0;
   3073   1.1    bouyer 
   3074   1.1    bouyer 	iiq.msg_version_maj = 0x02;
   3075   1.1    bouyer 	iiq.msg_version_min = 0x00;
   3076   1.1    bouyer 
   3077   1.1    bouyer 	/* XXX JPG ensure compliance with some level and hard-code? */
   3078   1.1    bouyer 	iiq.hdr_version_unit = 0x00;
   3079   1.1    bouyer 	iiq.hdr_version_dev = 0x00;
   3080   1.1    bouyer 
   3081   1.1    bouyer 	iiq.system_request_frame_size = htole16(MPII_REQUEST_SIZE / 4);
   3082   1.1    bouyer 
   3083   1.1    bouyer 	iiq.reply_descriptor_post_queue_depth =
   3084   1.1    bouyer 	    htole16(sc->sc_reply_post_qdepth);
   3085   1.1    bouyer 
   3086   1.1    bouyer 	iiq.reply_free_queue_depth = htole16(sc->sc_reply_free_qdepth);
   3087   1.1    bouyer 
   3088   1.1    bouyer 	hi_addr = (u_int32_t)((u_int64_t)MPII_DMA_DVA(sc->sc_requests) >> 32);
   3089   1.1    bouyer 	iiq.sense_buffer_address_high = htole32(hi_addr);
   3090   1.1    bouyer 
   3091   1.1    bouyer 	hi_addr = (u_int32_t)
   3092   1.1    bouyer 	    ((u_int64_t)MPII_DMA_DVA(sc->sc_replies) >> 32);
   3093   1.1    bouyer 	iiq.system_reply_address_high = htole32(hi_addr);
   3094   1.1    bouyer 
   3095   1.1    bouyer 	iiq.system_request_frame_base_address =
   3096   1.1    bouyer 	    (u_int64_t)MPII_DMA_DVA(sc->sc_requests);
   3097   1.1    bouyer 
   3098   1.1    bouyer 	iiq.reply_descriptor_post_queue_address =
   3099   1.1    bouyer 	    (u_int64_t)MPII_DMA_DVA(sc->sc_reply_postq);
   3100   1.1    bouyer 
   3101   1.1    bouyer 	iiq.reply_free_queue_address =
   3102   1.1    bouyer 	    (u_int64_t)MPII_DMA_DVA(sc->sc_reply_freeq);
   3103   1.1    bouyer 
   3104   1.1    bouyer 	if (mpii_handshake_send(sc, &iiq, dwordsof(iiq)) != 0) {
   3105   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_iocinit send failed\n",
   3106   1.1    bouyer 		    DEVNAME(sc));
   3107   1.1    bouyer 		return (1);
   3108   1.1    bouyer 	}
   3109   1.1    bouyer 
   3110   1.1    bouyer 	if (mpii_handshake_recv(sc, &iip, dwordsof(iip)) != 0) {
   3111   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_iocinit recv failed\n",
   3112   1.1    bouyer 		    DEVNAME(sc));
   3113   1.1    bouyer 		return (1);
   3114   1.1    bouyer 	}
   3115   1.1    bouyer 
   3116   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  function: 0x%02x msg_length: %d "
   3117   1.1    bouyer 	    "whoinit: 0x%02x\n", DEVNAME(sc), iip.function,
   3118   1.1    bouyer 	    iip.msg_length, iip.whoinit);
   3119   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  msg_flags: 0x%02x\n", DEVNAME(sc),
   3120   1.1    bouyer 	    iip.msg_flags);
   3121   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  vf_id: 0x%02x vp_id: 0x%02x\n", DEVNAME(sc),
   3122   1.1    bouyer 	    iip.vf_id, iip.vp_id);
   3123   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
   3124   1.1    bouyer 	    le16toh(iip.ioc_status));
   3125   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
   3126   1.1    bouyer 	    le32toh(iip.ioc_loginfo));
   3127   1.1    bouyer 
   3128   1.1    bouyer 	if ((iip.ioc_status != MPII_IOCSTATUS_SUCCESS) || (iip.ioc_loginfo))
   3129   1.1    bouyer 		return (1);
   3130   1.1    bouyer 
   3131   1.1    bouyer 	return (0);
   3132   1.1    bouyer }
   3133   1.1    bouyer 
   3134   1.1    bouyer static void
   3135   1.1    bouyer mpii_push_reply(struct mpii_softc *sc, struct mpii_rcb *rcb)
   3136   1.1    bouyer {
   3137   1.1    bouyer 	u_int32_t		*rfp;
   3138   1.1    bouyer 
   3139   1.1    bouyer 	if (rcb == NULL)
   3140   1.1    bouyer 		return;
   3141   1.1    bouyer 
   3142   1.1    bouyer 	rfp = MPII_DMA_KVA(sc->sc_reply_freeq);
   3143   1.1    bouyer 	rfp[sc->sc_reply_free_host_index] = rcb->rcb_reply_dva;
   3144   1.1    bouyer 
   3145   1.1    bouyer 	sc->sc_reply_free_host_index = (sc->sc_reply_free_host_index + 1) %
   3146   1.1    bouyer 	    sc->sc_reply_free_qdepth;
   3147   1.1    bouyer 
   3148   1.1    bouyer 	mpii_write_reply_free(sc, sc->sc_reply_free_host_index);
   3149   1.1    bouyer }
   3150   1.1    bouyer 
   3151   1.1    bouyer static int
   3152   1.1    bouyer mpii_portfacts(struct mpii_softc *sc)
   3153   1.1    bouyer {
   3154   1.1    bouyer 	struct mpii_msg_portfacts_request	*pfq;
   3155   1.1    bouyer 	struct mpii_msg_portfacts_reply		*pfp;
   3156   1.1    bouyer 	struct mpii_ccb				*ccb;
   3157   1.1    bouyer 	int					rv = 1;
   3158   1.1    bouyer 
   3159   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_portfacts\n", DEVNAME(sc));
   3160   1.1    bouyer 
   3161   1.1    bouyer 	ccb = mpii_get_ccb(sc, 0);
   3162   1.1    bouyer 	if (ccb == NULL) {
   3163   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_portfacts mpii_get_ccb fail\n",
   3164   1.1    bouyer 		    DEVNAME(sc));
   3165   1.1    bouyer 		return (rv);
   3166   1.1    bouyer 	}
   3167   1.1    bouyer 
   3168   1.1    bouyer 	ccb->ccb_done = mpii_empty_done;
   3169   1.1    bouyer 	pfq = ccb->ccb_cmd;
   3170   1.1    bouyer 
   3171   1.1    bouyer 	bzero(pfq, sizeof(*pfq));
   3172   1.1    bouyer 
   3173   1.1    bouyer 	pfq->function = MPII_FUNCTION_PORT_FACTS;
   3174   1.1    bouyer 	pfq->chain_offset = 0;
   3175   1.1    bouyer 	pfq->msg_flags = 0;
   3176   1.1    bouyer 	pfq->port_number = 0;
   3177   1.1    bouyer 	pfq->vp_id = 0;
   3178   1.1    bouyer 	pfq->vf_id = 0;
   3179   1.1    bouyer 
   3180   1.1    bouyer 	if (mpii_poll(sc, ccb) != 0) {
   3181   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_portfacts poll\n",
   3182   1.1    bouyer 		    DEVNAME(sc));
   3183   1.1    bouyer 		goto err;
   3184   1.1    bouyer 	}
   3185   1.1    bouyer 
   3186   1.1    bouyer 	if (ccb->ccb_rcb == NULL) {
   3187   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: empty portfacts reply\n",
   3188   1.1    bouyer 		    DEVNAME(sc));
   3189   1.1    bouyer 		goto err;
   3190   1.1    bouyer 	}
   3191   1.1    bouyer 
   3192   1.1    bouyer 	pfp = ccb->ccb_rcb->rcb_reply;
   3193   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s   pfp: %p\n", DEVNAME(sc), pfp);
   3194   1.1    bouyer 
   3195   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  function: 0x%02x msg_length: %d\n",
   3196   1.1    bouyer 	    DEVNAME(sc), pfp->function, pfp->msg_length);
   3197   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  msg_flags: 0x%02x port_number: %d\n",
   3198   1.1    bouyer 	    DEVNAME(sc), pfp->msg_flags, pfp->port_number);
   3199   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  vf_id: 0x%02x vp_id: 0x%02x\n",
   3200   1.1    bouyer 	    DEVNAME(sc), pfp->vf_id, pfp->vp_id);
   3201   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
   3202   1.1    bouyer 	    le16toh(pfp->ioc_status));
   3203   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
   3204   1.1    bouyer 	    le32toh(pfp->ioc_loginfo));
   3205   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  port_type: 0x%02x\n", DEVNAME(sc),
   3206   1.1    bouyer 	    pfp->port_type);
   3207   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  max_posted_cmd_buffers: %d\n", DEVNAME(sc),
   3208   1.1    bouyer 	    le16toh(pfp->max_posted_cmd_buffers));
   3209   1.1    bouyer 
   3210   1.1    bouyer 	sc->sc_porttype = pfp->port_type;
   3211   1.1    bouyer 
   3212   1.1    bouyer 	mpii_push_reply(sc, ccb->ccb_rcb);
   3213   1.1    bouyer 	rv = 0;
   3214   1.1    bouyer err:
   3215   1.1    bouyer 	mpii_put_ccb(sc, ccb);
   3216   1.1    bouyer 
   3217   1.1    bouyer 	return (rv);
   3218   1.1    bouyer }
   3219   1.1    bouyer 
   3220   1.1    bouyer static void
   3221   1.1    bouyer mpii_eventack(struct work *wk, void *cookie)
   3222   1.1    bouyer {
   3223   1.1    bouyer 	struct mpii_softc			*sc = cookie;
   3224   1.1    bouyer 	struct mpii_ccb				*ccb;
   3225   1.1    bouyer 	struct mpii_rcb				*rcb = (void *)wk;
   3226   1.1    bouyer 	struct mpii_msg_event_reply		*enp;
   3227   1.1    bouyer 	struct mpii_msg_eventack_request	*eaq;
   3228   1.1    bouyer 
   3229   1.1    bouyer 	ccb = mpii_get_ccb(sc, 0);
   3230   1.1    bouyer 
   3231   1.1    bouyer 	enp = (struct mpii_msg_event_reply *)rcb->rcb_reply;
   3232   1.1    bouyer 
   3233   1.1    bouyer 	ccb->ccb_done = mpii_eventack_done;
   3234   1.1    bouyer 	eaq = ccb->ccb_cmd;
   3235   1.1    bouyer 
   3236   1.1    bouyer 	eaq->function = MPII_FUNCTION_EVENT_ACK;
   3237   1.1    bouyer 
   3238   1.1    bouyer 	eaq->event = enp->event;
   3239   1.1    bouyer 	eaq->event_context = enp->event_context;
   3240   1.1    bouyer 
   3241   1.1    bouyer 	mpii_push_reply(sc, rcb);
   3242   1.1    bouyer 
   3243   1.1    bouyer 	mpii_start(sc, ccb);
   3244   1.1    bouyer 
   3245   1.1    bouyer }
   3246   1.1    bouyer 
   3247   1.1    bouyer static void
   3248   1.1    bouyer mpii_eventack_done(struct mpii_ccb *ccb)
   3249   1.1    bouyer {
   3250   1.1    bouyer 	struct mpii_softc			*sc = ccb->ccb_sc;
   3251   1.1    bouyer 
   3252   1.1    bouyer 	DNPRINTF(MPII_D_EVT, "%s: event ack done\n", DEVNAME(sc));
   3253   1.1    bouyer 
   3254   1.1    bouyer 	mpii_push_reply(sc, ccb->ccb_rcb);
   3255   1.1    bouyer 	mpii_put_ccb(sc, ccb);
   3256   1.1    bouyer }
   3257   1.1    bouyer 
   3258   1.1    bouyer static int
   3259   1.1    bouyer mpii_portenable(struct mpii_softc *sc)
   3260   1.1    bouyer {
   3261   1.1    bouyer 	struct mpii_msg_portenable_request	*peq;
   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 
   3291   1.1    bouyer 	mpii_push_reply(sc, ccb->ccb_rcb);
   3292   1.1    bouyer 	mpii_put_ccb(sc, ccb);
   3293   1.1    bouyer 
   3294   1.1    bouyer 	return (0);
   3295   1.1    bouyer }
   3296   1.1    bouyer 
   3297   1.1    bouyer static int
   3298   1.1    bouyer mpii_cfg_coalescing(struct mpii_softc *sc)
   3299   1.1    bouyer {
   3300   1.1    bouyer 	struct mpii_cfg_hdr		hdr;
   3301   1.1    bouyer 	struct mpii_cfg_ioc_pg1		pg;
   3302   1.1    bouyer 
   3303   1.1    bouyer 	if (mpii_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_IOC, 1, 0,
   3304   1.1    bouyer 	    &hdr) != 0) {
   3305   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: unable to fetch IOC page 1 "
   3306   1.1    bouyer 		    "header\n", DEVNAME(sc));
   3307   1.1    bouyer 		return (1);
   3308   1.1    bouyer 	}
   3309   1.1    bouyer 
   3310   1.1    bouyer 	if (mpii_cfg_page(sc, 0, &hdr, 1, &pg, sizeof(pg)) != 0) {
   3311   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: unable to fetch IOC page 1\n"
   3312   1.1    bouyer 		    "page 1\n", DEVNAME(sc));
   3313   1.1    bouyer 		return (1);
   3314   1.1    bouyer 	}
   3315   1.1    bouyer 
   3316   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: IOC page 1\n", DEVNAME(sc));
   3317   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  flags: 0x08%x\n", DEVNAME(sc),
   3318   1.1    bouyer 	    le32toh(pg.flags));
   3319   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  coalescing_timeout: %d\n", DEVNAME(sc),
   3320   1.1    bouyer 	    le32toh(pg.coalescing_timeout));
   3321   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  coalescing_depth: %d pci_slot_num: %d\n",
   3322   1.1    bouyer 	    DEVNAME(sc), pg.coalescing_timeout, pg.pci_slot_num);
   3323   1.1    bouyer 
   3324   1.1    bouyer 	if (!ISSET(le32toh(pg.flags), MPII_CFG_IOC_1_REPLY_COALESCING))
   3325   1.1    bouyer 		return (0);
   3326   1.1    bouyer 
   3327   1.1    bouyer 	CLR(pg.flags, htole32(MPII_CFG_IOC_1_REPLY_COALESCING));
   3328   1.1    bouyer 	if (mpii_cfg_page(sc, 0, &hdr, 0, &pg, sizeof(pg)) != 0) {
   3329   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: unable to clear coalescing\n",
   3330   1.1    bouyer 		    DEVNAME(sc));
   3331   1.1    bouyer 		return (1);
   3332   1.1    bouyer 	}
   3333   1.1    bouyer 
   3334   1.1    bouyer 	return (0);
   3335   1.1    bouyer }
   3336   1.1    bouyer 
   3337   1.1    bouyer #define MPII_EVENT_MASKALL(enq)		do {			\
   3338   1.1    bouyer 		enq->event_masks[0] = 0xffffffff;		\
   3339   1.1    bouyer 		enq->event_masks[1] = 0xffffffff;		\
   3340   1.1    bouyer 		enq->event_masks[2] = 0xffffffff;		\
   3341   1.1    bouyer 		enq->event_masks[3] = 0xffffffff;		\
   3342   1.1    bouyer 	} while (0)
   3343   1.1    bouyer 
   3344   1.1    bouyer #define MPII_EVENT_UNMASK(enq, evt)	do {			\
   3345   1.1    bouyer 		enq->event_masks[evt / 32] &=			\
   3346   1.1    bouyer 		    htole32(~(1 << (evt % 32)));		\
   3347   1.1    bouyer 	} while (0)
   3348   1.1    bouyer 
   3349   1.1    bouyer static int
   3350   1.1    bouyer mpii_eventnotify(struct mpii_softc *sc)
   3351   1.1    bouyer {
   3352   1.1    bouyer 	struct mpii_msg_event_request		*enq;
   3353   1.1    bouyer 	struct mpii_ccb				*ccb;
   3354   1.1    bouyer 
   3355   1.1    bouyer 	ccb = mpii_get_ccb(sc, 0);
   3356   1.1    bouyer 	if (ccb == NULL) {
   3357   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_eventnotify ccb_get\n",
   3358   1.1    bouyer 		    DEVNAME(sc));
   3359   1.1    bouyer 		return (1);
   3360   1.1    bouyer 	}
   3361   1.1    bouyer 
   3362   1.1    bouyer 	ccb->ccb_done = mpii_eventnotify_done;
   3363   1.1    bouyer 	enq = ccb->ccb_cmd;
   3364   1.1    bouyer 
   3365   1.1    bouyer 	enq->function = MPII_FUNCTION_EVENT_NOTIFICATION;
   3366   1.1    bouyer 
   3367   1.1    bouyer 	/*
   3368   1.1    bouyer 	 * Enable reporting of the following events:
   3369   1.1    bouyer 	 *
   3370   1.1    bouyer 	 * MPII_EVENT_SAS_DISCOVERY
   3371   1.1    bouyer 	 * MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST
   3372   1.1    bouyer 	 * MPII_EVENT_SAS_DEVICE_STATUS_CHANGE
   3373   1.1    bouyer 	 * MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE
   3374   1.1    bouyer 	 * MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST
   3375   1.1    bouyer 	 * MPII_EVENT_IR_VOLUME
   3376   1.1    bouyer 	 * MPII_EVENT_IR_PHYSICAL_DISK
   3377   1.1    bouyer 	 * MPII_EVENT_IR_OPERATION_STATUS
   3378   1.1    bouyer 	 */
   3379   1.1    bouyer 
   3380   1.1    bouyer 	MPII_EVENT_MASKALL(enq);
   3381   1.1    bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_DISCOVERY);
   3382   1.1    bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
   3383   1.1    bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_DEVICE_STATUS_CHANGE);
   3384   1.1    bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE);
   3385   1.1    bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST);
   3386   1.1    bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_VOLUME);
   3387   1.1    bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_PHYSICAL_DISK);
   3388   1.1    bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_OPERATION_STATUS);
   3389   1.1    bouyer 
   3390   1.1    bouyer 	mpii_start(sc, ccb);
   3391   1.1    bouyer 
   3392   1.1    bouyer 	return (0);
   3393   1.1    bouyer }
   3394   1.1    bouyer 
   3395   1.1    bouyer static void
   3396   1.1    bouyer mpii_eventnotify_done(struct mpii_ccb *ccb)
   3397   1.1    bouyer {
   3398   1.1    bouyer 	struct mpii_softc			*sc = ccb->ccb_sc;
   3399   1.1    bouyer 	struct mpii_rcb				*rcb = ccb->ccb_rcb;
   3400   1.1    bouyer 
   3401   1.1    bouyer 	DNPRINTF(MPII_D_EVT, "%s: mpii_eventnotify_done\n", DEVNAME(sc));
   3402   1.1    bouyer 
   3403   1.1    bouyer 	mpii_put_ccb(sc, ccb);
   3404   1.1    bouyer 	mpii_event_process(sc, rcb);
   3405   1.1    bouyer }
   3406   1.1    bouyer 
   3407   1.1    bouyer static void
   3408   1.1    bouyer mpii_event_raid(struct mpii_softc *sc, struct mpii_msg_event_reply *enp)
   3409   1.1    bouyer {
   3410   1.1    bouyer 	struct mpii_evt_ir_cfg_change_list	*ccl;
   3411   1.1    bouyer 	struct mpii_evt_ir_cfg_element		*ce;
   3412   1.1    bouyer 	struct mpii_device			*dev;
   3413   1.1    bouyer 	u_int16_t				type;
   3414   1.1    bouyer 	int					i;
   3415   1.1    bouyer 
   3416   1.1    bouyer 	ccl = (struct mpii_evt_ir_cfg_change_list *)(enp + 1);
   3417   1.1    bouyer 
   3418   1.1    bouyer 	if (ccl->num_elements == 0)
   3419   1.1    bouyer 		return;
   3420   1.1    bouyer 	if (ISSET(le32toh(ccl->flags), MPII_EVT_IR_CFG_CHANGE_LIST_FOREIGN))
   3421   1.1    bouyer 		/* bail on foreign configurations */
   3422   1.1    bouyer 		return;
   3423   1.1    bouyer 
   3424   1.1    bouyer 	ce = (struct mpii_evt_ir_cfg_element *)(ccl + 1);
   3425   1.1    bouyer 
   3426   1.1    bouyer 	for (i = 0; i < ccl->num_elements; i++, ce++) {
   3427   1.1    bouyer 		type = (le16toh(ce->element_flags) &
   3428   1.1    bouyer 		    MPII_EVT_IR_CFG_ELEMENT_TYPE_MASK);
   3429   1.1    bouyer 
   3430   1.1    bouyer 		switch (type) {
   3431   1.1    bouyer 		case MPII_EVT_IR_CFG_ELEMENT_TYPE_VOLUME:
   3432   1.1    bouyer 			switch (ce->reason_code) {
   3433   1.1    bouyer 			case MPII_EVT_IR_CFG_ELEMENT_RC_ADDED:
   3434   1.1    bouyer 			case MPII_EVT_IR_CFG_ELEMENT_RC_VOLUME_CREATED:
   3435   1.1    bouyer 				if (mpii_find_dev(sc,
   3436   1.1    bouyer 				    le16toh(ce->vol_dev_handle))) {
   3437   1.9  christos 					aprint_error_dev(sc->sc_dev,
   3438   1.9  christos 					    "device %#x is already "
   3439   1.9  christos 					    "configured\n",
   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.9  christos 					aprint_error_dev(sc->sc_dev,
   3447   1.9  christos 					    "can't allocate device structure\n");
   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.9  christos 					aprint_error_dev(sc->sc_dev,
   3455   1.9  christos 					    "can't insert device structure\n");
   3456   1.9  christos 					free(dev, M_DEVBUF);
   3457   1.9  christos 					break;
   3458   1.9  christos 				}
   3459   1.9  christos 				if (mpii_cache_enable(sc, dev)) {
   3460   1.9  christos 					aprint_error_dev(sc->sc_dev,
   3461   1.9  christos 					    "can't enable device cache\n");
   3462   1.1    bouyer 					free(dev, M_DEVBUF);
   3463   1.1    bouyer 					break;
   3464   1.1    bouyer 				}
   3465   1.1    bouyer 				sc->sc_vd_count++;
   3466   1.1    bouyer 				break;
   3467   1.1    bouyer 			case MPII_EVT_IR_CFG_ELEMENT_RC_REMOVED:
   3468   1.1    bouyer 			case MPII_EVT_IR_CFG_ELEMENT_RC_VOLUME_DELETED:
   3469   1.1    bouyer 				if (!(dev = mpii_find_dev(sc,
   3470   1.1    bouyer 				    le16toh(ce->vol_dev_handle))))
   3471   1.1    bouyer 					break;
   3472   1.1    bouyer 				mpii_remove_dev(sc, dev);
   3473   1.1    bouyer 				sc->sc_vd_count--;
   3474   1.1    bouyer 				break;
   3475   1.1    bouyer 			}
   3476   1.1    bouyer 			break;
   3477   1.1    bouyer 		case MPII_EVT_IR_CFG_ELEMENT_TYPE_VOLUME_DISK:
   3478   1.1    bouyer 			if (ce->reason_code ==
   3479   1.1    bouyer 			    MPII_EVT_IR_CFG_ELEMENT_RC_PD_CREATED ||
   3480   1.1    bouyer 			    ce->reason_code ==
   3481   1.1    bouyer 			    MPII_EVT_IR_CFG_ELEMENT_RC_HIDE) {
   3482   1.1    bouyer 				/* there should be an underlying sas drive */
   3483   1.1    bouyer 				if (!(dev = mpii_find_dev(sc,
   3484   1.1    bouyer 				    le16toh(ce->phys_disk_dev_handle))))
   3485   1.1    bouyer 					break;
   3486   1.1    bouyer 				/* promoted from a hot spare? */
   3487   1.1    bouyer 				CLR(dev->flags, MPII_DF_HOT_SPARE);
   3488   1.1    bouyer 				SET(dev->flags, MPII_DF_VOLUME_DISK |
   3489   1.1    bouyer 				    MPII_DF_HIDDEN);
   3490   1.1    bouyer 			}
   3491   1.1    bouyer 			break;
   3492   1.1    bouyer 		case MPII_EVT_IR_CFG_ELEMENT_TYPE_HOT_SPARE:
   3493   1.1    bouyer 			if (ce->reason_code ==
   3494   1.1    bouyer 			    MPII_EVT_IR_CFG_ELEMENT_RC_HIDE) {
   3495   1.1    bouyer 				/* there should be an underlying sas drive */
   3496   1.1    bouyer 				if (!(dev = mpii_find_dev(sc,
   3497   1.1    bouyer 				    le16toh(ce->phys_disk_dev_handle))))
   3498   1.1    bouyer 					break;
   3499   1.1    bouyer 				SET(dev->flags, MPII_DF_HOT_SPARE |
   3500   1.1    bouyer 				    MPII_DF_HIDDEN);
   3501   1.1    bouyer 			}
   3502   1.1    bouyer 			break;
   3503   1.1    bouyer 		}
   3504   1.1    bouyer 	}
   3505   1.1    bouyer }
   3506   1.1    bouyer 
   3507   1.1    bouyer static void
   3508   1.1    bouyer mpii_event_sas(struct mpii_softc *sc, struct mpii_msg_event_reply *enp)
   3509   1.1    bouyer {
   3510   1.1    bouyer 	struct mpii_evt_sas_tcl		*tcl;
   3511   1.1    bouyer 	struct mpii_evt_phy_entry	*pe;
   3512   1.1    bouyer 	struct mpii_device		*dev;
   3513   1.1    bouyer 	int				i;
   3514   1.1    bouyer 
   3515   1.1    bouyer 	tcl = (struct mpii_evt_sas_tcl *)(enp + 1);
   3516   1.1    bouyer 
   3517   1.1    bouyer 	if (tcl->num_entries == 0)
   3518   1.1    bouyer 		return;
   3519   1.1    bouyer 
   3520   1.1    bouyer 	pe = (struct mpii_evt_phy_entry *)(tcl + 1);
   3521   1.1    bouyer 
   3522   1.1    bouyer 	for (i = 0; i < tcl->num_entries; i++, pe++) {
   3523   1.1    bouyer 		switch (pe->phy_status & MPII_EVENT_SAS_TOPO_PS_RC_MASK) {
   3524   1.1    bouyer 		case MPII_EVENT_SAS_TOPO_PS_RC_ADDED:
   3525   1.1    bouyer 			if (mpii_find_dev(sc, le16toh(pe->dev_handle))) {
   3526   1.9  christos 				aprint_error_dev(sc->sc_dev,
   3527   1.9  christos 				    "device %#x is already configured\n",
   3528   1.1    bouyer 				    le16toh(pe->dev_handle));
   3529   1.1    bouyer 				break;
   3530   1.1    bouyer 			}
   3531   1.1    bouyer 			dev = malloc(sizeof(*dev), M_DEVBUF, M_NOWAIT | M_ZERO);
   3532   1.1    bouyer 			if (!dev) {
   3533   1.9  christos 				aprint_error_dev(sc->sc_dev, "can't allocate "
   3534   1.9  christos 				    "device structure\n");
   3535   1.1    bouyer 				break;
   3536   1.1    bouyer 			}
   3537   1.1    bouyer 			dev->slot = sc->sc_pd_id_start + tcl->start_phy_num + i;
   3538   1.1    bouyer 			dev->dev_handle = le16toh(pe->dev_handle);
   3539   1.1    bouyer 			dev->phy_num = tcl->start_phy_num + i;
   3540   1.1    bouyer 			if (tcl->enclosure_handle)
   3541   1.1    bouyer 				dev->physical_port = tcl->physical_port;
   3542   1.1    bouyer 			dev->enclosure = le16toh(tcl->enclosure_handle);
   3543   1.1    bouyer 			dev->expander = le16toh(tcl->expander_handle);
   3544   1.1    bouyer 			if (mpii_insert_dev(sc, dev)) {
   3545   1.9  christos 				aprint_error_dev(sc->sc_dev, "can't insert "
   3546   1.9  christos 				    "device structure\n");
   3547   1.1    bouyer 				free(dev, M_DEVBUF);
   3548   1.1    bouyer 				break;
   3549   1.1    bouyer 			}
   3550   1.1    bouyer 			break;
   3551   1.1    bouyer 		case MPII_EVENT_SAS_TOPO_PS_RC_MISSING:
   3552   1.1    bouyer 			if (!(dev = mpii_find_dev(sc,
   3553   1.1    bouyer 			    le16toh(pe->dev_handle))))
   3554   1.1    bouyer 				break;
   3555   1.1    bouyer 			mpii_remove_dev(sc, dev);
   3556   1.1    bouyer #if 0
   3557   1.1    bouyer 			if (sc->sc_scsibus) {
   3558   1.1    bouyer 				SET(dev->flags, MPII_DF_DETACH);
   3559   1.1    bouyer 				scsi_activate(sc->sc_scsibus, dev->slot, -1,
   3560   1.1    bouyer 				    DVACT_DEACTIVATE);
   3561   1.1    bouyer 				if (scsi_task(mpii_event_defer, sc,
   3562   1.1    bouyer 				    dev, 0) != 0)
   3563   1.9  christos 					aprint_error_dev(sc->sc_dev,
   3564   1.9  christos 					    "unable to run device "
   3565   1.9  christos 					    "detachment routine\n");
   3566   1.1    bouyer 			}
   3567   1.1    bouyer #else
   3568   1.1    bouyer 			mpii_event_defer(sc, dev);
   3569   1.1    bouyer #endif /* XXX */
   3570   1.1    bouyer 			break;
   3571   1.1    bouyer 		}
   3572   1.1    bouyer 	}
   3573   1.1    bouyer }
   3574   1.1    bouyer 
   3575   1.1    bouyer static void
   3576   1.1    bouyer mpii_event_process(struct mpii_softc *sc, struct mpii_rcb *rcb)
   3577   1.1    bouyer {
   3578   1.1    bouyer 	struct mpii_msg_event_reply		*enp;
   3579   1.1    bouyer 
   3580   1.1    bouyer 	enp = (struct mpii_msg_event_reply *)rcb->rcb_reply;
   3581   1.1    bouyer 
   3582   1.1    bouyer 	DNPRINTF(MPII_D_EVT, "%s: mpii_event_process: %#x\n", DEVNAME(sc),
   3583   1.1    bouyer 	    le32toh(enp->event));
   3584   1.1    bouyer 
   3585   1.1    bouyer 	switch (le32toh(enp->event)) {
   3586   1.1    bouyer 	case MPII_EVENT_EVENT_CHANGE:
   3587   1.1    bouyer 		/* should be properly ignored */
   3588   1.1    bouyer 		break;
   3589   1.1    bouyer 	case MPII_EVENT_SAS_DISCOVERY: {
   3590   1.1    bouyer 		struct mpii_evt_sas_discovery	*esd =
   3591   1.1    bouyer 		    (struct mpii_evt_sas_discovery *)(enp + 1);
   3592   1.1    bouyer 
   3593   1.1    bouyer 		if (esd->reason_code ==
   3594   1.1    bouyer 		    MPII_EVENT_SAS_DISC_REASON_CODE_COMPLETED &&
   3595   1.1    bouyer 		    esd->discovery_status != 0)
   3596   1.1    bouyer 			printf("%s: sas discovery completed with status %#x\n",
   3597   1.1    bouyer 			    DEVNAME(sc), esd->discovery_status);
   3598   1.1    bouyer 		}
   3599   1.1    bouyer 		break;
   3600   1.1    bouyer 	case MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
   3601   1.1    bouyer 		mpii_event_sas(sc, enp);
   3602   1.1    bouyer 		break;
   3603   1.1    bouyer 	case MPII_EVENT_SAS_DEVICE_STATUS_CHANGE:
   3604   1.1    bouyer 		break;
   3605   1.1    bouyer 	case MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
   3606   1.1    bouyer 		break;
   3607   1.1    bouyer 	case MPII_EVENT_IR_VOLUME: {
   3608   1.1    bouyer 		struct mpii_evt_ir_volume	*evd =
   3609   1.1    bouyer 		    (struct mpii_evt_ir_volume *)(enp + 1);
   3610   1.1    bouyer 		struct mpii_device		*dev;
   3611   1.1    bouyer #if NBIO > 0
   3612   1.1    bouyer 		const char *vol_states[] = {
   3613   1.1    bouyer 			BIOC_SVINVALID_S,
   3614   1.1    bouyer 			BIOC_SVOFFLINE_S,
   3615   1.1    bouyer 			BIOC_SVBUILDING_S,
   3616   1.1    bouyer 			BIOC_SVONLINE_S,
   3617   1.1    bouyer 			BIOC_SVDEGRADED_S,
   3618   1.1    bouyer 			BIOC_SVONLINE_S,
   3619   1.1    bouyer 		};
   3620   1.1    bouyer #endif
   3621   1.1    bouyer 
   3622   1.1    bouyer 		if (cold)
   3623   1.1    bouyer 			break;
   3624   1.1    bouyer 		if (!(dev = mpii_find_dev(sc, le16toh(evd->vol_dev_handle))))
   3625   1.1    bouyer 			break;
   3626   1.1    bouyer #if NBIO > 0
   3627   1.1    bouyer 		if (evd->reason_code == MPII_EVENT_IR_VOL_RC_STATE_CHANGED)
   3628   1.1    bouyer 			printf("%s: volume %d state changed from %s to %s\n",
   3629   1.1    bouyer 			    DEVNAME(sc), dev->slot - sc->sc_vd_id_low,
   3630   1.1    bouyer 			    vol_states[evd->prev_value],
   3631   1.1    bouyer 			    vol_states[evd->new_value]);
   3632   1.1    bouyer #endif
   3633   1.1    bouyer 		if (evd->reason_code == MPII_EVENT_IR_VOL_RC_STATUS_CHANGED &&
   3634   1.1    bouyer 		    ISSET(evd->new_value, MPII_CFG_RAID_VOL_0_STATUS_RESYNC) &&
   3635   1.1    bouyer 		    !ISSET(evd->prev_value, MPII_CFG_RAID_VOL_0_STATUS_RESYNC))
   3636   1.1    bouyer 			printf("%s: started resync on a volume %d\n",
   3637   1.1    bouyer 			    DEVNAME(sc), dev->slot - sc->sc_vd_id_low);
   3638   1.1    bouyer 		}
   3639   1.1    bouyer 		break;
   3640   1.1    bouyer 	case MPII_EVENT_IR_PHYSICAL_DISK:
   3641   1.1    bouyer 		break;
   3642   1.1    bouyer 	case MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST:
   3643   1.1    bouyer 		mpii_event_raid(sc, enp);
   3644   1.1    bouyer 		break;
   3645   1.1    bouyer 	case MPII_EVENT_IR_OPERATION_STATUS: {
   3646   1.1    bouyer 		struct mpii_evt_ir_status	*evs =
   3647   1.1    bouyer 		    (struct mpii_evt_ir_status *)(enp + 1);
   3648   1.1    bouyer 		struct mpii_device		*dev;
   3649   1.1    bouyer 
   3650   1.1    bouyer 		if (!(dev = mpii_find_dev(sc, le16toh(evs->vol_dev_handle))))
   3651   1.1    bouyer 			break;
   3652   1.1    bouyer 		if (evs->operation == MPII_EVENT_IR_RAIDOP_RESYNC)
   3653   1.1    bouyer 			dev->percent = evs->percent;
   3654   1.1    bouyer 		break;
   3655   1.1    bouyer 		}
   3656   1.1    bouyer 	default:
   3657   1.1    bouyer 		DNPRINTF(MPII_D_EVT, "%s:  unhandled event 0x%02x\n",
   3658   1.1    bouyer 		    DEVNAME(sc), le32toh(enp->event));
   3659   1.1    bouyer 	}
   3660   1.1    bouyer 
   3661   1.1    bouyer 	if (enp->ack_required)
   3662   1.1    bouyer 		workqueue_enqueue(sc->sc_ssb_evt_ackwk, &rcb->u.rcb_wk, NULL);
   3663   1.1    bouyer 	else
   3664   1.1    bouyer 		mpii_push_reply(sc, rcb);
   3665   1.1    bouyer }
   3666   1.1    bouyer 
   3667   1.1    bouyer static void
   3668   1.1    bouyer mpii_event_defer(void *xsc, void *arg)
   3669   1.1    bouyer {
   3670   1.1    bouyer 	struct mpii_softc	*sc = xsc;
   3671   1.1    bouyer 	struct mpii_device	*dev = arg;
   3672   1.1    bouyer 
   3673   1.1    bouyer 	if (ISSET(dev->flags, MPII_DF_DETACH)) {
   3674   1.1    bouyer 		mpii_sas_remove_device(sc, dev->dev_handle);
   3675   1.1    bouyer #if 0
   3676   1.1    bouyer 		if (!ISSET(dev->flags, MPII_DF_HIDDEN)) {
   3677   1.1    bouyer 			scsi_detach_target(sc->sc_scsibus, dev->slot,
   3678   1.1    bouyer 			    DETACH_FORCE);
   3679   1.1    bouyer 		}
   3680   1.1    bouyer #endif /* XXX */
   3681   1.1    bouyer 		free(dev, M_DEVBUF);
   3682   1.1    bouyer 
   3683   1.1    bouyer 	} else if (ISSET(dev->flags, MPII_DF_ATTACH)) {
   3684   1.1    bouyer 		CLR(dev->flags, MPII_DF_ATTACH);
   3685   1.1    bouyer #if 0
   3686   1.1    bouyer 		if (!ISSET(dev->flags, MPII_DF_HIDDEN))
   3687   1.1    bouyer 			scsi_probe_target(sc->sc_scsibus, dev->slot);
   3688   1.1    bouyer #endif /* XXX */
   3689   1.1    bouyer 	}
   3690   1.1    bouyer }
   3691   1.1    bouyer 
   3692   1.1    bouyer static void
   3693   1.1    bouyer mpii_sas_remove_device(struct mpii_softc *sc, u_int16_t handle)
   3694   1.1    bouyer {
   3695   1.1    bouyer  	struct mpii_msg_scsi_task_request	*stq;
   3696   1.1    bouyer 	struct mpii_msg_sas_oper_request	*soq;
   3697   1.1    bouyer 	struct mpii_ccb				*ccb;
   3698   1.1    bouyer 
   3699   1.1    bouyer 	ccb = mpii_get_ccb(sc, 0);
   3700   1.1    bouyer 	if (ccb == NULL)
   3701   1.1    bouyer 		return;
   3702   1.1    bouyer 
   3703   1.1    bouyer 	stq = ccb->ccb_cmd;
   3704   1.1    bouyer 	stq->function = MPII_FUNCTION_SCSI_TASK_MGMT;
   3705   1.1    bouyer 	stq->task_type = MPII_SCSI_TASK_TARGET_RESET;
   3706   1.1    bouyer 	stq->dev_handle = htole16(handle);
   3707   1.1    bouyer 
   3708   1.1    bouyer 	ccb->ccb_done = mpii_empty_done;
   3709   1.1    bouyer 	mpii_wait(sc, ccb);
   3710   1.1    bouyer 
   3711   1.1    bouyer 	if (ccb->ccb_rcb != NULL)
   3712   1.1    bouyer 		mpii_push_reply(sc, ccb->ccb_rcb);
   3713   1.1    bouyer 
   3714   1.1    bouyer 	/* reuse a ccb */
   3715   1.1    bouyer 	ccb->ccb_state = MPII_CCB_READY;
   3716   1.1    bouyer 	ccb->ccb_rcb = NULL;
   3717   1.1    bouyer 
   3718   1.1    bouyer 	soq = ccb->ccb_cmd;
   3719   1.1    bouyer 	bzero(soq, sizeof(*soq));
   3720   1.1    bouyer 	soq->function = MPII_FUNCTION_SAS_IO_UNIT_CONTROL;
   3721   1.1    bouyer 	soq->operation = MPII_SAS_OP_REMOVE_DEVICE;
   3722   1.1    bouyer 	soq->dev_handle = htole16(handle);
   3723   1.1    bouyer 
   3724   1.1    bouyer 	ccb->ccb_done = mpii_empty_done;
   3725   1.1    bouyer 	mpii_wait(sc, ccb);
   3726   1.1    bouyer 	if (ccb->ccb_rcb != NULL)
   3727   1.1    bouyer 		mpii_push_reply(sc, ccb->ccb_rcb);
   3728   1.1    bouyer }
   3729   1.1    bouyer 
   3730   1.1    bouyer static int
   3731   1.1    bouyer mpii_get_ioc_pg8(struct mpii_softc *sc)
   3732   1.1    bouyer {
   3733   1.1    bouyer 	struct mpii_cfg_hdr	hdr;
   3734   1.1    bouyer 	struct mpii_cfg_ioc_pg8	*page;
   3735   1.1    bouyer 	size_t			pagelen;
   3736   1.1    bouyer 	u_int16_t		flags;
   3737   1.1    bouyer 	int			pad = 0, rv = 0;
   3738   1.1    bouyer 
   3739   1.1    bouyer 	DNPRINTF(MPII_D_RAID, "%s: mpii_get_ioc_pg8\n", DEVNAME(sc));
   3740   1.1    bouyer 
   3741   1.1    bouyer 	if (mpii_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_IOC, 8, 0,
   3742   1.1    bouyer 	    &hdr) != 0) {
   3743   1.1    bouyer 		DNPRINTF(MPII_D_CFG, "%s: mpii_get_ioc_pg8 unable to fetch "
   3744   1.1    bouyer 		    "header for IOC page 8\n", DEVNAME(sc));
   3745   1.1    bouyer 		return (1);
   3746   1.1    bouyer 	}
   3747   1.1    bouyer 
   3748   1.1    bouyer 	pagelen = hdr.page_length * 4; /* dwords to bytes */
   3749   1.1    bouyer 
   3750   1.1    bouyer 	page = malloc(pagelen, M_TEMP, M_NOWAIT);
   3751   1.1    bouyer 	if (page == NULL) {
   3752   1.1    bouyer 		DNPRINTF(MPII_D_CFG, "%s: mpii_get_ioc_pg8 unable to allocate "
   3753   1.1    bouyer 		    "space for ioc config page 8\n", DEVNAME(sc));
   3754   1.1    bouyer 		return (1);
   3755   1.1    bouyer 	}
   3756   1.1    bouyer 
   3757   1.1    bouyer 	if (mpii_cfg_page(sc, 0, &hdr, 1, page, pagelen) != 0) {
   3758   1.1    bouyer 		DNPRINTF(MPII_D_CFG, "%s: mpii_get_raid unable to fetch IOC "
   3759   1.1    bouyer 		    "page 8\n", DEVNAME(sc));
   3760   1.1    bouyer 		rv = 1;
   3761   1.1    bouyer 		goto out;
   3762   1.1    bouyer 	}
   3763   1.1    bouyer 
   3764   1.1    bouyer 	DNPRINTF(MPII_D_CFG, "%s:  numdevsperenclosure: 0x%02x\n", DEVNAME(sc),
   3765   1.1    bouyer 	    page->num_devs_per_enclosure);
   3766   1.1    bouyer 	DNPRINTF(MPII_D_CFG, "%s:  maxpersistententries: 0x%04x "
   3767   1.1    bouyer 	    "maxnumphysicalmappedids: 0x%04x\n", DEVNAME(sc),
   3768   1.1    bouyer 	    le16toh(page->max_persistent_entries),
   3769   1.1    bouyer 	    le16toh(page->max_num_physical_mapped_ids));
   3770   1.1    bouyer 	DNPRINTF(MPII_D_CFG, "%s:  flags: 0x%04x\n", DEVNAME(sc),
   3771   1.1    bouyer 	    le16toh(page->flags));
   3772   1.1    bouyer 	DNPRINTF(MPII_D_CFG, "%s:  irvolumemappingflags: 0x%04x\n",
   3773   1.1    bouyer 	    DEVNAME(sc), le16toh(page->ir_volume_mapping_flags));
   3774   1.1    bouyer 
   3775   1.1    bouyer 	if (page->flags & MPII_IOC_PG8_FLAGS_RESERVED_TARGETID_0)
   3776   1.1    bouyer 		pad = 1;
   3777   1.1    bouyer 
   3778   1.1    bouyer 	flags = page->ir_volume_mapping_flags &
   3779   1.1    bouyer 	    MPII_IOC_PG8_IRFLAGS_VOLUME_MAPPING_MODE_MASK;
   3780   1.1    bouyer 	if (ISSET(sc->sc_flags, MPII_F_RAID)) {
   3781   1.1    bouyer 		if (flags == MPII_IOC_PG8_IRFLAGS_LOW_VOLUME_MAPPING) {
   3782   1.1    bouyer 			sc->sc_vd_id_low += pad;
   3783   1.1    bouyer 			pad = sc->sc_max_volumes; /* for sc_pd_id_start */
   3784   1.1    bouyer 		} else
   3785   1.1    bouyer 			sc->sc_vd_id_low = sc->sc_max_devices -
   3786   1.1    bouyer 			    sc->sc_max_volumes;
   3787   1.1    bouyer 	}
   3788   1.1    bouyer 
   3789   1.1    bouyer 	sc->sc_pd_id_start += pad;
   3790   1.1    bouyer 
   3791   1.1    bouyer 	DNPRINTF(MPII_D_MAP, "%s: mpii_get_ioc_pg8 mapping: sc_pd_id_start: %d "
   3792   1.1    bouyer 	    "sc_vd_id_low: %d sc_max_volumes: %d\n", DEVNAME(sc),
   3793   1.1    bouyer 	    sc->sc_pd_id_start, sc->sc_vd_id_low, sc->sc_max_volumes);
   3794   1.1    bouyer 
   3795   1.1    bouyer out:
   3796   1.1    bouyer 	free(page, M_TEMP);
   3797   1.1    bouyer 
   3798   1.1    bouyer 	return(rv);
   3799   1.1    bouyer }
   3800   1.1    bouyer 
   3801   1.1    bouyer static int
   3802   1.1    bouyer mpii_req_cfg_header(struct mpii_softc *sc, u_int8_t type, u_int8_t number,
   3803   1.1    bouyer     u_int32_t address, int flags, void *p)
   3804   1.1    bouyer {
   3805   1.1    bouyer 	struct mpii_msg_config_request		*cq;
   3806   1.1    bouyer 	struct mpii_msg_config_reply		*cp;
   3807   1.1    bouyer 	struct mpii_cfg_hdr	*hdr = p;
   3808   1.1    bouyer 	struct mpii_ccb		*ccb;
   3809   1.1    bouyer 	struct mpii_ecfg_hdr	*ehdr = p;
   3810   1.1    bouyer 	int			etype = 0;
   3811   1.1    bouyer 	int			rv = 0;
   3812   1.1    bouyer 
   3813   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_req_cfg_header type: %#x number: %x "
   3814   1.1    bouyer 	    "address: 0x%08x flags: 0x%x\n", DEVNAME(sc), type, number,
   3815   1.1    bouyer 	    address, flags);
   3816   1.1    bouyer 
   3817   1.1    bouyer 	ccb = mpii_get_ccb(sc, ISSET(flags, MPII_PG_POLL) ? MPII_NOSLEEP : 0);
   3818   1.1    bouyer 	if (ccb == NULL) {
   3819   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header ccb_get\n",
   3820   1.1    bouyer 		    DEVNAME(sc));
   3821   1.1    bouyer 		return (1);
   3822   1.1    bouyer 	}
   3823   1.1    bouyer 
   3824   1.1    bouyer 	if (ISSET(flags, MPII_PG_EXTENDED)) {
   3825   1.1    bouyer 		etype = type;
   3826   1.1    bouyer 		type = MPII_CONFIG_REQ_PAGE_TYPE_EXTENDED;
   3827   1.1    bouyer 	}
   3828   1.1    bouyer 
   3829   1.1    bouyer 	cq = ccb->ccb_cmd;
   3830   1.1    bouyer 
   3831   1.1    bouyer 	cq->function = MPII_FUNCTION_CONFIG;
   3832   1.1    bouyer 
   3833   1.1    bouyer 	cq->action = MPII_CONFIG_REQ_ACTION_PAGE_HEADER;
   3834   1.1    bouyer 
   3835   1.1    bouyer 	cq->config_header.page_number = number;
   3836   1.1    bouyer 	cq->config_header.page_type = type;
   3837   1.1    bouyer 	cq->ext_page_type = etype;
   3838   1.1    bouyer 	cq->page_address = htole32(address);
   3839   1.1    bouyer 	cq->page_buffer.sg_hdr = htole32(MPII_SGE_FL_TYPE_SIMPLE |
   3840   1.1    bouyer 	    MPII_SGE_FL_LAST | MPII_SGE_FL_EOB | MPII_SGE_FL_EOL);
   3841   1.1    bouyer 
   3842   1.1    bouyer 	ccb->ccb_done = mpii_empty_done;
   3843   1.1    bouyer 	if (ISSET(flags, MPII_PG_POLL)) {
   3844   1.1    bouyer 		if (mpii_poll(sc, ccb) != 0) {
   3845   1.1    bouyer 			DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header poll\n",
   3846   1.1    bouyer 			    DEVNAME(sc));
   3847   1.1    bouyer 			return (1);
   3848   1.1    bouyer 		}
   3849   1.1    bouyer 	} else
   3850   1.1    bouyer 		mpii_wait(sc, ccb);
   3851   1.1    bouyer 
   3852   1.1    bouyer 	if (ccb->ccb_rcb == NULL) {
   3853   1.1    bouyer 		mpii_put_ccb(sc, ccb);
   3854   1.1    bouyer 		return (1);
   3855   1.1    bouyer 	}
   3856   1.1    bouyer 	cp = ccb->ccb_rcb->rcb_reply;
   3857   1.1    bouyer 
   3858   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  action: 0x%02x sgl_flags: 0x%02x "
   3859   1.1    bouyer 	    "msg_length: %d function: 0x%02x\n", DEVNAME(sc), cp->action,
   3860   1.1    bouyer 	    cp->sgl_flags, cp->msg_length, cp->function);
   3861   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ext_page_length: %d ext_page_type: 0x%02x "
   3862   1.1    bouyer 	    "msg_flags: 0x%02x\n", DEVNAME(sc),
   3863   1.1    bouyer 	    le16toh(cp->ext_page_length), cp->ext_page_type,
   3864   1.1    bouyer 	    cp->msg_flags);
   3865   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc),
   3866   1.1    bouyer 	    cp->vp_id, cp->vf_id);
   3867   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
   3868   1.1    bouyer 	    le16toh(cp->ioc_status));
   3869   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
   3870   1.1    bouyer 	    le32toh(cp->ioc_loginfo));
   3871   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  page_version: 0x%02x page_length: %d "
   3872   1.1    bouyer 	    "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc),
   3873   1.1    bouyer 	    cp->config_header.page_version,
   3874   1.1    bouyer 	    cp->config_header.page_length,
   3875   1.1    bouyer 	    cp->config_header.page_number,
   3876   1.1    bouyer 	    cp->config_header.page_type);
   3877   1.1    bouyer 
   3878   1.1    bouyer 	if (le16toh(cp->ioc_status) != MPII_IOCSTATUS_SUCCESS)
   3879   1.1    bouyer 		rv = 1;
   3880   1.1    bouyer 	else if (ISSET(flags, MPII_PG_EXTENDED)) {
   3881   1.1    bouyer 		bzero(ehdr, sizeof(*ehdr));
   3882   1.1    bouyer 		ehdr->page_version = cp->config_header.page_version;
   3883   1.1    bouyer 		ehdr->page_number = cp->config_header.page_number;
   3884   1.1    bouyer 		ehdr->page_type = cp->config_header.page_type;
   3885   1.1    bouyer 		ehdr->ext_page_length = cp->ext_page_length;
   3886   1.1    bouyer 		ehdr->ext_page_type = cp->ext_page_type;
   3887   1.1    bouyer 	} else
   3888   1.1    bouyer 		*hdr = cp->config_header;
   3889   1.1    bouyer 
   3890   1.1    bouyer 	mpii_push_reply(sc, ccb->ccb_rcb);
   3891   1.1    bouyer 	mpii_put_ccb(sc, ccb);
   3892   1.1    bouyer 
   3893   1.1    bouyer 	return (rv);
   3894   1.1    bouyer }
   3895   1.1    bouyer 
   3896   1.1    bouyer static int
   3897   1.1    bouyer mpii_req_cfg_page(struct mpii_softc *sc, u_int32_t address, int flags,
   3898   1.1    bouyer     void *p, int read, void *page, size_t len)
   3899   1.1    bouyer {
   3900   1.1    bouyer 	struct mpii_msg_config_request		*cq;
   3901   1.1    bouyer 	struct mpii_msg_config_reply		*cp;
   3902   1.1    bouyer 	struct mpii_cfg_hdr	*hdr = p;
   3903   1.1    bouyer 	struct mpii_ccb		*ccb;
   3904   1.1    bouyer 	struct mpii_ecfg_hdr	*ehdr = p;
   3905   1.1    bouyer 	u_int64_t		dva;
   3906   1.1    bouyer 	char			*kva;
   3907   1.1    bouyer 	int			page_length;
   3908   1.1    bouyer 	int			rv = 0;
   3909   1.1    bouyer 
   3910   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_page address: %d read: %d "
   3911   1.1    bouyer 	    "type: %x\n", DEVNAME(sc), address, read, hdr->page_type);
   3912   1.1    bouyer 
   3913   1.1    bouyer 	page_length = ISSET(flags, MPII_PG_EXTENDED) ?
   3914   1.1    bouyer 	    le16toh(ehdr->ext_page_length) : hdr->page_length;
   3915   1.1    bouyer 
   3916   1.1    bouyer 	if (len > MPII_REQUEST_SIZE - sizeof(struct mpii_msg_config_request) ||
   3917   1.1    bouyer     	    len < page_length * 4)
   3918   1.1    bouyer 		return (1);
   3919   1.1    bouyer 
   3920   1.1    bouyer 	ccb = mpii_get_ccb(sc,
   3921   1.1    bouyer 	    ISSET(flags, MPII_PG_POLL) ? MPII_NOSLEEP : 0);
   3922   1.1    bouyer 	if (ccb == NULL) {
   3923   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_page ccb_get\n",
   3924   1.1    bouyer 		    DEVNAME(sc));
   3925   1.1    bouyer 		return (1);
   3926   1.1    bouyer 	}
   3927   1.1    bouyer 
   3928   1.1    bouyer 	cq = ccb->ccb_cmd;
   3929   1.1    bouyer 
   3930   1.1    bouyer 	cq->function = MPII_FUNCTION_CONFIG;
   3931   1.1    bouyer 
   3932   1.1    bouyer 	cq->action = (read ? MPII_CONFIG_REQ_ACTION_PAGE_READ_CURRENT :
   3933   1.1    bouyer 	    MPII_CONFIG_REQ_ACTION_PAGE_WRITE_CURRENT);
   3934   1.1    bouyer 
   3935   1.1    bouyer 	if (ISSET(flags, MPII_PG_EXTENDED)) {
   3936   1.1    bouyer 		cq->config_header.page_version = ehdr->page_version;
   3937   1.1    bouyer 		cq->config_header.page_number = ehdr->page_number;
   3938   1.1    bouyer 		cq->config_header.page_type = ehdr->page_type;
   3939   1.1    bouyer 		cq->ext_page_len = ehdr->ext_page_length;
   3940   1.1    bouyer 		cq->ext_page_type = ehdr->ext_page_type;
   3941   1.1    bouyer 	} else
   3942   1.1    bouyer 		cq->config_header = *hdr;
   3943   1.1    bouyer 	cq->config_header.page_type &= MPII_CONFIG_REQ_PAGE_TYPE_MASK;
   3944   1.1    bouyer 	cq->page_address = htole32(address);
   3945   1.1    bouyer 	cq->page_buffer.sg_hdr = htole32(MPII_SGE_FL_TYPE_SIMPLE |
   3946   1.1    bouyer 	    MPII_SGE_FL_LAST | MPII_SGE_FL_EOB | MPII_SGE_FL_EOL |
   3947   1.1    bouyer 	    MPII_SGE_FL_SIZE_64 | (page_length * 4) |
   3948   1.1    bouyer 	    (read ? MPII_SGE_FL_DIR_IN : MPII_SGE_FL_DIR_OUT));
   3949   1.1    bouyer 
   3950   1.1    bouyer 	/* bounce the page via the request space to avoid more bus_dma games */
   3951   1.1    bouyer 	dva = ccb->ccb_cmd_dva + sizeof(struct mpii_msg_config_request);
   3952   1.1    bouyer 
   3953   1.1    bouyer 	cq->page_buffer.sg_hi_addr = htole32((u_int32_t)(dva >> 32));
   3954   1.1    bouyer 	cq->page_buffer.sg_lo_addr = htole32((u_int32_t)dva);
   3955   1.1    bouyer 
   3956   1.1    bouyer 	kva = ccb->ccb_cmd;
   3957   1.1    bouyer 	kva += sizeof(struct mpii_msg_config_request);
   3958   1.1    bouyer 
   3959   1.1    bouyer 	if (!read)
   3960   1.1    bouyer 		bcopy(page, kva, len);
   3961   1.1    bouyer 
   3962   1.1    bouyer 	ccb->ccb_done = mpii_empty_done;
   3963   1.1    bouyer 	if (ISSET(flags, MPII_PG_POLL)) {
   3964   1.1    bouyer 		if (mpii_poll(sc, ccb) != 0) {
   3965   1.1    bouyer 			DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header poll\n",
   3966   1.1    bouyer 			    DEVNAME(sc));
   3967   1.1    bouyer 			return (1);
   3968   1.1    bouyer 		}
   3969   1.1    bouyer 	} else
   3970   1.1    bouyer 		mpii_wait(sc, ccb);
   3971   1.1    bouyer 
   3972   1.1    bouyer 	if (ccb->ccb_rcb == NULL) {
   3973   1.1    bouyer 		mpii_put_ccb(sc, ccb);
   3974   1.1    bouyer 		return (1);
   3975   1.1    bouyer 	}
   3976   1.1    bouyer 	cp = ccb->ccb_rcb->rcb_reply;
   3977   1.1    bouyer 
   3978   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  action: 0x%02x "
   3979   1.1    bouyer 	    "msg_length: %d function: 0x%02x\n", DEVNAME(sc), cp->action,
   3980   1.1    bouyer 	    cp->msg_length, cp->function);
   3981   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ext_page_length: %d ext_page_type: 0x%02x "
   3982   1.1    bouyer 	    "msg_flags: 0x%02x\n", DEVNAME(sc),
   3983   1.1    bouyer 	    le16toh(cp->ext_page_length), cp->ext_page_type,
   3984   1.1    bouyer 	    cp->msg_flags);
   3985   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc),
   3986   1.1    bouyer 	    cp->vp_id, cp->vf_id);
   3987   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
   3988   1.1    bouyer 	    le16toh(cp->ioc_status));
   3989   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
   3990   1.1    bouyer 	    le32toh(cp->ioc_loginfo));
   3991   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  page_version: 0x%02x page_length: %d "
   3992   1.1    bouyer 	    "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc),
   3993   1.1    bouyer 	    cp->config_header.page_version,
   3994   1.1    bouyer 	    cp->config_header.page_length,
   3995   1.1    bouyer 	    cp->config_header.page_number,
   3996   1.1    bouyer 	    cp->config_header.page_type);
   3997   1.1    bouyer 
   3998   1.1    bouyer 	if (le16toh(cp->ioc_status) != MPII_IOCSTATUS_SUCCESS)
   3999   1.1    bouyer 		rv = 1;
   4000   1.1    bouyer 	else if (read)
   4001   1.1    bouyer 		bcopy(kva, page, len);
   4002   1.1    bouyer 
   4003   1.1    bouyer 	mpii_push_reply(sc, ccb->ccb_rcb);
   4004   1.1    bouyer 	mpii_put_ccb(sc, ccb);
   4005   1.1    bouyer 
   4006   1.1    bouyer 	return (rv);
   4007   1.1    bouyer }
   4008   1.1    bouyer 
   4009   1.1    bouyer static struct mpii_rcb *
   4010   1.1    bouyer mpii_reply(struct mpii_softc *sc, struct mpii_reply_descr *rdp)
   4011   1.1    bouyer {
   4012   1.1    bouyer 	struct mpii_rcb		*rcb = NULL;
   4013   1.1    bouyer 	u_int32_t		rfid;
   4014   1.1    bouyer 
   4015   1.1    bouyer 	DNPRINTF(MPII_D_INTR, "%s: mpii_reply\n", DEVNAME(sc));
   4016   1.1    bouyer 
   4017   1.1    bouyer 	if ((rdp->reply_flags & MPII_REPLY_DESCR_TYPE_MASK) ==
   4018   1.1    bouyer 	    MPII_REPLY_DESCR_ADDRESS_REPLY) {
   4019   1.1    bouyer 		rfid = (le32toh(rdp->frame_addr) -
   4020   1.1    bouyer 		    (u_int32_t)MPII_DMA_DVA(sc->sc_replies)) / MPII_REPLY_SIZE;
   4021   1.1    bouyer 
   4022   1.1    bouyer 		bus_dmamap_sync(sc->sc_dmat,
   4023   1.1    bouyer 		    MPII_DMA_MAP(sc->sc_replies), MPII_REPLY_SIZE * rfid,
   4024   1.1    bouyer 		    MPII_REPLY_SIZE, BUS_DMASYNC_POSTREAD);
   4025   1.1    bouyer 
   4026   1.1    bouyer 		rcb = &sc->sc_rcbs[rfid];
   4027   1.1    bouyer 	}
   4028   1.1    bouyer 
   4029   1.1    bouyer 	memset(rdp, 0xff, sizeof(*rdp));
   4030   1.1    bouyer 
   4031   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq),
   4032   1.1    bouyer 	    8 * sc->sc_reply_post_host_index, 8,
   4033   1.1    bouyer 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
   4034   1.1    bouyer 
   4035   1.1    bouyer 	return (rcb);
   4036   1.1    bouyer }
   4037   1.1    bouyer 
   4038   1.1    bouyer static struct mpii_dmamem *
   4039   1.1    bouyer mpii_dmamem_alloc(struct mpii_softc *sc, size_t size)
   4040   1.1    bouyer {
   4041   1.1    bouyer 	struct mpii_dmamem	*mdm;
   4042   1.1    bouyer 	int			nsegs;
   4043   1.1    bouyer 
   4044   1.1    bouyer 	mdm = malloc(sizeof(*mdm), M_DEVBUF, M_NOWAIT | M_ZERO);
   4045   1.1    bouyer 	if (mdm == NULL)
   4046  1.11      maya 		return (NULL);
   4047   1.1    bouyer 
   4048   1.1    bouyer 	mdm->mdm_size = size;
   4049   1.1    bouyer 
   4050   1.1    bouyer 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
   4051   1.1    bouyer 	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mdm->mdm_map) != 0)
   4052   1.1    bouyer 		goto mdmfree;
   4053   1.1    bouyer 
   4054   1.1    bouyer 	if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &mdm->mdm_seg,
   4055   1.1    bouyer 	    1, &nsegs, BUS_DMA_NOWAIT) != 0) goto destroy;
   4056   1.1    bouyer 
   4057   1.1    bouyer 	if (bus_dmamem_map(sc->sc_dmat, &mdm->mdm_seg, nsegs, size,
   4058   1.1    bouyer 	    &mdm->mdm_kva, BUS_DMA_NOWAIT) != 0)
   4059   1.1    bouyer 		goto free;
   4060   1.1    bouyer 
   4061   1.1    bouyer 	if (bus_dmamap_load(sc->sc_dmat, mdm->mdm_map, mdm->mdm_kva, size,
   4062   1.1    bouyer 	    NULL, BUS_DMA_NOWAIT) != 0)
   4063   1.1    bouyer 		goto unmap;
   4064   1.1    bouyer 
   4065   1.1    bouyer 	DNPRINTF(MPII_D_MEM,
   4066   1.1    bouyer 	    "  kva: %p  dva: 0x%" PRIx64 "  map: %p  size: %" PRId64 "\n",
   4067   1.1    bouyer 	    mdm->mdm_kva, (uint64_t)mdm->mdm_map->dm_segs[0].ds_addr,
   4068   1.1    bouyer 	    mdm->mdm_map, (uint64_t)size);
   4069   1.1    bouyer 
   4070   1.1    bouyer 	bzero(mdm->mdm_kva, size);
   4071   1.1    bouyer 
   4072   1.1    bouyer 	return (mdm);
   4073   1.1    bouyer 
   4074   1.1    bouyer unmap:
   4075   1.1    bouyer 	bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, size);
   4076   1.1    bouyer free:
   4077   1.1    bouyer 	bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1);
   4078   1.1    bouyer destroy:
   4079   1.1    bouyer 	bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map);
   4080   1.1    bouyer mdmfree:
   4081   1.1    bouyer 	free(mdm, M_DEVBUF);
   4082   1.1    bouyer 
   4083   1.1    bouyer 	return (NULL);
   4084   1.1    bouyer }
   4085   1.1    bouyer 
   4086   1.1    bouyer static void
   4087   1.1    bouyer mpii_dmamem_free(struct mpii_softc *sc, struct mpii_dmamem *mdm)
   4088   1.1    bouyer {
   4089   1.1    bouyer 	DNPRINTF(MPII_D_MEM, "%s: mpii_dmamem_free %p\n", DEVNAME(sc), mdm);
   4090   1.1    bouyer 
   4091   1.1    bouyer 	bus_dmamap_unload(sc->sc_dmat, mdm->mdm_map);
   4092   1.1    bouyer 	bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, mdm->mdm_size);
   4093   1.1    bouyer 	bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1);
   4094   1.1    bouyer 	bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map);
   4095   1.1    bouyer 	free(mdm, M_DEVBUF);
   4096   1.1    bouyer }
   4097   1.1    bouyer 
   4098   1.1    bouyer static int
   4099   1.1    bouyer mpii_alloc_dev(struct mpii_softc *sc)
   4100   1.1    bouyer {
   4101   1.1    bouyer 	sc->sc_devs = malloc(sc->sc_max_devices *
   4102   1.1    bouyer 	    sizeof(struct mpii_device *), M_DEVBUF, M_NOWAIT | M_ZERO);
   4103   1.1    bouyer 	if (sc->sc_devs == NULL)
   4104   1.1    bouyer 		return (1);
   4105   1.1    bouyer 	return (0);
   4106   1.1    bouyer }
   4107   1.1    bouyer 
   4108   1.1    bouyer static int
   4109   1.1    bouyer mpii_insert_dev(struct mpii_softc *sc, struct mpii_device *dev)
   4110   1.1    bouyer {
   4111  1.10      maya 
   4112  1.10      maya 	if (!dev || dev->slot < 0)
   4113  1.10      maya 		return (1);
   4114  1.10      maya 
   4115   1.1    bouyer 	int slot = dev->slot; 	/* initial hint */
   4116   1.1    bouyer 
   4117   1.1    bouyer 	while (slot < sc->sc_max_devices && sc->sc_devs[slot] != NULL)
   4118   1.1    bouyer 		slot++;
   4119   1.1    bouyer 	if (slot >= sc->sc_max_devices)
   4120   1.1    bouyer 		return (1);
   4121   1.1    bouyer 	dev->slot = slot;
   4122   1.1    bouyer 	sc->sc_devs[slot] = dev;
   4123   1.1    bouyer 	return (0);
   4124   1.1    bouyer }
   4125   1.1    bouyer 
   4126   1.1    bouyer static int
   4127   1.1    bouyer mpii_remove_dev(struct mpii_softc *sc, struct mpii_device *dev)
   4128   1.1    bouyer {
   4129   1.1    bouyer 	int			i;
   4130   1.1    bouyer 
   4131   1.1    bouyer 	if (!dev)
   4132   1.1    bouyer 		return (1);
   4133   1.1    bouyer 	for (i = 0; i < sc->sc_max_devices;  i++)
   4134   1.1    bouyer 		if (sc->sc_devs[i] &&
   4135   1.1    bouyer 		    sc->sc_devs[i]->dev_handle == dev->dev_handle) {
   4136   1.1    bouyer 			sc->sc_devs[i] = NULL;
   4137   1.1    bouyer 			return (0);
   4138   1.1    bouyer 		}
   4139   1.1    bouyer 	return (1);
   4140   1.1    bouyer }
   4141   1.1    bouyer 
   4142   1.1    bouyer static struct mpii_device *
   4143   1.1    bouyer mpii_find_dev(struct mpii_softc *sc, u_int16_t handle)
   4144   1.1    bouyer {
   4145   1.1    bouyer 	int			i;
   4146   1.1    bouyer 
   4147   1.1    bouyer 	for (i = 0; i < sc->sc_max_devices;  i++)
   4148   1.1    bouyer 		if (sc->sc_devs[i] && sc->sc_devs[i]->dev_handle == handle)
   4149   1.1    bouyer 			return (sc->sc_devs[i]);
   4150   1.1    bouyer 	return (NULL);
   4151   1.1    bouyer }
   4152   1.1    bouyer 
   4153   1.1    bouyer static int
   4154   1.1    bouyer mpii_alloc_ccbs(struct mpii_softc *sc)
   4155   1.1    bouyer {
   4156   1.1    bouyer 	struct mpii_ccb		*ccb;
   4157   1.1    bouyer 	u_int8_t		*cmd;
   4158   1.1    bouyer 	int			i;
   4159   1.1    bouyer 
   4160   1.1    bouyer 	SIMPLEQ_INIT(&sc->sc_ccb_free);
   4161   1.1    bouyer 
   4162   1.1    bouyer 	sc->sc_ccbs = malloc(sizeof(*ccb) * (sc->sc_request_depth-1),
   4163   1.1    bouyer 	    M_DEVBUF, M_NOWAIT | M_ZERO);
   4164   1.1    bouyer 	if (sc->sc_ccbs == NULL) {
   4165   1.1    bouyer 		printf("%s: unable to allocate ccbs\n", DEVNAME(sc));
   4166   1.1    bouyer 		return (1);
   4167   1.1    bouyer 	}
   4168   1.1    bouyer 
   4169   1.1    bouyer 	sc->sc_requests = mpii_dmamem_alloc(sc,
   4170   1.1    bouyer 	    MPII_REQUEST_SIZE * sc->sc_request_depth);
   4171   1.1    bouyer 	if (sc->sc_requests == NULL) {
   4172   1.1    bouyer 		printf("%s: unable to allocate ccb dmamem\n", DEVNAME(sc));
   4173   1.1    bouyer 		goto free_ccbs;
   4174   1.1    bouyer 	}
   4175   1.1    bouyer 	cmd = MPII_DMA_KVA(sc->sc_requests);
   4176   1.1    bouyer 	bzero(cmd, MPII_REQUEST_SIZE * sc->sc_request_depth);
   4177   1.1    bouyer 
   4178   1.1    bouyer 	/*
   4179   1.1    bouyer 	 * we have sc->sc_request_depth system request message
   4180   1.1    bouyer 	 * frames, but smid zero cannot be used. so we then
   4181   1.1    bouyer 	 * have (sc->sc_request_depth - 1) number of ccbs
   4182   1.1    bouyer 	 */
   4183   1.1    bouyer 	for (i = 1; i < sc->sc_request_depth; i++) {
   4184   1.1    bouyer 		ccb = &sc->sc_ccbs[i - 1];
   4185   1.1    bouyer 
   4186   1.1    bouyer 		if (bus_dmamap_create(sc->sc_dmat, MAXPHYS,
   4187   1.1    bouyer 		    sc->sc_max_sgl_len, MAXPHYS, 0,
   4188   1.1    bouyer 		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
   4189   1.1    bouyer 		    &ccb->ccb_dmamap) != 0) {
   4190   1.1    bouyer 			printf("%s: unable to create dma map\n", DEVNAME(sc));
   4191   1.1    bouyer 			goto free_maps;
   4192   1.1    bouyer 		}
   4193   1.1    bouyer 
   4194   1.1    bouyer 		ccb->ccb_sc = sc;
   4195   1.1    bouyer 		ccb->ccb_smid = i;
   4196   1.1    bouyer 		ccb->ccb_offset = MPII_REQUEST_SIZE * i;
   4197   1.1    bouyer 
   4198   1.1    bouyer 		ccb->ccb_cmd = &cmd[ccb->ccb_offset];
   4199   1.1    bouyer 		ccb->ccb_cmd_dva = (u_int32_t)MPII_DMA_DVA(sc->sc_requests) +
   4200   1.1    bouyer 		    ccb->ccb_offset;
   4201   1.1    bouyer 
   4202   1.1    bouyer 		DNPRINTF(MPII_D_CCB, "%s: mpii_alloc_ccbs(%d) ccb: %p map: %p "
   4203   1.1    bouyer 		    "sc: %p smid: %#x offs: %#" PRIx64 " cmd: %#" PRIx64 " dva: %#" PRIx64 "\n",
   4204   1.1    bouyer 		    DEVNAME(sc), i, ccb, ccb->ccb_dmamap, ccb->ccb_sc,
   4205   1.1    bouyer 		    ccb->ccb_smid, (uint64_t)ccb->ccb_offset,
   4206   1.1    bouyer 		    (uint64_t)ccb->ccb_cmd, (uint64_t)ccb->ccb_cmd_dva);
   4207   1.1    bouyer 
   4208   1.1    bouyer 		mpii_put_ccb(sc, ccb);
   4209   1.1    bouyer 	}
   4210   1.1    bouyer 
   4211   1.1    bouyer 	return (0);
   4212   1.1    bouyer 
   4213   1.1    bouyer free_maps:
   4214   1.1    bouyer 	while ((ccb = mpii_get_ccb(sc, MPII_NOSLEEP)) != NULL)
   4215   1.1    bouyer 		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
   4216   1.1    bouyer 
   4217   1.1    bouyer 	mpii_dmamem_free(sc, sc->sc_requests);
   4218   1.1    bouyer free_ccbs:
   4219   1.1    bouyer 	free(sc->sc_ccbs, M_DEVBUF);
   4220   1.1    bouyer 
   4221   1.1    bouyer 	return (1);
   4222   1.1    bouyer }
   4223   1.1    bouyer 
   4224   1.1    bouyer static void
   4225   1.1    bouyer mpii_put_ccb(struct mpii_softc *sc, struct mpii_ccb *ccb)
   4226   1.1    bouyer {
   4227   1.1    bouyer 	KASSERT(ccb->ccb_sc == sc);
   4228   1.1    bouyer 	DNPRINTF(MPII_D_CCB, "%s: mpii_put_ccb %p\n", DEVNAME(sc), ccb);
   4229   1.1    bouyer 
   4230   1.1    bouyer 	ccb->ccb_state = MPII_CCB_FREE;
   4231   1.1    bouyer 	ccb->ccb_cookie = NULL;
   4232   1.1    bouyer 	ccb->ccb_done = NULL;
   4233   1.1    bouyer 	ccb->ccb_rcb = NULL;
   4234   1.1    bouyer 	bzero(ccb->ccb_cmd, MPII_REQUEST_SIZE);
   4235   1.1    bouyer 
   4236   1.1    bouyer 	mutex_enter(&sc->sc_ccb_free_mtx);
   4237   1.1    bouyer 	SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ccb, u.ccb_link);
   4238   1.1    bouyer 	cv_signal(&sc->sc_ccb_free_cv);
   4239   1.1    bouyer 	mutex_exit(&sc->sc_ccb_free_mtx);
   4240   1.1    bouyer }
   4241   1.1    bouyer 
   4242   1.1    bouyer static struct mpii_ccb *
   4243   1.1    bouyer mpii_get_ccb(struct mpii_softc *sc, int flags)
   4244   1.1    bouyer {
   4245   1.1    bouyer 	struct mpii_ccb		*ccb;
   4246   1.1    bouyer 
   4247   1.1    bouyer 	mutex_enter(&sc->sc_ccb_free_mtx);
   4248   1.1    bouyer 	while ((ccb = SIMPLEQ_FIRST(&sc->sc_ccb_free)) == NULL) {
   4249   1.1    bouyer 		if (flags & MPII_NOSLEEP)
   4250   1.1    bouyer 			break;
   4251   1.1    bouyer 		cv_wait(&sc->sc_ccb_free_cv, &sc->sc_ccb_free_mtx);
   4252   1.1    bouyer 	}
   4253   1.1    bouyer 
   4254   1.1    bouyer 	if (ccb != NULL) {
   4255   1.1    bouyer 		SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, u.ccb_link);
   4256   1.1    bouyer 		ccb->ccb_state = MPII_CCB_READY;
   4257   1.1    bouyer 		KASSERT(ccb->ccb_sc == sc);
   4258   1.1    bouyer 	}
   4259   1.1    bouyer 	mutex_exit(&sc->sc_ccb_free_mtx);
   4260   1.1    bouyer 
   4261   1.1    bouyer 	DNPRINTF(MPII_D_CCB, "%s: mpii_get_ccb %p\n", DEVNAME(sc), ccb);
   4262   1.1    bouyer 
   4263   1.1    bouyer 	return (ccb);
   4264   1.1    bouyer }
   4265   1.1    bouyer 
   4266   1.1    bouyer static int
   4267   1.1    bouyer mpii_alloc_replies(struct mpii_softc *sc)
   4268   1.1    bouyer {
   4269   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_alloc_replies\n", DEVNAME(sc));
   4270   1.1    bouyer 
   4271   1.1    bouyer 	sc->sc_rcbs = malloc(sc->sc_num_reply_frames * sizeof(struct mpii_rcb),
   4272   1.1    bouyer 	    M_DEVBUF, M_NOWAIT);
   4273   1.1    bouyer 	if (sc->sc_rcbs == NULL)
   4274   1.1    bouyer 		return (1);
   4275   1.1    bouyer 
   4276   1.1    bouyer 	sc->sc_replies = mpii_dmamem_alloc(sc, MPII_REPLY_SIZE *
   4277   1.1    bouyer 	    sc->sc_num_reply_frames);
   4278   1.1    bouyer 	if (sc->sc_replies == NULL) {
   4279   1.1    bouyer 		free(sc->sc_rcbs, M_DEVBUF);
   4280   1.1    bouyer 		return (1);
   4281   1.1    bouyer 	}
   4282   1.1    bouyer 
   4283   1.1    bouyer 	return (0);
   4284   1.1    bouyer }
   4285   1.1    bouyer 
   4286   1.1    bouyer static void
   4287   1.1    bouyer mpii_push_replies(struct mpii_softc *sc)
   4288   1.1    bouyer {
   4289   1.1    bouyer 	struct mpii_rcb		*rcb;
   4290   1.1    bouyer 	char			*kva = MPII_DMA_KVA(sc->sc_replies);
   4291   1.1    bouyer 	int			i;
   4292   1.1    bouyer 
   4293   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_replies),
   4294   1.1    bouyer 	    0, MPII_REPLY_SIZE * sc->sc_num_reply_frames, BUS_DMASYNC_PREREAD);
   4295   1.1    bouyer 
   4296   1.1    bouyer 	for (i = 0; i < sc->sc_num_reply_frames; i++) {
   4297   1.1    bouyer 		rcb = &sc->sc_rcbs[i];
   4298   1.1    bouyer 
   4299   1.1    bouyer 		rcb->rcb_reply = kva + MPII_REPLY_SIZE * i;
   4300   1.1    bouyer 		rcb->rcb_reply_dva = (u_int32_t)MPII_DMA_DVA(sc->sc_replies) +
   4301   1.1    bouyer 		    MPII_REPLY_SIZE * i;
   4302   1.1    bouyer 		mpii_push_reply(sc, rcb);
   4303   1.1    bouyer 	}
   4304   1.1    bouyer }
   4305   1.1    bouyer 
   4306   1.1    bouyer static void
   4307   1.1    bouyer mpii_start(struct mpii_softc *sc, struct mpii_ccb *ccb)
   4308   1.1    bouyer {
   4309   1.1    bouyer 	struct mpii_request_header	*rhp;
   4310   1.1    bouyer 	struct mpii_request_descr	descr;
   4311   1.1    bouyer 	u_int32_t			*rdp = (u_int32_t *)&descr;
   4312   1.1    bouyer 
   4313   1.1    bouyer 	DNPRINTF(MPII_D_RW, "%s: mpii_start %#" PRIx64 "\n", DEVNAME(sc),
   4314   1.1    bouyer 	    (uint64_t)ccb->ccb_cmd_dva);
   4315   1.1    bouyer 
   4316   1.1    bouyer 	rhp = ccb->ccb_cmd;
   4317   1.1    bouyer 
   4318   1.1    bouyer 	bzero(&descr, sizeof(descr));
   4319   1.1    bouyer 
   4320   1.1    bouyer 	switch (rhp->function) {
   4321   1.1    bouyer 	case MPII_FUNCTION_SCSI_IO_REQUEST:
   4322   1.1    bouyer 		descr.request_flags = MPII_REQ_DESCR_SCSI_IO;
   4323   1.1    bouyer 		descr.dev_handle = htole16(ccb->ccb_dev_handle);
   4324   1.1    bouyer 		break;
   4325   1.1    bouyer 	case MPII_FUNCTION_SCSI_TASK_MGMT:
   4326   1.1    bouyer 		descr.request_flags = MPII_REQ_DESCR_HIGH_PRIORITY;
   4327   1.1    bouyer 		break;
   4328   1.1    bouyer 	default:
   4329   1.1    bouyer 		descr.request_flags = MPII_REQ_DESCR_DEFAULT;
   4330   1.1    bouyer 	}
   4331   1.1    bouyer 
   4332   1.1    bouyer 	descr.vf_id = sc->sc_vf_id;
   4333   1.1    bouyer 	descr.smid = htole16(ccb->ccb_smid);
   4334   1.1    bouyer 
   4335   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_requests),
   4336   1.1    bouyer 	    ccb->ccb_offset, MPII_REQUEST_SIZE,
   4337   1.1    bouyer 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
   4338   1.1    bouyer 
   4339   1.1    bouyer 	ccb->ccb_state = MPII_CCB_QUEUED;
   4340   1.1    bouyer 
   4341   1.1    bouyer 	DNPRINTF(MPII_D_RW, "%s:   MPII_REQ_DESCR_POST_LOW (0x%08x) write "
   4342   1.1    bouyer 	    "0x%08x\n", DEVNAME(sc), MPII_REQ_DESCR_POST_LOW, *rdp);
   4343   1.1    bouyer 
   4344   1.1    bouyer 	DNPRINTF(MPII_D_RW, "%s:   MPII_REQ_DESCR_POST_HIGH (0x%08x) write "
   4345   1.1    bouyer 	    "0x%08x\n", DEVNAME(sc), MPII_REQ_DESCR_POST_HIGH, *(rdp+1));
   4346   1.1    bouyer 
   4347   1.1    bouyer 	mutex_enter(&sc->sc_req_mtx);
   4348   1.1    bouyer 	mpii_write(sc, MPII_REQ_DESCR_POST_LOW, htole32(*rdp));
   4349   1.1    bouyer 	mpii_write(sc, MPII_REQ_DESCR_POST_HIGH, htole32(*(rdp+1)));
   4350   1.1    bouyer 	mutex_exit(&sc->sc_req_mtx);
   4351   1.1    bouyer }
   4352   1.1    bouyer 
   4353   1.1    bouyer static int
   4354   1.1    bouyer mpii_poll(struct mpii_softc *sc, struct mpii_ccb *ccb)
   4355   1.1    bouyer {
   4356   1.1    bouyer 	void				(*done)(struct mpii_ccb *);
   4357   1.1    bouyer 	void				*cookie;
   4358   1.1    bouyer 	int				rv = 1;
   4359   1.1    bouyer 
   4360   1.1    bouyer 	DNPRINTF(MPII_D_INTR, "%s: mpii_complete\n", DEVNAME(sc));
   4361   1.1    bouyer 
   4362   1.1    bouyer 	done = ccb->ccb_done;
   4363   1.1    bouyer 	cookie = ccb->ccb_cookie;
   4364   1.1    bouyer 
   4365   1.1    bouyer 	ccb->ccb_done = mpii_poll_done;
   4366   1.1    bouyer 	ccb->ccb_cookie = &rv;
   4367   1.1    bouyer 
   4368   1.1    bouyer 	mpii_start(sc, ccb);
   4369   1.1    bouyer 
   4370   1.1    bouyer 	while (rv == 1) {
   4371   1.1    bouyer 		/* avoid excessive polling */
   4372   1.1    bouyer 		if (mpii_reply_waiting(sc))
   4373   1.1    bouyer 			mpii_intr(sc);
   4374   1.1    bouyer 		else
   4375   1.1    bouyer 			delay(10);
   4376   1.1    bouyer 	}
   4377   1.1    bouyer 
   4378   1.1    bouyer 	ccb->ccb_cookie = cookie;
   4379   1.1    bouyer 	done(ccb);
   4380   1.1    bouyer 
   4381   1.1    bouyer 	return (0);
   4382   1.1    bouyer }
   4383   1.1    bouyer 
   4384   1.1    bouyer static void
   4385   1.1    bouyer mpii_poll_done(struct mpii_ccb *ccb)
   4386   1.1    bouyer {
   4387   1.1    bouyer 	int				*rv = ccb->ccb_cookie;
   4388   1.1    bouyer 
   4389   1.1    bouyer 	*rv = 0;
   4390   1.1    bouyer }
   4391   1.1    bouyer 
   4392   1.1    bouyer static int
   4393   1.1    bouyer mpii_alloc_queues(struct mpii_softc *sc)
   4394   1.1    bouyer {
   4395   1.1    bouyer 	u_int32_t		*kva;
   4396   1.1    bouyer 	u_int64_t		*kva64;
   4397   1.1    bouyer 	int			i;
   4398   1.1    bouyer 
   4399   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_alloc_queues\n", DEVNAME(sc));
   4400   1.1    bouyer 
   4401   1.1    bouyer 	sc->sc_reply_freeq = mpii_dmamem_alloc(sc,
   4402   1.1    bouyer 	    sc->sc_reply_free_qdepth * 4);
   4403   1.1    bouyer 	if (sc->sc_reply_freeq == NULL)
   4404   1.1    bouyer 		return (1);
   4405   1.1    bouyer 
   4406   1.1    bouyer 	kva = MPII_DMA_KVA(sc->sc_reply_freeq);
   4407   1.1    bouyer 	for (i = 0; i < sc->sc_num_reply_frames; i++) {
   4408   1.1    bouyer 		kva[i] = (u_int32_t)MPII_DMA_DVA(sc->sc_replies) +
   4409   1.1    bouyer 		    MPII_REPLY_SIZE * i;
   4410   1.1    bouyer 
   4411   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s:   %d:  %p = 0x%08x\n",
   4412   1.1    bouyer 		    DEVNAME(sc), i,
   4413   1.1    bouyer 		    &kva[i], (u_int)MPII_DMA_DVA(sc->sc_replies) +
   4414   1.1    bouyer 		    MPII_REPLY_SIZE * i);
   4415   1.1    bouyer 	}
   4416   1.1    bouyer 
   4417   1.1    bouyer 	sc->sc_reply_postq =
   4418   1.1    bouyer 	    mpii_dmamem_alloc(sc, sc->sc_reply_post_qdepth * 8);
   4419   1.1    bouyer 	if (sc->sc_reply_postq == NULL)
   4420   1.1    bouyer 		goto free_reply_freeq;
   4421   1.1    bouyer 	sc->sc_reply_postq_kva = MPII_DMA_KVA(sc->sc_reply_postq);
   4422   1.1    bouyer 
   4423   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  populating reply post descriptor queue\n",
   4424   1.1    bouyer 	    DEVNAME(sc));
   4425   1.1    bouyer 	kva64 = (u_int64_t *)MPII_DMA_KVA(sc->sc_reply_postq);
   4426   1.1    bouyer 	for (i = 0; i < sc->sc_reply_post_qdepth; i++) {
   4427   1.1    bouyer 		kva64[i] = 0xffffffffffffffffllu;
   4428   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s:    %d:  %p = 0x%" PRIx64 "\n",
   4429   1.1    bouyer 		    DEVNAME(sc), i, &kva64[i], kva64[i]);
   4430   1.1    bouyer 	}
   4431   1.1    bouyer 
   4432   1.1    bouyer 	return (0);
   4433   1.1    bouyer 
   4434   1.1    bouyer free_reply_freeq:
   4435   1.1    bouyer 
   4436   1.1    bouyer 	mpii_dmamem_free(sc, sc->sc_reply_freeq);
   4437   1.1    bouyer 	return (1);
   4438   1.1    bouyer }
   4439   1.1    bouyer 
   4440   1.1    bouyer static void
   4441   1.1    bouyer mpii_init_queues(struct mpii_softc *sc)
   4442   1.1    bouyer {
   4443   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  mpii_init_queues\n", DEVNAME(sc));
   4444   1.1    bouyer 
   4445   1.1    bouyer 	sc->sc_reply_free_host_index = sc->sc_reply_free_qdepth - 1;
   4446   1.1    bouyer 	sc->sc_reply_post_host_index = 0;
   4447   1.1    bouyer 	mpii_write_reply_free(sc, sc->sc_reply_free_host_index);
   4448   1.1    bouyer 	mpii_write_reply_post(sc, sc->sc_reply_post_host_index);
   4449   1.1    bouyer }
   4450   1.1    bouyer 
   4451   1.1    bouyer static void
   4452   1.1    bouyer mpii_wait(struct mpii_softc *sc, struct mpii_ccb *ccb)
   4453   1.1    bouyer {
   4454   1.1    bouyer 	struct mpii_ccb_wait	mpii_ccb_wait;
   4455   1.1    bouyer 	void			(*done)(struct mpii_ccb *);
   4456   1.1    bouyer 	void			*cookie;
   4457   1.1    bouyer 
   4458   1.1    bouyer 	done = ccb->ccb_done;
   4459   1.1    bouyer 	cookie = ccb->ccb_cookie;
   4460   1.1    bouyer 
   4461   1.1    bouyer 	ccb->ccb_done = mpii_wait_done;
   4462   1.1    bouyer 	ccb->ccb_cookie = &mpii_ccb_wait;
   4463   1.1    bouyer 
   4464   1.1    bouyer 	mutex_init(&mpii_ccb_wait.mpii_ccbw_mtx, MUTEX_DEFAULT, IPL_BIO);
   4465   1.1    bouyer 	cv_init(&mpii_ccb_wait.mpii_ccbw_cv, "mpii_wait");
   4466   1.1    bouyer 
   4467   1.1    bouyer 	/* XXX this will wait forever for the ccb to complete */
   4468   1.1    bouyer 
   4469   1.1    bouyer 	mpii_start(sc, ccb);
   4470   1.1    bouyer 
   4471   1.1    bouyer 	mutex_enter(&mpii_ccb_wait.mpii_ccbw_mtx);
   4472   1.1    bouyer 	while (ccb->ccb_cookie != NULL) {
   4473   1.1    bouyer 		cv_wait(&mpii_ccb_wait.mpii_ccbw_cv,
   4474   1.1    bouyer 		    &mpii_ccb_wait.mpii_ccbw_mtx);
   4475   1.1    bouyer 	}
   4476   1.1    bouyer 	mutex_exit(&mpii_ccb_wait.mpii_ccbw_mtx);
   4477   1.1    bouyer 	mutex_destroy(&mpii_ccb_wait.mpii_ccbw_mtx);
   4478   1.1    bouyer 	cv_destroy(&mpii_ccb_wait.mpii_ccbw_cv);
   4479   1.1    bouyer 
   4480   1.1    bouyer 	ccb->ccb_cookie = cookie;
   4481   1.1    bouyer 	done(ccb);
   4482   1.1    bouyer }
   4483   1.1    bouyer 
   4484   1.1    bouyer static void
   4485   1.1    bouyer mpii_wait_done(struct mpii_ccb *ccb)
   4486   1.1    bouyer {
   4487   1.1    bouyer 	struct mpii_ccb_wait	*mpii_ccb_waitp = ccb->ccb_cookie;
   4488   1.1    bouyer 
   4489   1.1    bouyer 	mutex_enter(&mpii_ccb_waitp->mpii_ccbw_mtx);
   4490   1.1    bouyer 	ccb->ccb_cookie = NULL;
   4491   1.1    bouyer 	cv_signal(&mpii_ccb_waitp->mpii_ccbw_cv);
   4492   1.1    bouyer 	mutex_exit(&mpii_ccb_waitp->mpii_ccbw_mtx);
   4493   1.1    bouyer }
   4494   1.1    bouyer 
   4495   1.1    bouyer static void
   4496   1.1    bouyer mpii_minphys(struct buf *bp)
   4497   1.1    bouyer {
   4498   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "mpii_minphys: %d\n", bp->b_bcount);
   4499   1.1    bouyer 
   4500   1.1    bouyer 	/* XXX currently using MPII_MAXFER = MAXPHYS */
   4501   1.1    bouyer 	if (bp->b_bcount > MPII_MAXFER) {
   4502   1.1    bouyer 		bp->b_bcount = MPII_MAXFER;
   4503   1.1    bouyer 		minphys(bp);
   4504   1.1    bouyer 	}
   4505   1.1    bouyer }
   4506   1.1    bouyer 
   4507   1.1    bouyer static void
   4508   1.1    bouyer mpii_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
   4509   1.1    bouyer     void *arg)
   4510   1.1    bouyer {
   4511   1.1    bouyer 	struct scsipi_periph	*periph;
   4512   1.1    bouyer 	struct scsipi_xfer	*xs;
   4513   1.1    bouyer 	struct scsipi_adapter	*adapt = chan->chan_adapter;
   4514   1.1    bouyer 	struct mpii_softc	*sc = device_private(adapt->adapt_dev);
   4515   1.1    bouyer 	struct mpii_ccb		*ccb;
   4516   1.1    bouyer 	struct mpii_ccb_bundle	*mcb;
   4517   1.1    bouyer 	struct mpii_msg_scsi_io	*io;
   4518   1.1    bouyer 	struct mpii_device	*dev;
   4519   1.1    bouyer 	int			target;
   4520   1.1    bouyer 	int timeout;
   4521   1.1    bouyer 
   4522   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s: mpii_scsipi_request\n", DEVNAME(sc));
   4523   1.1    bouyer 	switch (req) {
   4524   1.1    bouyer 	case ADAPTER_REQ_GROW_RESOURCES:
   4525   1.1    bouyer 		/* Not supported. */
   4526   1.1    bouyer 		return;
   4527   1.1    bouyer 	case ADAPTER_REQ_SET_XFER_MODE:
   4528   1.1    bouyer 	{
   4529   1.1    bouyer 		struct scsipi_xfer_mode *xm = arg;
   4530   1.1    bouyer 		xm->xm_mode = PERIPH_CAP_TQING;
   4531   1.1    bouyer 		xm->xm_period = 0;
   4532   1.1    bouyer 		xm->xm_offset = 0;
   4533   1.1    bouyer 		scsipi_async_event(&sc->sc_chan, ASYNC_EVENT_XFER_MODE, xm);
   4534   1.1    bouyer 		return;
   4535   1.1    bouyer 	}
   4536   1.1    bouyer 	case ADAPTER_REQ_RUN_XFER:
   4537   1.1    bouyer 		break;
   4538   1.1    bouyer 	}
   4539   1.1    bouyer 
   4540   1.1    bouyer 	xs = arg;
   4541   1.1    bouyer 	periph = xs->xs_periph;
   4542   1.1    bouyer 	target = periph->periph_target;
   4543   1.1    bouyer 
   4544   1.1    bouyer 	if (xs->cmdlen > MPII_CDB_LEN) {
   4545   1.1    bouyer 		DNPRINTF(MPII_D_CMD, "%s: CBD too big %d\n",
   4546   1.1    bouyer 		    DEVNAME(sc), xs->cmdlen);
   4547   1.1    bouyer 		bzero(&xs->sense, sizeof(xs->sense));
   4548   1.1    bouyer 		xs->sense.scsi_sense.response_code =
   4549   1.1    bouyer 		    SSD_RCODE_VALID | SSD_RCODE_CURRENT;
   4550   1.1    bouyer 		xs->sense.scsi_sense.flags = SKEY_ILLEGAL_REQUEST;
   4551   1.1    bouyer 		xs->sense.scsi_sense.asc = 0x20;
   4552   1.1    bouyer 		xs->error = XS_SENSE;
   4553   1.1    bouyer 		scsipi_done(xs);
   4554   1.1    bouyer 		return;
   4555   1.1    bouyer 	}
   4556   1.1    bouyer 
   4557   1.1    bouyer 	if ((dev = sc->sc_devs[target]) == NULL) {
   4558   1.1    bouyer 		/* device no longer exists */
   4559   1.1    bouyer 		xs->error = XS_SELTIMEOUT;
   4560   1.1    bouyer 		scsipi_done(xs);
   4561   1.1    bouyer 		return;
   4562   1.1    bouyer 	}
   4563   1.1    bouyer 
   4564   1.1    bouyer 	ccb = mpii_get_ccb(sc, MPII_NOSLEEP);
   4565   1.1    bouyer 	if (ccb == NULL) {
   4566   1.1    bouyer 		xs->error = XS_RESOURCE_SHORTAGE;
   4567   1.1    bouyer 		scsipi_done(xs);
   4568   1.1    bouyer 		return;
   4569   1.1    bouyer 	}
   4570   1.1    bouyer 
   4571   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s: ccb_smid: %d xs->xs_control: 0x%x\n",
   4572   1.1    bouyer 	    DEVNAME(sc), ccb->ccb_smid, xs->xs_control);
   4573   1.1    bouyer 
   4574   1.1    bouyer 	ccb->ccb_cookie = xs;
   4575   1.1    bouyer 	ccb->ccb_done = mpii_scsi_cmd_done;
   4576   1.1    bouyer 	ccb->ccb_dev_handle = dev->dev_handle;
   4577   1.1    bouyer 
   4578   1.1    bouyer 	mcb = ccb->ccb_cmd;
   4579   1.1    bouyer 	io = &mcb->mcb_io;
   4580   1.1    bouyer 
   4581   1.1    bouyer 	io->function = MPII_FUNCTION_SCSI_IO_REQUEST;
   4582   1.1    bouyer 	io->sense_buffer_length = sizeof(xs->sense);
   4583   1.1    bouyer 	io->sgl_offset0 = 24; /* XXX fix this */
   4584   1.1    bouyer 	io->io_flags = htole16(xs->cmdlen);
   4585   1.1    bouyer 	io->dev_handle = htole16(ccb->ccb_dev_handle);
   4586   1.1    bouyer 	io->lun[0] = htobe16(periph->periph_lun);
   4587   1.1    bouyer 
   4588   1.1    bouyer 	switch (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
   4589   1.1    bouyer 	case XS_CTL_DATA_IN:
   4590   1.1    bouyer 		io->direction = MPII_SCSIIO_DIR_READ;
   4591   1.1    bouyer 		break;
   4592   1.1    bouyer 	case XS_CTL_DATA_OUT:
   4593   1.1    bouyer 		io->direction = MPII_SCSIIO_DIR_WRITE;
   4594   1.1    bouyer 		break;
   4595   1.1    bouyer 	default:
   4596   1.1    bouyer 		io->direction = MPII_SCSIIO_DIR_NONE;
   4597   1.1    bouyer 	}
   4598   1.1    bouyer 
   4599   1.1    bouyer 	io->tagging = MPII_SCSIIO_ATTR_SIMPLE_Q;
   4600   1.1    bouyer 
   4601   1.1    bouyer 	memcpy(io->cdb, xs->cmd, xs->cmdlen);
   4602   1.1    bouyer 
   4603   1.1    bouyer 	io->data_length = htole32(xs->datalen);
   4604   1.1    bouyer 
   4605   1.1    bouyer 	io->sense_buffer_low_address = htole32(ccb->ccb_cmd_dva +
   4606   1.1    bouyer 	    ((u_int8_t *)&mcb->mcb_sense - (u_int8_t *)mcb));
   4607   1.1    bouyer 
   4608   1.1    bouyer 	if (mpii_load_xs(ccb) != 0) {
   4609   1.1    bouyer 		xs->error = XS_DRIVER_STUFFUP;
   4610   1.1    bouyer 		mpii_put_ccb(sc, ccb);
   4611   1.1    bouyer 		scsipi_done(xs);
   4612   1.1    bouyer 		return;
   4613   1.1    bouyer 	}
   4614   1.1    bouyer 
   4615   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  sizeof(mpii_msg_scsi_io): %ld "
   4616   1.1    bouyer 	    "sizeof(mpii_ccb_bundle): %ld sge offset: 0x%02lx\n",
   4617   1.1    bouyer 	    DEVNAME(sc), sizeof(struct mpii_msg_scsi_io),
   4618   1.1    bouyer 	    sizeof(struct mpii_ccb_bundle),
   4619   1.1    bouyer 	    (u_int8_t *)&mcb->mcb_sgl[0] - (u_int8_t *)mcb);
   4620   1.1    bouyer 
   4621   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s   sgl[0]: 0x%04x 0%04x 0x%04x\n",
   4622   1.1    bouyer 	    DEVNAME(sc), mcb->mcb_sgl[0].sg_hdr, mcb->mcb_sgl[0].sg_lo_addr,
   4623   1.1    bouyer 	    mcb->mcb_sgl[0].sg_hi_addr);
   4624   1.1    bouyer 
   4625   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  Offset0: 0x%02x\n", DEVNAME(sc),
   4626   1.1    bouyer 	    io->sgl_offset0);
   4627   1.1    bouyer 
   4628   1.1    bouyer 	if (xs->xs_control & XS_CTL_POLL) {
   4629   1.1    bouyer 		if (mpii_poll(sc, ccb) != 0) {
   4630   1.1    bouyer 			xs->error = XS_DRIVER_STUFFUP;
   4631   1.1    bouyer 			mpii_put_ccb(sc, ccb);
   4632   1.1    bouyer 			scsipi_done(xs);
   4633   1.1    bouyer 		}
   4634   1.1    bouyer 		return;
   4635   1.1    bouyer 	}
   4636   1.1    bouyer 	timeout = mstohz(xs->timeout);
   4637   1.1    bouyer 	if (timeout == 0)
   4638   1.1    bouyer 		timeout = 1;
   4639   1.1    bouyer 	callout_reset(&xs->xs_callout, timeout, mpii_scsi_cmd_tmo, ccb);
   4640   1.1    bouyer 
   4641   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:    mpii_scsipi_request(): opcode: %02x "
   4642   1.1    bouyer 	    "datalen: %d\n", DEVNAME(sc), xs->cmd->opcode, xs->datalen);
   4643   1.1    bouyer 
   4644   1.1    bouyer 	mpii_start(sc, ccb);
   4645   1.1    bouyer }
   4646   1.1    bouyer 
   4647   1.1    bouyer static void
   4648   1.1    bouyer mpii_scsi_cmd_tmo(void *xccb)
   4649   1.1    bouyer {
   4650   1.1    bouyer 	struct mpii_ccb		*ccb = xccb;
   4651   1.1    bouyer 	struct mpii_softc	*sc = ccb->ccb_sc;
   4652   1.1    bouyer 
   4653   1.1    bouyer 	printf("%s: mpii_scsi_cmd_tmo\n", DEVNAME(sc));
   4654   1.1    bouyer 
   4655   1.1    bouyer 	mutex_enter(&sc->sc_ccb_mtx);
   4656   1.1    bouyer 	if (ccb->ccb_state == MPII_CCB_QUEUED) {
   4657   1.1    bouyer 		ccb->ccb_state = MPII_CCB_TIMEOUT;
   4658   1.1    bouyer 		workqueue_enqueue(sc->sc_ssb_tmowk, &ccb->u.ccb_wk, NULL);
   4659   1.1    bouyer 	}
   4660   1.1    bouyer 	mutex_exit(&sc->sc_ccb_mtx);
   4661   1.1    bouyer }
   4662   1.1    bouyer 
   4663   1.1    bouyer static void
   4664   1.1    bouyer mpii_scsi_cmd_tmo_handler(struct work *wk, void *cookie)
   4665   1.1    bouyer {
   4666   1.1    bouyer 	struct mpii_softc			*sc = cookie;
   4667   1.1    bouyer 	struct mpii_ccb				*tccb;
   4668   1.1    bouyer 	struct mpii_ccb				*ccb;
   4669   1.1    bouyer 	struct mpii_msg_scsi_task_request	*stq;
   4670   1.1    bouyer 
   4671   1.1    bouyer 	ccb = (void *)wk;
   4672   1.1    bouyer 	tccb = mpii_get_ccb(sc, 0);
   4673   1.1    bouyer 
   4674   1.1    bouyer 	mutex_enter(&sc->sc_ccb_mtx);
   4675   1.1    bouyer 	if (ccb->ccb_state != MPII_CCB_TIMEOUT) {
   4676   1.1    bouyer 		mpii_put_ccb(sc, tccb);
   4677   1.1    bouyer 	}
   4678   1.1    bouyer 	/* should remove any other ccbs for the same dev handle */
   4679   1.1    bouyer 	mutex_exit(&sc->sc_ccb_mtx);
   4680   1.1    bouyer 
   4681   1.1    bouyer 	stq = tccb->ccb_cmd;
   4682   1.1    bouyer 	stq->function = MPII_FUNCTION_SCSI_TASK_MGMT;
   4683   1.1    bouyer 	stq->task_type = MPII_SCSI_TASK_TARGET_RESET;
   4684   1.1    bouyer 	stq->dev_handle = htole16(ccb->ccb_dev_handle);
   4685   1.1    bouyer 
   4686   1.1    bouyer 	tccb->ccb_done = mpii_scsi_cmd_tmo_done;
   4687   1.1    bouyer 	mpii_start(sc, tccb);
   4688   1.1    bouyer }
   4689   1.1    bouyer 
   4690   1.1    bouyer static void
   4691   1.1    bouyer mpii_scsi_cmd_tmo_done(struct mpii_ccb *tccb)
   4692   1.1    bouyer {
   4693   1.1    bouyer         mpii_put_ccb(tccb->ccb_sc, tccb);
   4694   1.1    bouyer }
   4695   1.1    bouyer 
   4696   1.3    kardel static u_int8_t
   4697   1.3    kardel map_scsi_status(u_int8_t mpii_scsi_status)
   4698   1.3    kardel {
   4699   1.3    kardel 	u_int8_t scsi_status;
   4700   1.3    kardel 
   4701   1.3    kardel 	switch (mpii_scsi_status)
   4702   1.3    kardel 	{
   4703   1.3    kardel 	case MPII_SCSIIO_ERR_STATUS_SUCCESS:
   4704   1.3    kardel 		scsi_status = SCSI_OK;
   4705   1.3    kardel 		break;
   4706   1.3    kardel 
   4707   1.3    kardel 	case MPII_SCSIIO_ERR_STATUS_CHECK_COND:
   4708   1.3    kardel 		scsi_status = SCSI_CHECK;
   4709   1.3    kardel 		break;
   4710   1.3    kardel 
   4711   1.3    kardel 	case MPII_SCSIIO_ERR_STATUS_BUSY:
   4712   1.3    kardel 		scsi_status = SCSI_BUSY;
   4713   1.3    kardel 		break;
   4714   1.3    kardel 
   4715   1.3    kardel 	case MPII_SCSIIO_ERR_STATUS_INTERMEDIATE:
   4716   1.3    kardel 		scsi_status = SCSI_INTERM;
   4717   1.3    kardel 		break;
   4718   1.3    kardel 
   4719   1.3    kardel 	case MPII_SCSIIO_ERR_STATUS_INTERMEDIATE_CONDMET:
   4720   1.3    kardel 		scsi_status = SCSI_INTERM;
   4721   1.3    kardel 		break;
   4722   1.3    kardel 
   4723   1.3    kardel 	case MPII_SCSIIO_ERR_STATUS_RESERVATION_CONFLICT:
   4724   1.3    kardel 		scsi_status = SCSI_RESV_CONFLICT;
   4725   1.3    kardel 		break;
   4726   1.3    kardel 
   4727   1.3    kardel 	case MPII_SCSIIO_ERR_STATUS_CMD_TERM:
   4728   1.3    kardel 	case MPII_SCSIIO_ERR_STATUS_TASK_ABORTED:
   4729   1.3    kardel 		scsi_status = SCSI_TERMINATED;
   4730   1.3    kardel 		break;
   4731   1.3    kardel 
   4732   1.3    kardel 	case MPII_SCSIIO_ERR_STATUS_TASK_SET_FULL:
   4733   1.3    kardel 		scsi_status = SCSI_QUEUE_FULL;
   4734   1.3    kardel 		break;
   4735   1.3    kardel 
   4736   1.3    kardel 	case MPII_SCSIIO_ERR_STATUS_ACA_ACTIVE:
   4737   1.3    kardel 		scsi_status = SCSI_ACA_ACTIVE;
   4738   1.3    kardel 		break;
   4739   1.3    kardel 
   4740   1.3    kardel 	default:
   4741   1.3    kardel 		/* XXX: for the lack of anything better and other than OK */
   4742   1.3    kardel 		scsi_status = 0xFF;
   4743   1.3    kardel 		break;
   4744   1.3    kardel 	}
   4745   1.3    kardel 
   4746   1.3    kardel 	return scsi_status;
   4747   1.3    kardel }
   4748   1.1    bouyer 
   4749   1.1    bouyer static void
   4750   1.1    bouyer mpii_scsi_cmd_done(struct mpii_ccb *ccb)
   4751   1.1    bouyer {
   4752   1.1    bouyer 	struct mpii_msg_scsi_io_error	*sie;
   4753   1.1    bouyer 	struct mpii_softc	*sc = ccb->ccb_sc;
   4754   1.1    bouyer 	struct scsipi_xfer	*xs = ccb->ccb_cookie;
   4755   1.1    bouyer 	struct mpii_ccb_bundle	*mcb = ccb->ccb_cmd;
   4756   1.1    bouyer 	bus_dmamap_t		dmap = ccb->ccb_dmamap;
   4757   1.1    bouyer 	bool			timeout = 0;
   4758   1.1    bouyer 
   4759   1.1    bouyer 	callout_stop(&xs->xs_callout);
   4760   1.1    bouyer 	mutex_enter(&sc->sc_ccb_mtx);
   4761   1.1    bouyer 	if (ccb->ccb_state == MPII_CCB_TIMEOUT)
   4762   1.1    bouyer 		timeout = 1;
   4763   1.1    bouyer 	ccb->ccb_state = MPII_CCB_READY;
   4764   1.1    bouyer 	mutex_exit(&sc->sc_ccb_mtx);
   4765   1.1    bouyer 
   4766   1.1    bouyer 	if (xs->datalen != 0) {
   4767   1.1    bouyer 		bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
   4768   1.1    bouyer 		    (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_POSTREAD :
   4769   1.1    bouyer 		    BUS_DMASYNC_POSTWRITE);
   4770   1.1    bouyer 
   4771   1.1    bouyer 		bus_dmamap_unload(sc->sc_dmat, dmap);
   4772   1.1    bouyer 	}
   4773   1.1    bouyer 
   4774   1.1    bouyer 	xs->error = XS_NOERROR;
   4775   1.1    bouyer 	xs->resid = 0;
   4776   1.1    bouyer 
   4777   1.1    bouyer 	if (ccb->ccb_rcb == NULL) {
   4778   1.1    bouyer 		/* no scsi error, we're ok so drop out early */
   4779   1.1    bouyer 		xs->status = SCSI_OK;
   4780   1.1    bouyer 		mpii_put_ccb(sc, ccb);
   4781   1.1    bouyer 		scsipi_done(xs);
   4782   1.1    bouyer 		return;
   4783   1.1    bouyer 	}
   4784   1.1    bouyer 
   4785   1.1    bouyer 	sie = ccb->ccb_rcb->rcb_reply;
   4786   1.1    bouyer 
   4787   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s: mpii_scsi_cmd_done xs cmd: 0x%02x len: %d "
   4788   1.1    bouyer 	    "xs_control 0x%x\n", DEVNAME(sc), xs->cmd->opcode, xs->datalen,
   4789   1.1    bouyer 	    xs->xs_control);
   4790   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  dev_handle: %d msg_length: %d "
   4791   1.1    bouyer 	    "function: 0x%02x\n", DEVNAME(sc), le16toh(sie->dev_handle),
   4792   1.1    bouyer 	    sie->msg_length, sie->function);
   4793   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc),
   4794   1.1    bouyer 	    sie->vp_id, sie->vf_id);
   4795   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  scsi_status: 0x%02x scsi_state: 0x%02x "
   4796   1.1    bouyer 	    "ioc_status: 0x%04x\n", DEVNAME(sc), sie->scsi_status,
   4797   1.1    bouyer 	    sie->scsi_state, le16toh(sie->ioc_status));
   4798   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
   4799   1.1    bouyer 	    le32toh(sie->ioc_loginfo));
   4800   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  transfer_count: %d\n", DEVNAME(sc),
   4801   1.1    bouyer 	    le32toh(sie->transfer_count));
   4802   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  sense_count: %d\n", DEVNAME(sc),
   4803   1.1    bouyer 	    le32toh(sie->sense_count));
   4804   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  response_info: 0x%08x\n", DEVNAME(sc),
   4805   1.1    bouyer 	    le32toh(sie->response_info));
   4806   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  task_tag: 0x%04x\n", DEVNAME(sc),
   4807   1.1    bouyer 	    le16toh(sie->task_tag));
   4808   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  bidirectional_transfer_count: 0x%08x\n",
   4809   1.1    bouyer 	    DEVNAME(sc), le32toh(sie->bidirectional_transfer_count));
   4810   1.1    bouyer 
   4811   1.3    kardel 	xs->status = map_scsi_status(sie->scsi_status);
   4812   1.3    kardel 
   4813   1.1    bouyer 	switch (le16toh(sie->ioc_status) & MPII_IOCSTATUS_MASK) {
   4814   1.1    bouyer 	case MPII_IOCSTATUS_SCSI_DATA_UNDERRUN:
   4815   1.3    kardel 		switch (sie->scsi_status) {
   4816   1.3    kardel 		case MPII_SCSIIO_ERR_STATUS_CHECK_COND:
   4817   1.3    kardel 			xs->error = XS_SENSE;
   4818   1.3    kardel 			/*FALLTHROUGH*/
   4819   1.3    kardel 		case MPII_SCSIIO_ERR_STATUS_SUCCESS:
   4820   1.1    bouyer 			xs->resid = xs->datalen - le32toh(sie->transfer_count);
   4821   1.1    bouyer 			break;
   4822   1.3    kardel 
   4823   1.1    bouyer 		default:
   4824   1.1    bouyer 			xs->error = XS_DRIVER_STUFFUP;
   4825   1.1    bouyer 			break;
   4826   1.1    bouyer 		}
   4827   1.1    bouyer 		break;
   4828   1.3    kardel 
   4829   1.1    bouyer 	case MPII_IOCSTATUS_SUCCESS:
   4830   1.1    bouyer 	case MPII_IOCSTATUS_SCSI_RECOVERED_ERROR:
   4831   1.3    kardel 		switch (sie->scsi_status) {
   4832   1.3    kardel 		case MPII_SCSIIO_ERR_STATUS_SUCCESS:
   4833   1.3    kardel 			/*
   4834   1.3    kardel 			 * xs->resid = 0; - already set above
   4835   1.3    kardel 			 *
   4836   1.3    kardel 			 * XXX: check whether UNDERUN strategy
   4837   1.3    kardel 			 * would be appropriate here too.
   4838   1.3    kardel 			 * that would allow joining these cases.
   4839   1.3    kardel 			 */
   4840   1.1    bouyer 			break;
   4841   1.1    bouyer 
   4842   1.3    kardel 		case MPII_SCSIIO_ERR_STATUS_CHECK_COND:
   4843   1.1    bouyer 			xs->error = XS_SENSE;
   4844   1.1    bouyer 			break;
   4845   1.3    kardel 
   4846   1.3    kardel 		case MPII_SCSIIO_ERR_STATUS_BUSY:
   4847   1.3    kardel 		case MPII_SCSIIO_ERR_STATUS_TASK_SET_FULL:
   4848   1.1    bouyer 			xs->error = XS_BUSY;
   4849   1.1    bouyer 			break;
   4850   1.1    bouyer 
   4851   1.1    bouyer 		default:
   4852   1.1    bouyer 			xs->error = XS_DRIVER_STUFFUP;
   4853   1.1    bouyer 		}
   4854   1.1    bouyer 		break;
   4855   1.1    bouyer 
   4856   1.1    bouyer 	case MPII_IOCSTATUS_BUSY:
   4857   1.1    bouyer 	case MPII_IOCSTATUS_INSUFFICIENT_RESOURCES:
   4858   1.1    bouyer 		xs->error = XS_BUSY;
   4859   1.1    bouyer 		break;
   4860   1.1    bouyer 
   4861   1.1    bouyer 	case MPII_IOCSTATUS_SCSI_IOC_TERMINATED:
   4862   1.1    bouyer 	case MPII_IOCSTATUS_SCSI_TASK_TERMINATED:
   4863   1.1    bouyer 		xs->error = timeout ? XS_TIMEOUT : XS_RESET;
   4864   1.1    bouyer 		break;
   4865   1.1    bouyer 
   4866   1.1    bouyer 	case MPII_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
   4867   1.1    bouyer 	case MPII_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
   4868   1.1    bouyer 		xs->error = XS_SELTIMEOUT;
   4869   1.1    bouyer 		break;
   4870   1.1    bouyer 
   4871   1.1    bouyer 	default:
   4872   1.1    bouyer 		xs->error = XS_DRIVER_STUFFUP;
   4873   1.1    bouyer 		break;
   4874   1.1    bouyer 	}
   4875   1.1    bouyer 
   4876   1.1    bouyer 	if (sie->scsi_state & MPII_SCSIIO_ERR_STATE_AUTOSENSE_VALID)
   4877   1.1    bouyer 		memcpy(&xs->sense, &mcb->mcb_sense, sizeof(xs->sense));
   4878   1.1    bouyer 
   4879   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  xs err: %d status: %#x\n", DEVNAME(sc),
   4880   1.1    bouyer 	    xs->error, xs->status);
   4881   1.1    bouyer 
   4882   1.1    bouyer 	mpii_push_reply(sc, ccb->ccb_rcb);
   4883   1.1    bouyer 	mpii_put_ccb(sc, ccb);
   4884   1.1    bouyer 	scsipi_done(xs);
   4885   1.1    bouyer }
   4886   1.1    bouyer 
   4887   1.1    bouyer #if 0
   4888   1.1    bouyer static int
   4889   1.1    bouyer mpii_ioctl_cache(struct scsi_link *link, u_long cmd, struct dk_cache *dc)
   4890   1.1    bouyer {
   4891   1.1    bouyer 	struct mpii_softc *sc = (struct mpii_softc *)link->adapter_softc;
   4892   1.1    bouyer 	struct mpii_device *dev = sc->sc_devs[link->target];
   4893   1.1    bouyer 	struct mpii_cfg_raid_vol_pg0 *vpg;
   4894   1.1    bouyer 	struct mpii_msg_raid_action_request *req;
   4895   1.1    bouyer  	struct mpii_msg_raid_action_reply *rep;
   4896   1.1    bouyer 	struct mpii_cfg_hdr hdr;
   4897   1.1    bouyer 	struct mpii_ccb	*ccb;
   4898   1.1    bouyer 	u_int32_t addr = MPII_CFG_RAID_VOL_ADDR_HANDLE | dev->dev_handle;
   4899   1.1    bouyer 	size_t pagelen;
   4900   1.1    bouyer 	int rv = 0;
   4901   1.1    bouyer 	int enabled;
   4902   1.1    bouyer 
   4903   1.1    bouyer 	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
   4904   1.1    bouyer 	    addr, MPII_PG_POLL, &hdr) != 0)
   4905   1.1    bouyer 		return (EINVAL);
   4906   1.1    bouyer 
   4907   1.1    bouyer 	pagelen = hdr.page_length * 4;
   4908  1.12  jdolecek 	vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_ZERO);
   4909   1.1    bouyer 	if (vpg == NULL)
   4910   1.1    bouyer 		return (ENOMEM);
   4911   1.1    bouyer 
   4912   1.1    bouyer 	if (mpii_req_cfg_page(sc, addr, MPII_PG_POLL, &hdr, 1,
   4913   1.1    bouyer 	    vpg, pagelen) != 0) {
   4914   1.1    bouyer 		rv = EINVAL;
   4915   1.1    bouyer 		goto done;
   4916   1.1    bouyer 	}
   4917   1.1    bouyer 
   4918   1.1    bouyer 	enabled = ((le16toh(vpg->volume_settings) &
   4919   1.1    bouyer 	    MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_MASK) ==
   4920   1.1    bouyer 	    MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_ENABLED) ? 1 : 0;
   4921   1.1    bouyer 
   4922   1.1    bouyer 	if (cmd == DIOCGCACHE) {
   4923   1.1    bouyer 		dc->wrcache = enabled;
   4924   1.1    bouyer 		dc->rdcache = 0;
   4925   1.1    bouyer 		goto done;
   4926   1.1    bouyer 	} /* else DIOCSCACHE */
   4927   1.1    bouyer 
   4928   1.1    bouyer 	if (dc->rdcache) {
   4929   1.1    bouyer 		rv = EOPNOTSUPP;
   4930   1.1    bouyer 		goto done;
   4931   1.1    bouyer 	}
   4932   1.1    bouyer 
   4933   1.1    bouyer 	if (((dc->wrcache) ? 1 : 0) == enabled)
   4934   1.1    bouyer 		goto done;
   4935   1.1    bouyer 
   4936   1.1    bouyer 	ccb = mpii_get_ccb(sc, MPII_NOSLEEP);
   4937   1.1    bouyer 	if (ccb == NULL) {
   4938   1.1    bouyer 		rv = ENOMEM;
   4939   1.1    bouyer 		goto done;
   4940   1.1    bouyer 	}
   4941   1.1    bouyer 
   4942   1.1    bouyer 	ccb->ccb_done = mpii_empty_done;
   4943   1.1    bouyer 
   4944   1.1    bouyer 	req = ccb->ccb_cmd;
   4945   1.1    bouyer 	bzero(req, sizeof(*req));
   4946   1.1    bouyer 	req->function = MPII_FUNCTION_RAID_ACTION;
   4947   1.1    bouyer 	req->action = MPII_RAID_ACTION_CHANGE_VOL_WRITE_CACHE;
   4948   1.1    bouyer 	req->vol_dev_handle = htole16(dev->dev_handle);
   4949   1.1    bouyer 	req->action_data = htole32(dc->wrcache ?
   4950   1.1    bouyer 	    MPII_RAID_VOL_WRITE_CACHE_ENABLE :
   4951   1.1    bouyer 	    MPII_RAID_VOL_WRITE_CACHE_DISABLE);
   4952   1.1    bouyer 
   4953   1.1    bouyer 	if (mpii_poll(sc, ccb) != 0) {
   4954   1.1    bouyer 		rv = EIO;
   4955   1.1    bouyer 		goto done;
   4956   1.1    bouyer 	}
   4957   1.1    bouyer 
   4958   1.1    bouyer 	if (ccb->ccb_rcb != NULL) {
   4959   1.1    bouyer 		rep = ccb->ccb_rcb->rcb_reply;
   4960   1.1    bouyer 		if ((rep->ioc_status != MPII_IOCSTATUS_SUCCESS) ||
   4961   1.1    bouyer 		    ((rep->action_data[0] &
   4962   1.1    bouyer 		     MPII_RAID_VOL_WRITE_CACHE_MASK) !=
   4963   1.1    bouyer 		    (dc->wrcache ? MPII_RAID_VOL_WRITE_CACHE_ENABLE :
   4964   1.1    bouyer 		     MPII_RAID_VOL_WRITE_CACHE_DISABLE)))
   4965   1.1    bouyer 			rv = EINVAL;
   4966   1.1    bouyer 		mpii_push_reply(sc, ccb->ccb_rcb);
   4967   1.1    bouyer 	}
   4968   1.1    bouyer 
   4969   1.1    bouyer 	mpii_put_ccb(sc, ccb);
   4970   1.1    bouyer 
   4971   1.1    bouyer done:
   4972   1.1    bouyer 	free(vpg, M_TEMP);
   4973   1.1    bouyer 	return (rv);
   4974   1.1    bouyer }
   4975   1.1    bouyer #endif
   4976   1.1    bouyer static int
   4977   1.1    bouyer mpii_cache_enable(struct mpii_softc *sc, struct mpii_device *dev)
   4978   1.1    bouyer {
   4979   1.1    bouyer 	struct mpii_cfg_raid_vol_pg0 *vpg;
   4980   1.1    bouyer 	struct mpii_msg_raid_action_request *req;
   4981   1.1    bouyer  	struct mpii_msg_raid_action_reply *rep;
   4982   1.1    bouyer 	struct mpii_cfg_hdr hdr;
   4983   1.1    bouyer 	struct mpii_ccb	*ccb;
   4984   1.1    bouyer 	u_int32_t addr = MPII_CFG_RAID_VOL_ADDR_HANDLE | dev->dev_handle;
   4985   1.1    bouyer 	size_t pagelen;
   4986   1.1    bouyer 	int rv = 0;
   4987   1.1    bouyer 	int enabled;
   4988   1.1    bouyer 
   4989   1.1    bouyer 	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
   4990   1.1    bouyer 	    addr, MPII_PG_POLL, &hdr) != 0)
   4991   1.1    bouyer 		return (EINVAL);
   4992   1.1    bouyer 
   4993   1.1    bouyer 	pagelen = hdr.page_length * 4;
   4994   1.9  christos 	vpg = malloc(pagelen, M_TEMP, M_NOWAIT | M_ZERO);
   4995   1.1    bouyer 	if (vpg == NULL)
   4996   1.1    bouyer 		return (ENOMEM);
   4997   1.1    bouyer 
   4998   1.1    bouyer 	if (mpii_req_cfg_page(sc, addr, MPII_PG_POLL, &hdr, 1,
   4999   1.1    bouyer 	    vpg, pagelen) != 0) {
   5000   1.1    bouyer 		rv = EINVAL;
   5001   1.1    bouyer 		goto done;
   5002   1.1    bouyer 		free(vpg, M_TEMP);
   5003   1.1    bouyer 		return (EINVAL);
   5004   1.1    bouyer 	}
   5005   1.1    bouyer 
   5006   1.1    bouyer 	enabled = ((le16toh(vpg->volume_settings) &
   5007   1.1    bouyer 	    MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_MASK) ==
   5008   1.1    bouyer 	    MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_ENABLED) ? 1 : 0;
   5009   1.1    bouyer 	aprint_normal_dev(sc->sc_dev, "target %d cache %s", dev->slot,
   5010   1.1    bouyer 	    enabled ? "enabled" : "disabled, enabling");
   5011   1.1    bouyer 	aprint_normal("\n");
   5012   1.1    bouyer 
   5013   1.1    bouyer 	if (enabled == 0)
   5014   1.1    bouyer 		goto done;
   5015   1.1    bouyer 
   5016   1.1    bouyer 	ccb = mpii_get_ccb(sc, MPII_NOSLEEP);
   5017   1.1    bouyer 	if (ccb == NULL) {
   5018   1.1    bouyer 		rv = ENOMEM;
   5019   1.1    bouyer 		goto done;
   5020   1.1    bouyer 	}
   5021   1.1    bouyer 
   5022   1.1    bouyer 	ccb->ccb_done = mpii_empty_done;
   5023   1.1    bouyer 
   5024   1.1    bouyer 	req = ccb->ccb_cmd;
   5025   1.1    bouyer 	bzero(req, sizeof(*req));
   5026   1.1    bouyer 	req->function = MPII_FUNCTION_RAID_ACTION;
   5027   1.1    bouyer 	req->action = MPII_RAID_ACTION_CHANGE_VOL_WRITE_CACHE;
   5028   1.1    bouyer 	req->vol_dev_handle = htole16(dev->dev_handle);
   5029   1.1    bouyer 	req->action_data = htole32(
   5030   1.1    bouyer 	    MPII_RAID_VOL_WRITE_CACHE_ENABLE);
   5031   1.1    bouyer 
   5032   1.1    bouyer 	if (mpii_poll(sc, ccb) != 0) {
   5033   1.1    bouyer 		rv = EIO;
   5034   1.1    bouyer 		goto done;
   5035   1.1    bouyer 	}
   5036   1.1    bouyer 
   5037   1.1    bouyer 	if (ccb->ccb_rcb != NULL) {
   5038   1.1    bouyer 		rep = ccb->ccb_rcb->rcb_reply;
   5039   1.1    bouyer 		if ((rep->ioc_status != MPII_IOCSTATUS_SUCCESS) ||
   5040   1.1    bouyer 		    ((rep->action_data[0] &
   5041   1.1    bouyer 		     MPII_RAID_VOL_WRITE_CACHE_MASK) !=
   5042   1.1    bouyer 		     MPII_RAID_VOL_WRITE_CACHE_ENABLE))
   5043   1.1    bouyer 			rv = EINVAL;
   5044   1.1    bouyer 		mpii_push_reply(sc, ccb->ccb_rcb);
   5045   1.1    bouyer 	}
   5046   1.1    bouyer 
   5047   1.1    bouyer 	mpii_put_ccb(sc, ccb);
   5048   1.1    bouyer 
   5049   1.1    bouyer done:
   5050   1.1    bouyer 	free(vpg, M_TEMP);
   5051   1.1    bouyer 	if (rv) {
   5052   1.1    bouyer 		aprint_error_dev(sc->sc_dev,
   5053   1.1    bouyer 		    "enabling cache on target %d failed (%d)\n",
   5054   1.1    bouyer 		    dev->slot, rv);
   5055   1.1    bouyer 	}
   5056   1.1    bouyer 	return (rv);
   5057   1.1    bouyer }
   5058   1.1    bouyer 
   5059   1.1    bouyer #if NBIO > 0
   5060   1.1    bouyer static int
   5061   1.1    bouyer mpii_ioctl(device_t dev, u_long cmd, void *addr)
   5062   1.1    bouyer {
   5063   1.1    bouyer 	struct mpii_softc	*sc = device_private(dev);
   5064   1.1    bouyer 	int			s, error = 0;
   5065   1.1    bouyer 
   5066   1.1    bouyer 	DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl ", DEVNAME(sc));
   5067   1.1    bouyer 	KERNEL_LOCK(1, curlwp);
   5068   1.1    bouyer 	s = splbio();
   5069   1.1    bouyer 
   5070   1.1    bouyer 	switch (cmd) {
   5071   1.1    bouyer 	case BIOCINQ:
   5072   1.1    bouyer 		DNPRINTF(MPII_D_IOCTL, "inq\n");
   5073   1.1    bouyer 		error = mpii_ioctl_inq(sc, (struct bioc_inq *)addr);
   5074   1.1    bouyer 		break;
   5075   1.1    bouyer 	case BIOCVOL:
   5076   1.1    bouyer 		DNPRINTF(MPII_D_IOCTL, "vol\n");
   5077   1.1    bouyer 		error = mpii_ioctl_vol(sc, (struct bioc_vol *)addr);
   5078   1.1    bouyer 		break;
   5079   1.1    bouyer 	case BIOCDISK:
   5080   1.1    bouyer 		DNPRINTF(MPII_D_IOCTL, "disk\n");
   5081   1.1    bouyer 		error = mpii_ioctl_disk(sc, (struct bioc_disk *)addr);
   5082   1.1    bouyer 		break;
   5083   1.1    bouyer 	default:
   5084   1.1    bouyer 		DNPRINTF(MPII_D_IOCTL, " invalid ioctl\n");
   5085   1.1    bouyer 		error = EINVAL;
   5086   1.1    bouyer 	}
   5087   1.1    bouyer 
   5088   1.1    bouyer 	splx(s);
   5089   1.1    bouyer 	KERNEL_UNLOCK_ONE(curlwp);
   5090   1.1    bouyer 	return (error);
   5091   1.1    bouyer }
   5092   1.1    bouyer 
   5093   1.1    bouyer static int
   5094   1.1    bouyer mpii_ioctl_inq(struct mpii_softc *sc, struct bioc_inq *bi)
   5095   1.1    bouyer {
   5096   1.1    bouyer 	int			i;
   5097   1.1    bouyer 
   5098   1.1    bouyer 	DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl_inq\n", DEVNAME(sc));
   5099   1.1    bouyer 
   5100   1.1    bouyer 	strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev));
   5101   1.1    bouyer 	for (i = 0; i < sc->sc_max_devices; i++)
   5102   1.1    bouyer 		if (sc->sc_devs[i] &&
   5103   1.1    bouyer 		    ISSET(sc->sc_devs[i]->flags, MPII_DF_VOLUME))
   5104   1.1    bouyer 			bi->bi_novol++;
   5105   1.1    bouyer 	return (0);
   5106   1.1    bouyer }
   5107   1.1    bouyer 
   5108   1.1    bouyer static int
   5109   1.1    bouyer mpii_ioctl_vol(struct mpii_softc *sc, struct bioc_vol *bv)
   5110   1.1    bouyer {
   5111   1.1    bouyer 	struct mpii_cfg_raid_vol_pg0	*vpg;
   5112   1.1    bouyer 	struct mpii_cfg_hdr		hdr;
   5113   1.1    bouyer 	struct mpii_device		*dev;
   5114   1.1    bouyer 	struct scsipi_periph 		*periph;
   5115   1.1    bouyer 	size_t				pagelen;
   5116   1.1    bouyer 	u_int16_t			volh;
   5117   1.1    bouyer 	int				rv, hcnt = 0;
   5118   1.1    bouyer 
   5119   1.1    bouyer 	DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl_vol %d\n",
   5120   1.1    bouyer 	    DEVNAME(sc), bv->bv_volid);
   5121   1.1    bouyer 
   5122   1.1    bouyer 	if ((dev = mpii_find_vol(sc, bv->bv_volid)) == NULL)
   5123   1.1    bouyer 		return (ENODEV);
   5124   1.1    bouyer 	volh = dev->dev_handle;
   5125   1.1    bouyer 
   5126   1.1    bouyer 	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
   5127   1.1    bouyer 	    MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0, &hdr) != 0) {
   5128   1.1    bouyer 		printf("%s: unable to fetch header for raid volume page 0\n",
   5129   1.1    bouyer 		    DEVNAME(sc));
   5130   1.1    bouyer 		return (EINVAL);
   5131   1.1    bouyer 	}
   5132   1.1    bouyer 
   5133   1.1    bouyer 	pagelen = hdr.page_length * 4;
   5134  1.12  jdolecek 	vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_ZERO);
   5135   1.1    bouyer 	if (vpg == NULL) {
   5136   1.1    bouyer 		printf("%s: unable to allocate space for raid "
   5137   1.1    bouyer 		    "volume page 0\n", DEVNAME(sc));
   5138   1.1    bouyer 		return (ENOMEM);
   5139   1.1    bouyer 	}
   5140   1.1    bouyer 
   5141   1.1    bouyer 	if (mpii_req_cfg_page(sc, MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0,
   5142   1.1    bouyer 	    &hdr, 1, vpg, pagelen) != 0) {
   5143   1.1    bouyer 		printf("%s: unable to fetch raid volume page 0\n",
   5144   1.1    bouyer 		    DEVNAME(sc));
   5145   1.1    bouyer 		free(vpg, M_TEMP);
   5146   1.1    bouyer 		return (EINVAL);
   5147   1.1    bouyer 	}
   5148   1.1    bouyer 
   5149   1.1    bouyer 	switch (vpg->volume_state) {
   5150   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_ONLINE:
   5151   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_OPTIMAL:
   5152   1.1    bouyer 		bv->bv_status = BIOC_SVONLINE;
   5153   1.1    bouyer 		break;
   5154   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_DEGRADED:
   5155   1.1    bouyer 		if (ISSET(le32toh(vpg->volume_status),
   5156   1.1    bouyer 		    MPII_CFG_RAID_VOL_0_STATUS_RESYNC)) {
   5157   1.1    bouyer 			bv->bv_status = BIOC_SVREBUILD;
   5158   1.1    bouyer 			bv->bv_percent = dev->percent;
   5159   1.1    bouyer 		} else
   5160   1.1    bouyer 			bv->bv_status = BIOC_SVDEGRADED;
   5161   1.1    bouyer 		break;
   5162   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_FAILED:
   5163   1.1    bouyer 		bv->bv_status = BIOC_SVOFFLINE;
   5164   1.1    bouyer 		break;
   5165   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_INITIALIZING:
   5166   1.1    bouyer 		bv->bv_status = BIOC_SVBUILDING;
   5167   1.1    bouyer 		break;
   5168   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_MISSING:
   5169   1.1    bouyer 	default:
   5170   1.1    bouyer 		bv->bv_status = BIOC_SVINVALID;
   5171   1.1    bouyer 		break;
   5172   1.1    bouyer 	}
   5173   1.1    bouyer 
   5174   1.1    bouyer 	switch (vpg->volume_type) {
   5175   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_TYPE_RAID0:
   5176   1.1    bouyer 		bv->bv_level = 0;
   5177   1.1    bouyer 		break;
   5178   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_TYPE_RAID1:
   5179   1.1    bouyer 		bv->bv_level = 1;
   5180   1.1    bouyer 		break;
   5181   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_TYPE_RAID1E:
   5182   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_TYPE_RAID10:
   5183   1.1    bouyer 		bv->bv_level = 10;
   5184   1.1    bouyer 		break;
   5185   1.1    bouyer 	default:
   5186   1.1    bouyer 		bv->bv_level = -1;
   5187   1.1    bouyer 	}
   5188   1.1    bouyer 
   5189   1.1    bouyer 	if ((rv = mpii_bio_hs(sc, NULL, 0, vpg->hot_spare_pool, &hcnt)) != 0) {
   5190   1.1    bouyer 		free(vpg, M_TEMP);
   5191   1.1    bouyer 		return (rv);
   5192   1.1    bouyer 	}
   5193   1.1    bouyer 
   5194   1.1    bouyer 	bv->bv_nodisk = vpg->num_phys_disks + hcnt;
   5195   1.1    bouyer 
   5196   1.1    bouyer 	bv->bv_size = le64toh(vpg->max_lba) * le16toh(vpg->block_size);
   5197   1.1    bouyer 
   5198   1.1    bouyer 	periph = scsipi_lookup_periph(&sc->sc_chan, dev->slot, 0);
   5199   1.1    bouyer 	if (periph != NULL) {
   5200   1.1    bouyer 		if (periph->periph_dev == NULL) {
   5201   1.1    bouyer 			snprintf(bv->bv_dev, sizeof(bv->bv_dev), "%s:%d",
   5202   1.1    bouyer 			    DEVNAME(sc), dev->slot);
   5203   1.1    bouyer 		} else {
   5204   1.1    bouyer 			strlcpy(bv->bv_dev, device_xname(periph->periph_dev),
   5205   1.1    bouyer 			    sizeof(bv->bv_dev));
   5206   1.1    bouyer 		}
   5207   1.1    bouyer 	}
   5208   1.1    bouyer 
   5209   1.1    bouyer 	free(vpg, M_TEMP);
   5210   1.1    bouyer 	return (0);
   5211   1.1    bouyer }
   5212   1.1    bouyer 
   5213   1.1    bouyer static int
   5214   1.1    bouyer mpii_ioctl_disk(struct mpii_softc *sc, struct bioc_disk *bd)
   5215   1.1    bouyer {
   5216   1.1    bouyer 	struct mpii_cfg_raid_vol_pg0		*vpg;
   5217   1.1    bouyer 	struct mpii_cfg_raid_vol_pg0_physdisk	*pd;
   5218   1.1    bouyer 	struct mpii_cfg_hdr			hdr;
   5219   1.1    bouyer 	struct mpii_device			*dev;
   5220   1.1    bouyer 	size_t					pagelen;
   5221   1.1    bouyer 	u_int16_t				volh;
   5222   1.1    bouyer 	u_int8_t				dn;
   5223   1.1    bouyer 
   5224   1.1    bouyer 	DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl_disk %d/%d\n",
   5225   1.1    bouyer 	    DEVNAME(sc), bd->bd_volid, bd->bd_diskid);
   5226   1.1    bouyer 
   5227   1.1    bouyer 	if ((dev = mpii_find_vol(sc, bd->bd_volid)) == NULL)
   5228   1.1    bouyer 		return (ENODEV);
   5229   1.1    bouyer 	volh = dev->dev_handle;
   5230   1.1    bouyer 
   5231   1.1    bouyer 	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
   5232   1.1    bouyer 	    MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0, &hdr) != 0) {
   5233   1.1    bouyer 		printf("%s: unable to fetch header for raid volume page 0\n",
   5234   1.1    bouyer 		    DEVNAME(sc));
   5235   1.1    bouyer 		return (EINVAL);
   5236   1.1    bouyer 	}
   5237   1.1    bouyer 
   5238   1.1    bouyer 	pagelen = hdr.page_length * 4;
   5239  1.12  jdolecek 	vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_ZERO);
   5240   1.1    bouyer 	if (vpg == NULL) {
   5241   1.1    bouyer 		printf("%s: unable to allocate space for raid "
   5242   1.1    bouyer 		    "volume page 0\n", DEVNAME(sc));
   5243   1.1    bouyer 		return (ENOMEM);
   5244   1.1    bouyer 	}
   5245   1.1    bouyer 
   5246   1.1    bouyer 	if (mpii_req_cfg_page(sc, MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0,
   5247   1.1    bouyer 	    &hdr, 1, vpg, pagelen) != 0) {
   5248   1.1    bouyer 		printf("%s: unable to fetch raid volume page 0\n",
   5249   1.1    bouyer 		    DEVNAME(sc));
   5250   1.1    bouyer 		free(vpg, M_TEMP);
   5251   1.1    bouyer 		return (EINVAL);
   5252   1.1    bouyer 	}
   5253   1.1    bouyer 
   5254   1.1    bouyer 	if (bd->bd_diskid >= vpg->num_phys_disks) {
   5255   1.1    bouyer 		int		nvdsk = vpg->num_phys_disks;
   5256   1.1    bouyer 		int		hsmap = vpg->hot_spare_pool;
   5257   1.1    bouyer 
   5258   1.1    bouyer 		free(vpg, M_TEMP);
   5259   1.1    bouyer 		return (mpii_bio_hs(sc, bd, nvdsk, hsmap, NULL));
   5260   1.1    bouyer 	}
   5261   1.1    bouyer 
   5262   1.1    bouyer 	pd = (struct mpii_cfg_raid_vol_pg0_physdisk *)(vpg + 1) +
   5263   1.1    bouyer 	    bd->bd_diskid;
   5264   1.1    bouyer 	dn = pd->phys_disk_num;
   5265   1.1    bouyer 
   5266   1.1    bouyer 	free(vpg, M_TEMP);
   5267   1.1    bouyer 	return (mpii_bio_disk(sc, bd, dn));
   5268   1.1    bouyer }
   5269   1.1    bouyer 
   5270   1.1    bouyer static int
   5271   1.1    bouyer mpii_bio_hs(struct mpii_softc *sc, struct bioc_disk *bd, int nvdsk,
   5272   1.1    bouyer      int hsmap, int *hscnt)
   5273   1.1    bouyer {
   5274   1.1    bouyer 	struct mpii_cfg_raid_config_pg0	*cpg;
   5275   1.1    bouyer 	struct mpii_raid_config_element	*el;
   5276   1.1    bouyer 	struct mpii_ecfg_hdr		ehdr;
   5277   1.1    bouyer 	size_t				pagelen;
   5278   1.1    bouyer 	int				i, nhs = 0;
   5279   1.1    bouyer 
   5280   1.1    bouyer 	if (bd) {
   5281   1.1    bouyer 		DNPRINTF(MPII_D_IOCTL, "%s: mpii_bio_hs %d\n", DEVNAME(sc),
   5282   1.1    bouyer 		    bd->bd_diskid - nvdsk);
   5283   1.1    bouyer 	} else {
   5284   1.1    bouyer 		DNPRINTF(MPII_D_IOCTL, "%s: mpii_bio_hs\n", DEVNAME(sc));
   5285   1.1    bouyer 	}
   5286   1.1    bouyer 
   5287   1.1    bouyer 	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_CONFIG,
   5288   1.1    bouyer 	    0, MPII_CFG_RAID_CONFIG_ACTIVE_CONFIG, MPII_PG_EXTENDED,
   5289   1.1    bouyer 	    &ehdr) != 0) {
   5290   1.1    bouyer 		printf("%s: unable to fetch header for raid config page 0\n",
   5291   1.1    bouyer 		    DEVNAME(sc));
   5292   1.1    bouyer 		return (EINVAL);
   5293   1.1    bouyer 	}
   5294   1.1    bouyer 
   5295   1.1    bouyer 	pagelen = le16toh(ehdr.ext_page_length) * 4;
   5296  1.12  jdolecek 	cpg = malloc(pagelen, M_TEMP, M_WAITOK | M_ZERO);
   5297   1.1    bouyer 	if (cpg == NULL) {
   5298   1.1    bouyer 		printf("%s: unable to allocate space for raid config page 0\n",
   5299   1.1    bouyer 		    DEVNAME(sc));
   5300   1.1    bouyer 		return (ENOMEM);
   5301   1.1    bouyer 	}
   5302   1.1    bouyer 
   5303   1.1    bouyer 	if (mpii_req_cfg_page(sc, MPII_CFG_RAID_CONFIG_ACTIVE_CONFIG,
   5304   1.1    bouyer 	    MPII_PG_EXTENDED, &ehdr, 1, cpg, pagelen) != 0) {
   5305   1.1    bouyer 		printf("%s: unable to fetch raid config page 0\n",
   5306   1.1    bouyer 		    DEVNAME(sc));
   5307   1.1    bouyer 		free(cpg, M_TEMP);
   5308   1.1    bouyer 		return (EINVAL);
   5309   1.1    bouyer 	}
   5310   1.1    bouyer 
   5311   1.1    bouyer 	el = (struct mpii_raid_config_element *)(cpg + 1);
   5312   1.1    bouyer 	for (i = 0; i < cpg->num_elements; i++, el++) {
   5313   1.1    bouyer 		if (ISSET(le16toh(el->element_flags),
   5314   1.1    bouyer 		    MPII_RAID_CONFIG_ELEMENT_FLAG_HSP_PHYS_DISK) &&
   5315   1.1    bouyer 		    el->hot_spare_pool == hsmap) {
   5316   1.1    bouyer 			/*
   5317   1.1    bouyer 			 * diskid comparison is based on the idea that all
   5318   1.1    bouyer 			 * disks are counted by the bio(4) in sequence, thus
   5319   1.1    bouyer 			 * substracting the number of disks in the volume
   5320   1.1    bouyer 			 * from the diskid yields us a "relative" hotspare
   5321   1.1    bouyer 			 * number, which is good enough for us.
   5322   1.1    bouyer 			 */
   5323   1.1    bouyer 			if (bd != NULL && bd->bd_diskid == nhs + nvdsk) {
   5324   1.1    bouyer 				u_int8_t dn = el->phys_disk_num;
   5325   1.1    bouyer 
   5326   1.1    bouyer 				free(cpg, M_TEMP);
   5327   1.1    bouyer 				return (mpii_bio_disk(sc, bd, dn));
   5328   1.1    bouyer 			}
   5329   1.1    bouyer 			nhs++;
   5330   1.1    bouyer 		}
   5331   1.1    bouyer 	}
   5332   1.1    bouyer 
   5333   1.1    bouyer 	if (hscnt)
   5334   1.1    bouyer 		*hscnt = nhs;
   5335   1.1    bouyer 
   5336   1.1    bouyer 	free(cpg, M_TEMP);
   5337   1.1    bouyer 	return (0);
   5338   1.1    bouyer }
   5339   1.1    bouyer 
   5340   1.1    bouyer static int
   5341   1.1    bouyer mpii_bio_disk(struct mpii_softc *sc, struct bioc_disk *bd, u_int8_t dn)
   5342   1.1    bouyer {
   5343   1.1    bouyer 	struct mpii_cfg_raid_physdisk_pg0	*ppg;
   5344   1.1    bouyer 	struct mpii_cfg_hdr			hdr;
   5345   1.1    bouyer 	struct mpii_device			*dev;
   5346   1.1    bouyer 	int					len;
   5347   1.1    bouyer 
   5348   1.1    bouyer 	DNPRINTF(MPII_D_IOCTL, "%s: mpii_bio_disk %d\n", DEVNAME(sc),
   5349   1.1    bouyer 	    bd->bd_diskid);
   5350   1.1    bouyer 
   5351  1.12  jdolecek 	ppg = malloc(sizeof(*ppg), M_TEMP, M_WAITOK | M_ZERO);
   5352   1.1    bouyer 	if (ppg == NULL) {
   5353   1.1    bouyer 		printf("%s: unable to allocate space for raid physical disk "
   5354   1.1    bouyer 		    "page 0\n", DEVNAME(sc));
   5355   1.1    bouyer 		return (ENOMEM);
   5356   1.1    bouyer 	}
   5357   1.1    bouyer 
   5358   1.1    bouyer 	hdr.page_version = 0;
   5359   1.1    bouyer 	hdr.page_length = sizeof(*ppg) / 4;
   5360   1.1    bouyer 	hdr.page_number = 0;
   5361   1.1    bouyer 	hdr.page_type = MPII_CONFIG_REQ_PAGE_TYPE_RAID_PD;
   5362   1.1    bouyer 
   5363   1.1    bouyer 	if (mpii_req_cfg_page(sc, MPII_CFG_RAID_PHYS_DISK_ADDR_NUMBER | dn, 0,
   5364   1.1    bouyer 	    &hdr, 1, ppg, sizeof(*ppg)) != 0) {
   5365   1.1    bouyer 		printf("%s: unable to fetch raid drive page 0\n",
   5366   1.1    bouyer 		    DEVNAME(sc));
   5367   1.1    bouyer 		free(ppg, M_TEMP);
   5368   1.1    bouyer 		return (EINVAL);
   5369   1.1    bouyer 	}
   5370   1.1    bouyer 
   5371   1.1    bouyer 	bd->bd_target = ppg->phys_disk_num;
   5372   1.1    bouyer 
   5373   1.1    bouyer 	if ((dev = mpii_find_dev(sc, le16toh(ppg->dev_handle))) == NULL) {
   5374   1.1    bouyer 		bd->bd_status = BIOC_SDINVALID;
   5375   1.1    bouyer 		free(ppg, M_TEMP);
   5376   1.1    bouyer 		return (0);
   5377   1.1    bouyer 	}
   5378   1.1    bouyer 
   5379   1.1    bouyer 	switch (ppg->phys_disk_state) {
   5380   1.1    bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_ONLINE:
   5381   1.1    bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_OPTIMAL:
   5382   1.1    bouyer 		bd->bd_status = BIOC_SDONLINE;
   5383   1.1    bouyer 		break;
   5384   1.1    bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_OFFLINE:
   5385   1.1    bouyer 		if (ppg->offline_reason ==
   5386   1.1    bouyer 		    MPII_CFG_RAID_PHYDISK_0_OFFLINE_FAILED ||
   5387   1.1    bouyer 		    ppg->offline_reason ==
   5388   1.1    bouyer 		    MPII_CFG_RAID_PHYDISK_0_OFFLINE_FAILEDREQ)
   5389   1.1    bouyer 			bd->bd_status = BIOC_SDFAILED;
   5390   1.1    bouyer 		else
   5391   1.1    bouyer 			bd->bd_status = BIOC_SDOFFLINE;
   5392   1.1    bouyer 		break;
   5393   1.1    bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_DEGRADED:
   5394   1.1    bouyer 		bd->bd_status = BIOC_SDFAILED;
   5395   1.1    bouyer 		break;
   5396   1.1    bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_REBUILDING:
   5397   1.1    bouyer 		bd->bd_status = BIOC_SDREBUILD;
   5398   1.1    bouyer 		break;
   5399   1.1    bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_HOTSPARE:
   5400   1.1    bouyer 		bd->bd_status = BIOC_SDHOTSPARE;
   5401   1.1    bouyer 		break;
   5402   1.1    bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_NOTCONFIGURED:
   5403   1.1    bouyer 		bd->bd_status = BIOC_SDUNUSED;
   5404   1.1    bouyer 		break;
   5405   1.1    bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_NOTCOMPATIBLE:
   5406   1.1    bouyer 	default:
   5407   1.1    bouyer 		bd->bd_status = BIOC_SDINVALID;
   5408   1.1    bouyer 		break;
   5409   1.1    bouyer 	}
   5410   1.1    bouyer 
   5411   1.1    bouyer 	bd->bd_size = le64toh(ppg->dev_max_lba) * le16toh(ppg->block_size);
   5412   1.1    bouyer 
   5413   1.8  christos 	strnvisx(bd->bd_vendor, sizeof(bd->bd_vendor),
   5414   1.8  christos 	    ppg->vendor_id, sizeof(ppg->vendor_id),
   5415   1.8  christos 	    VIS_TRIM|VIS_SAFE|VIS_OCTAL);
   5416   1.1    bouyer 	len = strlen(bd->bd_vendor);
   5417   1.1    bouyer 	bd->bd_vendor[len] = ' ';
   5418   1.8  christos 	strnvisx(&bd->bd_vendor[len + 1], sizeof(ppg->vendor_id) - len - 1,
   5419   1.8  christos 	    ppg->product_id, sizeof(ppg->product_id),
   5420   1.8  christos 	    VIS_TRIM|VIS_SAFE|VIS_OCTAL);
   5421   1.8  christos 	strnvisx(bd->bd_serial, sizeof(bd->bd_serial),
   5422   1.8  christos 	    ppg->serial, sizeof(ppg->serial), VIS_TRIM|VIS_SAFE|VIS_OCTAL);
   5423   1.1    bouyer 
   5424   1.1    bouyer 	free(ppg, M_TEMP);
   5425   1.1    bouyer 	return (0);
   5426   1.1    bouyer }
   5427   1.1    bouyer 
   5428   1.1    bouyer static struct mpii_device *
   5429   1.1    bouyer mpii_find_vol(struct mpii_softc *sc, int volid)
   5430   1.1    bouyer {
   5431   1.1    bouyer 	struct mpii_device	*dev = NULL;
   5432   1.1    bouyer 
   5433   1.1    bouyer 	if (sc->sc_vd_id_low + volid >= sc->sc_max_devices)
   5434   1.1    bouyer 		return (NULL);
   5435   1.1    bouyer 	dev = sc->sc_devs[sc->sc_vd_id_low + volid];
   5436   1.1    bouyer 	if (dev && ISSET(dev->flags, MPII_DF_VOLUME))
   5437   1.1    bouyer 		return (dev);
   5438   1.1    bouyer 	return (NULL);
   5439   1.1    bouyer }
   5440   1.1    bouyer 
   5441   1.1    bouyer /*
   5442   1.1    bouyer  * Non-sleeping lightweight version of the mpii_ioctl_vol
   5443   1.1    bouyer  */
   5444   1.1    bouyer static int
   5445   1.1    bouyer mpii_bio_volstate(struct mpii_softc *sc, struct bioc_vol *bv)
   5446   1.1    bouyer {
   5447   1.1    bouyer 	struct mpii_cfg_raid_vol_pg0	*vpg;
   5448   1.1    bouyer 	struct mpii_cfg_hdr		hdr;
   5449   1.1    bouyer 	struct mpii_device		*dev = NULL;
   5450   1.1    bouyer 	size_t				pagelen;
   5451   1.1    bouyer 	u_int16_t			volh;
   5452   1.1    bouyer 
   5453   1.1    bouyer 	if ((dev = mpii_find_vol(sc, bv->bv_volid)) == NULL)
   5454   1.1    bouyer 		return (ENODEV);
   5455   1.1    bouyer 	volh = dev->dev_handle;
   5456   1.1    bouyer 
   5457   1.1    bouyer 	if (mpii_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
   5458   1.1    bouyer 	    MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, &hdr) != 0) {
   5459   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: unable to fetch header for raid "
   5460   1.1    bouyer 		    "volume page 0\n", DEVNAME(sc));
   5461   1.1    bouyer 		return (EINVAL);
   5462   1.1    bouyer 	}
   5463   1.1    bouyer 
   5464   1.1    bouyer 	pagelen = hdr.page_length * 4;
   5465   1.1    bouyer 	vpg = malloc(pagelen, M_TEMP, M_NOWAIT | M_ZERO);
   5466   1.1    bouyer 	if (vpg == NULL) {
   5467   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: unable to allocate space for raid "
   5468   1.1    bouyer 		    "volume page 0\n", DEVNAME(sc));
   5469   1.1    bouyer 		return (ENOMEM);
   5470   1.1    bouyer 	}
   5471   1.1    bouyer 
   5472   1.1    bouyer 	if (mpii_cfg_page(sc, MPII_CFG_RAID_VOL_ADDR_HANDLE | volh,
   5473   1.1    bouyer 	    &hdr, 1, vpg, pagelen) != 0) {
   5474   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: unable to fetch raid volume "
   5475   1.1    bouyer 		    "page 0\n", DEVNAME(sc));
   5476   1.1    bouyer 		free(vpg, M_TEMP);
   5477   1.1    bouyer 		return (EINVAL);
   5478   1.1    bouyer 	}
   5479   1.1    bouyer 
   5480   1.1    bouyer 	switch (vpg->volume_state) {
   5481   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_ONLINE:
   5482   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_OPTIMAL:
   5483   1.1    bouyer 		bv->bv_status = BIOC_SVONLINE;
   5484   1.1    bouyer 		break;
   5485   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_DEGRADED:
   5486   1.1    bouyer 		if (ISSET(le32toh(vpg->volume_status),
   5487   1.1    bouyer 		    MPII_CFG_RAID_VOL_0_STATUS_RESYNC))
   5488   1.1    bouyer 			bv->bv_status = BIOC_SVREBUILD;
   5489   1.1    bouyer 		else
   5490   1.1    bouyer 			bv->bv_status = BIOC_SVDEGRADED;
   5491   1.1    bouyer 		break;
   5492   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_FAILED:
   5493   1.1    bouyer 		bv->bv_status = BIOC_SVOFFLINE;
   5494   1.1    bouyer 		break;
   5495   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_INITIALIZING:
   5496   1.1    bouyer 		bv->bv_status = BIOC_SVBUILDING;
   5497   1.1    bouyer 		break;
   5498   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_MISSING:
   5499   1.1    bouyer 	default:
   5500   1.1    bouyer 		bv->bv_status = BIOC_SVINVALID;
   5501   1.1    bouyer 		break;
   5502   1.1    bouyer 	}
   5503   1.1    bouyer 
   5504   1.1    bouyer 	free(vpg, M_TEMP);
   5505   1.1    bouyer 	return (0);
   5506   1.1    bouyer }
   5507   1.1    bouyer 
   5508   1.1    bouyer static int
   5509   1.1    bouyer mpii_create_sensors(struct mpii_softc *sc)
   5510   1.1    bouyer {
   5511   1.1    bouyer 	int			i, rv;
   5512   1.1    bouyer 
   5513   1.1    bouyer 	sc->sc_sme = sysmon_envsys_create();
   5514   1.1    bouyer 	sc->sc_sensors = malloc(sizeof(envsys_data_t) * sc->sc_vd_count,
   5515   1.1    bouyer 	    M_DEVBUF, M_NOWAIT | M_ZERO);
   5516   1.1    bouyer 	if (sc->sc_sensors == NULL) {
   5517   1.1    bouyer 		aprint_error_dev(sc->sc_dev,
   5518   1.1    bouyer 		    "can't allocate envsys_data_t\n");
   5519   1.1    bouyer 		return (1);
   5520   1.1    bouyer 	}
   5521   1.1    bouyer 
   5522   1.1    bouyer 	for (i = 0; i < sc->sc_vd_count; i++) {
   5523   1.1    bouyer 		sc->sc_sensors[i].units = ENVSYS_DRIVE;
   5524   1.1    bouyer 		sc->sc_sensors[i].state = ENVSYS_SINVALID;
   5525   1.1    bouyer 		sc->sc_sensors[i].value_cur = ENVSYS_DRIVE_EMPTY;
   5526   1.1    bouyer 		/* Enable monitoring for drive state changes */
   5527   1.1    bouyer 		sc->sc_sensors[i].flags |= ENVSYS_FMONSTCHANGED;
   5528   1.1    bouyer 
   5529   1.1    bouyer 		/* logical drives */
   5530   1.1    bouyer 		snprintf(sc->sc_sensors[i].desc,
   5531   1.1    bouyer 		    sizeof(sc->sc_sensors[i].desc), "%s:%d",
   5532   1.1    bouyer 		    DEVNAME(sc), i);
   5533   1.1    bouyer 		if ((rv = sysmon_envsys_sensor_attach(sc->sc_sme,
   5534   1.1    bouyer 		    &sc->sc_sensors[i])) != 0) {
   5535   1.1    bouyer 			aprint_error_dev(sc->sc_dev,
   5536   1.1    bouyer 			    "unable to attach sensor (rv = %d)\n", rv);
   5537   1.1    bouyer 			goto out;
   5538   1.1    bouyer 		}
   5539   1.1    bouyer 	}
   5540   1.1    bouyer 	sc->sc_sme->sme_name =  DEVNAME(sc);
   5541   1.1    bouyer 	sc->sc_sme->sme_cookie = sc;
   5542   1.1    bouyer 	sc->sc_sme->sme_refresh = mpii_refresh_sensors;
   5543   1.1    bouyer 
   5544   1.1    bouyer 	rv = sysmon_envsys_register(sc->sc_sme);
   5545   1.1    bouyer 
   5546   1.1    bouyer 	if (rv != 0) {
   5547   1.1    bouyer 		aprint_error_dev(sc->sc_dev,
   5548   1.1    bouyer 		    "unable to register with sysmon (rv = %d)\n", rv);
   5549   1.1    bouyer 		goto out;
   5550   1.1    bouyer 	}
   5551   1.1    bouyer 	return 0;
   5552   1.1    bouyer 
   5553   1.1    bouyer out:
   5554   1.1    bouyer 	free(sc->sc_sensors, M_DEVBUF);
   5555   1.1    bouyer 	sysmon_envsys_destroy(sc->sc_sme);
   5556   1.1    bouyer 	sc->sc_sme = NULL;
   5557   1.1    bouyer 	return EINVAL;
   5558   1.1    bouyer }
   5559   1.1    bouyer 
   5560   1.1    bouyer static int
   5561   1.1    bouyer mpii_destroy_sensors(struct mpii_softc *sc)
   5562   1.1    bouyer {
   5563   1.1    bouyer 	if (sc->sc_sme == NULL)
   5564   1.1    bouyer 		return 0;
   5565   1.1    bouyer 	sysmon_envsys_unregister(sc->sc_sme);
   5566   1.1    bouyer 	sc->sc_sme = NULL;
   5567   1.1    bouyer 	free(sc->sc_sensors, M_DEVBUF);
   5568   1.1    bouyer 	return 0;
   5569   1.1    bouyer }
   5570   1.1    bouyer 
   5571   1.1    bouyer static void
   5572   1.1    bouyer mpii_refresh_sensors(struct sysmon_envsys *sme, envsys_data_t *edata)
   5573   1.1    bouyer {
   5574   1.1    bouyer 	struct mpii_softc	*sc = sc = sme->sme_cookie;
   5575   1.1    bouyer 	struct bioc_vol		bv;
   5576   1.1    bouyer 	int			s, error;
   5577   1.1    bouyer 
   5578   1.1    bouyer 	bzero(&bv, sizeof(bv));
   5579   1.1    bouyer 	bv.bv_volid = edata->sensor;
   5580   1.1    bouyer 	KERNEL_LOCK(1, curlwp);
   5581   1.1    bouyer 	s = splbio();
   5582   1.1    bouyer 	error = mpii_bio_volstate(sc, &bv);
   5583   1.1    bouyer 	splx(s);
   5584   1.1    bouyer 	KERNEL_UNLOCK_ONE(curlwp);
   5585   1.1    bouyer 	if (error)
   5586   1.6  christos 		bv.bv_status = BIOC_SVINVALID;
   5587   1.6  christos 	bio_vol_to_envsys(edata, &bv);
   5588   1.1    bouyer }
   5589   1.1    bouyer #endif /* NBIO > 0 */
   5590