Home | History | Annotate | Line # | Download | only in pci
      1  1.32   msaitoh /* $NetBSD: mfii.c,v 1.32 2024/02/13 14:56:52 msaitoh Exp $ */
      2   1.1    bouyer /* $OpenBSD: mfii.c,v 1.58 2018/08/14 05:22:21 jmatthew Exp $ */
      3   1.1    bouyer 
      4   1.1    bouyer /*
      5   1.2    bouyer  * Copyright (c) 2018 Manuel Bouyer <Manuel.Bouyer (at) lip6.fr>
      6   1.1    bouyer  * Copyright (c) 2012 David Gwynne <dlg (at) openbsd.org>
      7   1.1    bouyer  *
      8   1.1    bouyer  * Permission to use, copy, modify, and distribute this software for any
      9   1.1    bouyer  * purpose with or without fee is hereby granted, provided that the above
     10   1.1    bouyer  * copyright notice and this permission notice appear in all copies.
     11   1.1    bouyer  *
     12   1.1    bouyer  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     13   1.1    bouyer  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     14   1.1    bouyer  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     15   1.1    bouyer  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     16   1.1    bouyer  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     17   1.1    bouyer  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     18   1.1    bouyer  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     19   1.1    bouyer  */
     20   1.1    bouyer 
     21   1.1    bouyer #include <sys/cdefs.h>
     22  1.32   msaitoh __KERNEL_RCSID(0, "$NetBSD: mfii.c,v 1.32 2024/02/13 14:56:52 msaitoh Exp $");
     23   1.1    bouyer 
     24   1.1    bouyer #include "bio.h"
     25   1.1    bouyer 
     26   1.1    bouyer #include <sys/atomic.h>
     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/ioctl.h>
     31   1.1    bouyer #include <sys/device.h>
     32   1.1    bouyer #include <sys/kernel.h>
     33   1.1    bouyer #include <sys/proc.h>
     34   1.1    bouyer #include <sys/cpu.h>
     35   1.1    bouyer #include <sys/conf.h>
     36   1.1    bouyer #include <sys/kauth.h>
     37   1.1    bouyer #include <sys/workqueue.h>
     38   1.1    bouyer #include <sys/malloc.h>
     39   1.1    bouyer 
     40   1.1    bouyer #include <uvm/uvm_param.h>
     41   1.1    bouyer 
     42   1.1    bouyer #include <dev/pci/pcidevs.h>
     43   1.1    bouyer #include <dev/pci/pcivar.h>
     44   1.1    bouyer 
     45   1.1    bouyer #include <sys/bus.h>
     46   1.1    bouyer 
     47   1.1    bouyer #include <dev/sysmon/sysmonvar.h>
     48   1.1    bouyer #include <sys/envsys.h>
     49   1.1    bouyer 
     50   1.1    bouyer #include <dev/scsipi/scsipi_all.h>
     51   1.1    bouyer #include <dev/scsipi/scsi_all.h>
     52   1.1    bouyer #include <dev/scsipi/scsi_spc.h>
     53   1.1    bouyer #include <dev/scsipi/scsipi_disk.h>
     54   1.1    bouyer #include <dev/scsipi/scsi_disk.h>
     55   1.1    bouyer #include <dev/scsipi/scsiconf.h>
     56   1.1    bouyer 
     57   1.1    bouyer #if NBIO > 0
     58   1.1    bouyer #include <dev/biovar.h>
     59   1.1    bouyer #endif /* NBIO > 0 */
     60   1.1    bouyer 
     61   1.1    bouyer #include <dev/ic/mfireg.h>
     62   1.1    bouyer #include <dev/pci/mpiireg.h>
     63   1.1    bouyer 
     64   1.1    bouyer #define	MFII_BAR		0x14
     65   1.1    bouyer #define MFII_BAR_35		0x10
     66   1.1    bouyer #define	MFII_PCI_MEMSIZE	0x2000 /* 8k */
     67   1.1    bouyer 
     68   1.1    bouyer #define MFII_OSTS_INTR_VALID	0x00000009
     69   1.1    bouyer #define MFII_RPI		0x6c /* reply post host index */
     70   1.1    bouyer #define MFII_OSP2		0xb4 /* outbound scratch pad 2 */
     71   1.1    bouyer #define MFII_OSP3		0xb8 /* outbound scratch pad 3 */
     72   1.1    bouyer 
     73   1.1    bouyer #define MFII_REQ_TYPE_SCSI	MPII_REQ_DESCR_SCSI_IO
     74   1.1    bouyer #define MFII_REQ_TYPE_LDIO	(0x7 << 1)
     75   1.1    bouyer #define MFII_REQ_TYPE_MFA	(0x1 << 1)
     76   1.1    bouyer #define MFII_REQ_TYPE_NO_LOCK	(0x2 << 1)
     77   1.1    bouyer #define MFII_REQ_TYPE_HI_PRI	(0x6 << 1)
     78   1.1    bouyer 
     79   1.1    bouyer #define MFII_REQ_MFA(_a)	htole64((_a) | MFII_REQ_TYPE_MFA)
     80   1.1    bouyer 
     81   1.1    bouyer #define MFII_FUNCTION_PASSTHRU_IO			(0xf0)
     82   1.1    bouyer #define MFII_FUNCTION_LDIO_REQUEST			(0xf1)
     83   1.1    bouyer 
     84   1.1    bouyer #define MFII_MAX_CHAIN_UNIT	0x00400000
     85   1.1    bouyer #define MFII_MAX_CHAIN_MASK	0x000003E0
     86   1.1    bouyer #define MFII_MAX_CHAIN_SHIFT	5
     87   1.1    bouyer 
     88   1.1    bouyer #define MFII_256K_IO		128
     89   1.1    bouyer #define MFII_1MB_IO		(MFII_256K_IO * 4)
     90   1.1    bouyer 
     91   1.1    bouyer #define MFII_CHAIN_FRAME_MIN	1024
     92   1.1    bouyer 
     93   1.1    bouyer struct mfii_request_descr {
     94   1.1    bouyer 	u_int8_t	flags;
     95   1.1    bouyer 	u_int8_t	msix_index;
     96   1.1    bouyer 	u_int16_t	smid;
     97   1.1    bouyer 
     98   1.1    bouyer 	u_int16_t	lmid;
     99   1.1    bouyer 	u_int16_t	dev_handle;
    100   1.1    bouyer } __packed;
    101   1.1    bouyer 
    102   1.1    bouyer #define MFII_RAID_CTX_IO_TYPE_SYSPD	(0x1 << 4)
    103   1.1    bouyer #define MFII_RAID_CTX_TYPE_CUDA		(0x2 << 4)
    104   1.1    bouyer 
    105   1.1    bouyer struct mfii_raid_context {
    106   1.1    bouyer 	u_int8_t	type_nseg;
    107   1.1    bouyer 	u_int8_t	_reserved1;
    108   1.1    bouyer 	u_int16_t	timeout_value;
    109   1.1    bouyer 
    110   1.1    bouyer 	u_int16_t	reg_lock_flags;
    111   1.1    bouyer #define MFII_RAID_CTX_RL_FLAGS_SEQNO_EN	(0x08)
    112   1.1    bouyer #define MFII_RAID_CTX_RL_FLAGS_CPU0	(0x00)
    113   1.1    bouyer #define MFII_RAID_CTX_RL_FLAGS_CPU1	(0x10)
    114   1.1    bouyer #define MFII_RAID_CTX_RL_FLAGS_CUDA	(0x80)
    115   1.1    bouyer 
    116   1.1    bouyer #define MFII_RAID_CTX_ROUTING_FLAGS_SQN	(1 << 4)
    117   1.1    bouyer #define MFII_RAID_CTX_ROUTING_FLAGS_CPU0 0
    118   1.1    bouyer 	u_int16_t	virtual_disk_target_id;
    119   1.1    bouyer 
    120   1.1    bouyer 	u_int64_t	reg_lock_row_lba;
    121   1.1    bouyer 
    122   1.1    bouyer 	u_int32_t	reg_lock_length;
    123   1.1    bouyer 
    124   1.1    bouyer 	u_int16_t	next_lm_id;
    125   1.1    bouyer 	u_int8_t	ex_status;
    126   1.1    bouyer 	u_int8_t	status;
    127   1.1    bouyer 
    128   1.1    bouyer 	u_int8_t	raid_flags;
    129   1.1    bouyer 	u_int8_t	num_sge;
    130   1.1    bouyer 	u_int16_t	config_seq_num;
    131   1.1    bouyer 
    132   1.1    bouyer 	u_int8_t	span_arm;
    133   1.1    bouyer 	u_int8_t	_reserved3[3];
    134   1.1    bouyer } __packed;
    135   1.1    bouyer 
    136   1.1    bouyer struct mfii_sge {
    137   1.1    bouyer 	u_int64_t	sg_addr;
    138   1.1    bouyer 	u_int32_t	sg_len;
    139   1.1    bouyer 	u_int16_t	_reserved;
    140   1.1    bouyer 	u_int8_t	sg_next_chain_offset;
    141   1.1    bouyer 	u_int8_t	sg_flags;
    142   1.1    bouyer } __packed;
    143   1.1    bouyer 
    144   1.1    bouyer #define MFII_SGE_ADDR_MASK		(0x03)
    145   1.1    bouyer #define MFII_SGE_ADDR_SYSTEM		(0x00)
    146   1.1    bouyer #define MFII_SGE_ADDR_IOCDDR		(0x01)
    147   1.1    bouyer #define MFII_SGE_ADDR_IOCPLB		(0x02)
    148   1.1    bouyer #define MFII_SGE_ADDR_IOCPLBNTA		(0x03)
    149   1.1    bouyer #define MFII_SGE_END_OF_LIST		(0x40)
    150   1.1    bouyer #define MFII_SGE_CHAIN_ELEMENT		(0x80)
    151   1.1    bouyer 
    152   1.1    bouyer #define MFII_REQUEST_SIZE	256
    153   1.1    bouyer 
    154   1.1    bouyer #define MR_DCMD_LD_MAP_GET_INFO			0x0300e101
    155   1.1    bouyer 
    156   1.1    bouyer #define MFII_MAX_ROW		32
    157   1.1    bouyer #define MFII_MAX_ARRAY		128
    158   1.1    bouyer 
    159   1.1    bouyer struct mfii_array_map {
    160   1.1    bouyer 	uint16_t		mam_pd[MFII_MAX_ROW];
    161   1.1    bouyer } __packed;
    162   1.1    bouyer 
    163   1.1    bouyer struct mfii_dev_handle {
    164   1.1    bouyer 	uint16_t		mdh_cur_handle;
    165   1.1    bouyer 	uint8_t			mdh_valid;
    166   1.1    bouyer 	uint8_t			mdh_reserved;
    167   1.1    bouyer 	uint16_t		mdh_handle[2];
    168   1.1    bouyer } __packed;
    169   1.1    bouyer 
    170   1.1    bouyer struct mfii_ld_map {
    171   1.1    bouyer 	uint32_t		mlm_total_size;
    172   1.1    bouyer 	uint32_t		mlm_reserved1[5];
    173   1.1    bouyer 	uint32_t		mlm_num_lds;
    174   1.1    bouyer 	uint32_t		mlm_reserved2;
    175   1.1    bouyer 	uint8_t			mlm_tgtid_to_ld[2 * MFI_MAX_LD];
    176   1.1    bouyer 	uint8_t			mlm_pd_timeout;
    177   1.1    bouyer 	uint8_t			mlm_reserved3[7];
    178   1.1    bouyer 	struct mfii_array_map	mlm_am[MFII_MAX_ARRAY];
    179   1.1    bouyer 	struct mfii_dev_handle	mlm_dev_handle[MFI_MAX_PD];
    180   1.1    bouyer } __packed;
    181   1.1    bouyer 
    182   1.1    bouyer struct mfii_task_mgmt {
    183   1.1    bouyer 	union {
    184   1.1    bouyer 		uint8_t			request[128];
    185   1.1    bouyer 		struct mpii_msg_scsi_task_request
    186   1.1    bouyer 					mpii_request;
    187   1.1    bouyer 	} __packed __aligned(8);
    188   1.1    bouyer 
    189   1.1    bouyer 	union {
    190   1.1    bouyer 		uint8_t			reply[128];
    191   1.1    bouyer 		uint32_t		flags;
    192   1.1    bouyer #define MFII_TASK_MGMT_FLAGS_LD				(1 << 0)
    193   1.1    bouyer #define MFII_TASK_MGMT_FLAGS_PD				(1 << 1)
    194   1.1    bouyer 		struct mpii_msg_scsi_task_reply
    195   1.1    bouyer 					mpii_reply;
    196   1.1    bouyer 	} __packed __aligned(8);
    197   1.1    bouyer } __packed __aligned(8);
    198   1.1    bouyer 
    199   1.1    bouyer /* We currently don't know the full details of the following struct */
    200   1.1    bouyer struct mfii_foreign_scan_cfg {
    201  1.10   msaitoh 	char data[24];
    202  1.10   msaitoh } __packed;
    203   1.1    bouyer 
    204   1.1    bouyer struct mfii_foreign_scan_info {
    205   1.1    bouyer 	uint32_t count; /* Number of foreign configs found */
    206   1.1    bouyer 	struct mfii_foreign_scan_cfg cfgs[8];
    207   1.1    bouyer } __packed;
    208   1.1    bouyer 
    209  1.24   msaitoh #define MFII_MAX_LD_EXT		256
    210  1.24   msaitoh 
    211  1.24   msaitoh struct mfii_ld_list_ext {
    212  1.24   msaitoh 	uint32_t		mll_no_ld;
    213  1.24   msaitoh 	uint32_t		mll_res;
    214  1.24   msaitoh 	struct {
    215  1.24   msaitoh 		struct mfi_ld	mll_ld;
    216  1.24   msaitoh 		uint8_t		mll_state; /* states are the same as MFI_ */
    217  1.24   msaitoh 		uint8_t		mll_res2;
    218  1.24   msaitoh 		uint8_t		mll_res3;
    219  1.24   msaitoh 		uint8_t		mll_res4;
    220  1.24   msaitoh 		uint64_t	mll_size;
    221  1.24   msaitoh 	} mll_list[MFII_MAX_LD_EXT];
    222  1.24   msaitoh } __packed;
    223  1.24   msaitoh 
    224   1.1    bouyer struct mfii_dmamem {
    225   1.1    bouyer 	bus_dmamap_t		mdm_map;
    226   1.1    bouyer 	bus_dma_segment_t	mdm_seg;
    227   1.1    bouyer 	size_t			mdm_size;
    228   1.1    bouyer 	void *			mdm_kva;
    229   1.1    bouyer };
    230   1.1    bouyer #define MFII_DMA_MAP(_mdm)	((_mdm)->mdm_map)
    231   1.1    bouyer #define MFII_DMA_LEN(_mdm)	((_mdm)->mdm_size)
    232   1.1    bouyer #define MFII_DMA_DVA(_mdm)	((u_int64_t)(_mdm)->mdm_map->dm_segs[0].ds_addr)
    233   1.1    bouyer #define MFII_DMA_KVA(_mdm)	((void *)(_mdm)->mdm_kva)
    234   1.1    bouyer 
    235   1.1    bouyer struct mfii_softc;
    236   1.1    bouyer 
    237   1.1    bouyer typedef enum mfii_direction {
    238   1.1    bouyer 	MFII_DATA_NONE = 0,
    239   1.1    bouyer 	MFII_DATA_IN,
    240   1.1    bouyer 	MFII_DATA_OUT
    241   1.1    bouyer } mfii_direction_t;
    242   1.1    bouyer 
    243   1.1    bouyer struct mfii_ccb {
    244   1.1    bouyer 	struct mfii_softc	*ccb_sc;
    245   1.1    bouyer 	void			*ccb_request;
    246   1.1    bouyer 	u_int64_t		ccb_request_dva;
    247   1.1    bouyer 	bus_addr_t		ccb_request_offset;
    248   1.1    bouyer 
    249   1.1    bouyer 	void			*ccb_mfi;
    250   1.1    bouyer 	u_int64_t		ccb_mfi_dva;
    251   1.1    bouyer 	bus_addr_t		ccb_mfi_offset;
    252   1.1    bouyer 
    253   1.1    bouyer 	struct mfi_sense	*ccb_sense;
    254   1.1    bouyer 	u_int64_t		ccb_sense_dva;
    255   1.1    bouyer 	bus_addr_t		ccb_sense_offset;
    256   1.1    bouyer 
    257   1.1    bouyer 	struct mfii_sge		*ccb_sgl;
    258   1.1    bouyer 	u_int64_t		ccb_sgl_dva;
    259   1.1    bouyer 	bus_addr_t		ccb_sgl_offset;
    260   1.1    bouyer 	u_int			ccb_sgl_len;
    261   1.1    bouyer 
    262   1.1    bouyer 	struct mfii_request_descr ccb_req;
    263   1.1    bouyer 
    264   1.1    bouyer 	bus_dmamap_t		ccb_dmamap64;
    265   1.1    bouyer 	bus_dmamap_t		ccb_dmamap32;
    266   1.1    bouyer 	bool			ccb_dma64;
    267   1.1    bouyer 
    268   1.1    bouyer 	/* data for sgl */
    269   1.1    bouyer 	void			*ccb_data;
    270   1.1    bouyer 	size_t			ccb_len;
    271   1.1    bouyer 
    272   1.1    bouyer 	mfii_direction_t	ccb_direction;
    273   1.1    bouyer 
    274   1.1    bouyer 	void			*ccb_cookie;
    275   1.1    bouyer 	kmutex_t		ccb_mtx;
    276   1.1    bouyer 	kcondvar_t		ccb_cv;
    277   1.1    bouyer 	void			(*ccb_done)(struct mfii_softc *,
    278   1.1    bouyer 				    struct mfii_ccb *);
    279   1.1    bouyer 
    280   1.1    bouyer 	u_int32_t		ccb_flags;
    281   1.1    bouyer #define MFI_CCB_F_ERR			(1<<0)
    282   1.1    bouyer 	u_int			ccb_smid;
    283   1.1    bouyer 	SIMPLEQ_ENTRY(mfii_ccb)	ccb_link;
    284   1.1    bouyer };
    285   1.1    bouyer SIMPLEQ_HEAD(mfii_ccb_list, mfii_ccb);
    286   1.1    bouyer 
    287   1.1    bouyer struct mfii_iop {
    288   1.1    bouyer 	int bar;
    289   1.1    bouyer 	int num_sge_loc;
    290   1.1    bouyer #define MFII_IOP_NUM_SGE_LOC_ORIG	0
    291   1.1    bouyer #define MFII_IOP_NUM_SGE_LOC_35		1
    292   1.1    bouyer 	u_int16_t ldio_ctx_reg_lock_flags;
    293   1.1    bouyer 	u_int8_t ldio_req_type;
    294   1.1    bouyer 	u_int8_t ldio_ctx_type_nseg;
    295   1.1    bouyer 	u_int8_t sge_flag_chain;
    296   1.1    bouyer 	u_int8_t sge_flag_eol;
    297  1.23   msaitoh 	u_int8_t iop_flag;
    298  1.23   msaitoh #define MFII_IOP_QUIRK_REGREAD		0x01
    299  1.23   msaitoh #define MFII_IOP_HAS_32BITDESC_BIT	0x02
    300   1.1    bouyer };
    301   1.1    bouyer 
    302   1.1    bouyer struct mfii_softc {
    303   1.1    bouyer 	device_t		sc_dev;
    304   1.1    bouyer 	struct scsipi_channel   sc_chan;
    305   1.1    bouyer 	struct scsipi_adapter   sc_adapt;
    306   1.1    bouyer 
    307   1.1    bouyer 	const struct mfii_iop	*sc_iop;
    308  1.23   msaitoh 	u_int			sc_iop_flag;
    309  1.23   msaitoh #define MFII_IOP_DESC_32BIT		0x01
    310   1.1    bouyer 
    311   1.1    bouyer 	pci_chipset_tag_t	sc_pc;
    312   1.1    bouyer 	pcitag_t		sc_tag;
    313   1.1    bouyer 
    314   1.1    bouyer 	bus_space_tag_t		sc_iot;
    315   1.1    bouyer 	bus_space_handle_t	sc_ioh;
    316   1.1    bouyer 	bus_size_t		sc_ios;
    317   1.1    bouyer 	bus_dma_tag_t		sc_dmat;
    318   1.1    bouyer 	bus_dma_tag_t		sc_dmat64;
    319   1.1    bouyer 	bool			sc_64bit_dma;
    320   1.1    bouyer 
    321   1.1    bouyer 	void			*sc_ih;
    322   1.1    bouyer 
    323   1.1    bouyer 	kmutex_t		sc_ccb_mtx;
    324   1.1    bouyer 	kmutex_t		sc_post_mtx;
    325   1.1    bouyer 
    326   1.1    bouyer 	u_int			sc_max_fw_cmds;
    327   1.1    bouyer 	u_int			sc_max_cmds;
    328   1.1    bouyer 	u_int			sc_max_sgl;
    329   1.1    bouyer 
    330   1.1    bouyer 	u_int			sc_reply_postq_depth;
    331   1.1    bouyer 	u_int			sc_reply_postq_index;
    332   1.1    bouyer 	kmutex_t		sc_reply_postq_mtx;
    333   1.1    bouyer 	struct mfii_dmamem	*sc_reply_postq;
    334   1.1    bouyer 
    335   1.1    bouyer 	struct mfii_dmamem	*sc_requests;
    336   1.1    bouyer 	struct mfii_dmamem	*sc_mfi;
    337   1.1    bouyer 	struct mfii_dmamem	*sc_sense;
    338   1.1    bouyer 	struct mfii_dmamem	*sc_sgl;
    339   1.1    bouyer 
    340   1.1    bouyer 	struct mfii_ccb		*sc_ccb;
    341   1.1    bouyer 	struct mfii_ccb_list	sc_ccb_freeq;
    342   1.1    bouyer 
    343   1.1    bouyer 	struct mfii_ccb		*sc_aen_ccb;
    344   1.1    bouyer 	struct workqueue	*sc_aen_wq;
    345   1.1    bouyer 	struct work		sc_aen_work;
    346   1.1    bouyer 
    347   1.1    bouyer 	kmutex_t		sc_abort_mtx;
    348   1.1    bouyer 	struct mfii_ccb_list	sc_abort_list;
    349   1.1    bouyer 	struct workqueue	*sc_abort_wq;
    350   1.1    bouyer 	struct work		sc_abort_work;
    351   1.1    bouyer 
    352   1.1    bouyer 	/* save some useful information for logical drives that is missing
    353   1.1    bouyer 	 * in sc_ld_list
    354   1.1    bouyer 	 */
    355   1.1    bouyer 	struct {
    356   1.1    bouyer 		bool		ld_present;
    357   1.1    bouyer 		char		ld_dev[16];	/* device name sd? */
    358  1.25   msaitoh 		int		ld_target_id;
    359  1.24   msaitoh 	}			sc_ld[MFII_MAX_LD_EXT];
    360  1.24   msaitoh 	int			sc_target_lds[MFII_MAX_LD_EXT];
    361  1.24   msaitoh 	bool			sc_max256vd;
    362   1.1    bouyer 
    363   1.1    bouyer 	/* bio */
    364  1.15   msaitoh 	struct mfi_conf		*sc_cfg;
    365  1.15   msaitoh 	struct mfi_ctrl_info	sc_info;
    366  1.24   msaitoh 	struct mfii_ld_list_ext	sc_ld_list;
    367   1.1    bouyer 	struct mfi_ld_details	*sc_ld_details; /* array to all logical disks */
    368   1.1    bouyer 	int			sc_no_pd; /* used physical disks */
    369   1.1    bouyer 	int			sc_ld_sz; /* sizeof sc_ld_details */
    370   1.1    bouyer 
    371   1.1    bouyer 	/* mgmt lock */
    372   1.1    bouyer 	kmutex_t		sc_lock;
    373   1.1    bouyer 	bool			sc_running;
    374   1.1    bouyer 
    375   1.1    bouyer 	/* sensors */
    376   1.1    bouyer 	struct sysmon_envsys	*sc_sme;
    377   1.1    bouyer 	envsys_data_t		*sc_sensors;
    378  1.31  christos 	envsys_data_t		*sc_ld_sensors;
    379   1.1    bouyer 	bool			sc_bbuok;
    380   1.1    bouyer 
    381   1.1    bouyer 	device_t		sc_child;
    382   1.1    bouyer };
    383   1.1    bouyer 
    384   1.1    bouyer // #define MFII_DEBUG
    385   1.1    bouyer #ifdef MFII_DEBUG
    386   1.1    bouyer #define DPRINTF(x...)		do { if (mfii_debug) printf(x); } while(0)
    387   1.1    bouyer #define DNPRINTF(n,x...)	do { if (mfii_debug & n) printf(x); } while(0)
    388   1.1    bouyer #define	MFII_D_CMD		0x0001
    389   1.1    bouyer #define	MFII_D_INTR		0x0002
    390   1.1    bouyer #define	MFII_D_MISC		0x0004
    391   1.1    bouyer #define	MFII_D_DMA		0x0008
    392   1.1    bouyer #define	MFII_D_IOCTL		0x0010
    393   1.1    bouyer #define	MFII_D_RW		0x0020
    394   1.1    bouyer #define	MFII_D_MEM		0x0040
    395   1.1    bouyer #define	MFII_D_CCB		0x0080
    396   1.1    bouyer uint32_t	mfii_debug = 0
    397   1.1    bouyer /*		    | MFII_D_CMD */
    398   1.1    bouyer /*		    | MFII_D_INTR */
    399  1.10   msaitoh 		    | MFII_D_MISC
    400   1.1    bouyer /*		    | MFII_D_DMA */
    401   1.1    bouyer /*		    | MFII_D_IOCTL */
    402   1.1    bouyer /*		    | MFII_D_RW */
    403   1.1    bouyer /*		    | MFII_D_MEM */
    404   1.1    bouyer /*		    | MFII_D_CCB */
    405   1.1    bouyer 		;
    406   1.1    bouyer #else
    407   1.1    bouyer #define DPRINTF(x...)
    408   1.1    bouyer #define DNPRINTF(n,x...)
    409   1.1    bouyer #endif
    410   1.1    bouyer 
    411   1.6      maxv static int	mfii_match(device_t, cfdata_t, void *);
    412   1.6      maxv static void	mfii_attach(device_t, device_t, void *);
    413   1.6      maxv static int	mfii_detach(device_t, int);
    414   1.6      maxv static int	mfii_rescan(device_t, const char *, const int *);
    415   1.6      maxv static void	mfii_childdetached(device_t, device_t);
    416   1.1    bouyer static bool	mfii_suspend(device_t, const pmf_qual_t *);
    417   1.1    bouyer static bool	mfii_resume(device_t, const pmf_qual_t *);
    418   1.1    bouyer static bool	mfii_shutdown(device_t, int);
    419   1.1    bouyer 
    420   1.1    bouyer 
    421   1.1    bouyer CFATTACH_DECL3_NEW(mfii, sizeof(struct mfii_softc),
    422   1.1    bouyer     mfii_match, mfii_attach, mfii_detach, NULL, mfii_rescan,
    423   1.1    bouyer 	mfii_childdetached, DVF_DETACH_SHUTDOWN);
    424   1.1    bouyer 
    425   1.6      maxv static void	mfii_scsipi_request(struct scsipi_channel *,
    426   1.1    bouyer 			scsipi_adapter_req_t, void *);
    427   1.6      maxv static void	mfii_scsi_cmd_done(struct mfii_softc *, struct mfii_ccb *);
    428   1.1    bouyer 
    429   1.1    bouyer #define DEVNAME(_sc)		(device_xname((_sc)->sc_dev))
    430   1.1    bouyer 
    431   1.1    bouyer static u_int32_t	mfii_read(struct mfii_softc *, bus_size_t);
    432   1.1    bouyer static void		mfii_write(struct mfii_softc *, bus_size_t, u_int32_t);
    433   1.1    bouyer 
    434   1.6      maxv static struct mfii_dmamem *	mfii_dmamem_alloc(struct mfii_softc *, size_t);
    435   1.6      maxv static void		mfii_dmamem_free(struct mfii_softc *,
    436   1.1    bouyer 			    struct mfii_dmamem *);
    437   1.1    bouyer 
    438   1.6      maxv static struct mfii_ccb *	mfii_get_ccb(struct mfii_softc *);
    439   1.6      maxv static void		mfii_put_ccb(struct mfii_softc *, struct mfii_ccb *);
    440   1.6      maxv static int		mfii_init_ccb(struct mfii_softc *);
    441   1.6      maxv static void		mfii_scrub_ccb(struct mfii_ccb *);
    442   1.6      maxv 
    443  1.32   msaitoh static int		mfii_reset_hard(struct mfii_softc *);
    444   1.6      maxv static int		mfii_transition_firmware(struct mfii_softc *);
    445   1.6      maxv static int		mfii_initialise_firmware(struct mfii_softc *);
    446   1.6      maxv static int		mfii_get_info(struct mfii_softc *);
    447   1.6      maxv 
    448   1.6      maxv static void		mfii_start(struct mfii_softc *, struct mfii_ccb *);
    449  1.23   msaitoh static void		mfii_start64(struct mfii_softc *, struct mfii_ccb *);
    450  1.23   msaitoh static void		mfii_start_common(struct mfii_softc *,
    451  1.23   msaitoh 			    struct mfii_ccb *, bool);
    452   1.6      maxv static void		mfii_done(struct mfii_softc *, struct mfii_ccb *);
    453   1.6      maxv static int		mfii_poll(struct mfii_softc *, struct mfii_ccb *);
    454   1.6      maxv static void		mfii_poll_done(struct mfii_softc *, struct mfii_ccb *);
    455   1.6      maxv static int		mfii_exec(struct mfii_softc *, struct mfii_ccb *);
    456   1.6      maxv static void		mfii_exec_done(struct mfii_softc *, struct mfii_ccb *);
    457   1.6      maxv static int		mfii_my_intr(struct mfii_softc *);
    458   1.6      maxv static int		mfii_intr(void *);
    459   1.6      maxv static void		mfii_postq(struct mfii_softc *);
    460   1.1    bouyer 
    461   1.6      maxv static int		mfii_load_ccb(struct mfii_softc *, struct mfii_ccb *,
    462   1.1    bouyer 			    void *, int);
    463   1.6      maxv static int		mfii_load_mfa(struct mfii_softc *, struct mfii_ccb *,
    464   1.1    bouyer 			    void *, int);
    465   1.1    bouyer 
    466   1.6      maxv static int		mfii_mfa_poll(struct mfii_softc *, struct mfii_ccb *);
    467   1.1    bouyer 
    468   1.6      maxv static int		mfii_mgmt(struct mfii_softc *, uint32_t,
    469   1.1    bouyer 			    const union mfi_mbox *, void *, size_t,
    470   1.1    bouyer 			    mfii_direction_t, bool);
    471   1.6      maxv static int		mfii_do_mgmt(struct mfii_softc *, struct mfii_ccb *,
    472   1.1    bouyer 			    uint32_t, const union mfi_mbox *, void *, size_t,
    473   1.1    bouyer 			    mfii_direction_t, bool);
    474   1.6      maxv static void		mfii_empty_done(struct mfii_softc *, struct mfii_ccb *);
    475   1.1    bouyer 
    476   1.6      maxv static int		mfii_scsi_cmd_io(struct mfii_softc *,
    477   1.1    bouyer 			    struct mfii_ccb *, struct scsipi_xfer *);
    478   1.6      maxv static int		mfii_scsi_cmd_cdb(struct mfii_softc *,
    479   1.1    bouyer 			    struct mfii_ccb *, struct scsipi_xfer *);
    480   1.6      maxv static void		mfii_scsi_cmd_tmo(void *);
    481   1.1    bouyer 
    482   1.6      maxv static void		mfii_abort_task(struct work *, void *);
    483   1.6      maxv static void		mfii_abort(struct mfii_softc *, struct mfii_ccb *,
    484   1.1    bouyer 			    uint16_t, uint16_t, uint8_t, uint32_t);
    485   1.6      maxv static void		mfii_scsi_cmd_abort_done(struct mfii_softc *,
    486   1.1    bouyer 			    struct mfii_ccb *);
    487   1.1    bouyer 
    488   1.6      maxv static int		mfii_aen_register(struct mfii_softc *);
    489   1.6      maxv static void		mfii_aen_start(struct mfii_softc *, struct mfii_ccb *,
    490   1.1    bouyer 			    struct mfii_dmamem *, uint32_t);
    491   1.6      maxv static void		mfii_aen_done(struct mfii_softc *, struct mfii_ccb *);
    492   1.6      maxv static void		mfii_aen(struct work *, void *);
    493   1.6      maxv static void		mfii_aen_unregister(struct mfii_softc *);
    494   1.1    bouyer 
    495   1.6      maxv static void		mfii_aen_pd_insert(struct mfii_softc *,
    496   1.1    bouyer 			    const struct mfi_evtarg_pd_address *);
    497   1.6      maxv static void		mfii_aen_pd_remove(struct mfii_softc *,
    498   1.1    bouyer 			    const struct mfi_evtarg_pd_address *);
    499   1.6      maxv static void		mfii_aen_pd_state_change(struct mfii_softc *,
    500   1.1    bouyer 			    const struct mfi_evtarg_pd_state *);
    501   1.6      maxv static void		mfii_aen_ld_update(struct mfii_softc *);
    502   1.1    bouyer 
    503   1.1    bouyer #if NBIO > 0
    504   1.6      maxv static int	mfii_ioctl(device_t, u_long, void *);
    505   1.6      maxv static int	mfii_ioctl_inq(struct mfii_softc *, struct bioc_inq *);
    506   1.6      maxv static int	mfii_ioctl_vol(struct mfii_softc *, struct bioc_vol *);
    507   1.6      maxv static int	mfii_ioctl_disk(struct mfii_softc *, struct bioc_disk *);
    508   1.6      maxv static int	mfii_ioctl_alarm(struct mfii_softc *, struct bioc_alarm *);
    509   1.6      maxv static int	mfii_ioctl_blink(struct mfii_softc *sc, struct bioc_blink *);
    510   1.6      maxv static int	mfii_ioctl_setstate(struct mfii_softc *,
    511   1.1    bouyer 		    struct bioc_setstate *);
    512   1.6      maxv static int	mfii_bio_hs(struct mfii_softc *, int, int, void *);
    513   1.6      maxv static int	mfii_bio_getitall(struct mfii_softc *);
    514   1.1    bouyer #endif /* NBIO > 0 */
    515   1.1    bouyer 
    516   1.1    bouyer #if 0
    517   1.1    bouyer static const char *mfi_bbu_indicators[] = {
    518   1.1    bouyer 	"pack missing",
    519   1.1    bouyer 	"voltage low",
    520   1.1    bouyer 	"temp high",
    521   1.1    bouyer 	"charge active",
    522   1.1    bouyer 	"discharge active",
    523   1.1    bouyer 	"learn cycle req'd",
    524   1.1    bouyer 	"learn cycle active",
    525   1.1    bouyer 	"learn cycle failed",
    526   1.1    bouyer 	"learn cycle timeout",
    527   1.1    bouyer 	"I2C errors",
    528   1.1    bouyer 	"replace pack",
    529   1.1    bouyer 	"low capacity",
    530   1.1    bouyer 	"periodic learn req'd"
    531   1.1    bouyer };
    532   1.1    bouyer #endif
    533   1.1    bouyer 
    534  1.30  christos #define MFI_BBU_SENSORS 4
    535  1.30  christos 
    536   1.6      maxv static void	mfii_init_ld_sensor(struct mfii_softc *, envsys_data_t *, int);
    537   1.6      maxv static void	mfii_refresh_ld_sensor(struct mfii_softc *, envsys_data_t *);
    538   1.1    bouyer static void	mfii_attach_sensor(struct mfii_softc *, envsys_data_t *);
    539   1.6      maxv static int	mfii_create_sensors(struct mfii_softc *);
    540   1.1    bouyer static int	mfii_destroy_sensors(struct mfii_softc *);
    541   1.6      maxv static void	mfii_refresh_sensor(struct sysmon_envsys *, envsys_data_t *);
    542   1.6      maxv static void	mfii_bbu(struct mfii_softc *, envsys_data_t *);
    543   1.1    bouyer 
    544   1.1    bouyer /*
    545   1.1    bouyer  * mfii boards support asynchronous (and non-polled) completion of
    546   1.1    bouyer  * dcmds by proxying them through a passthru mpii command that points
    547   1.1    bouyer  * at a dcmd frame. since the passthru command is submitted like
    548   1.1    bouyer  * the scsi commands using an SMID in the request descriptor,
    549   1.1    bouyer  * ccb_request memory * must contain the passthru command because
    550   1.1    bouyer  * that is what the SMID refers to. this means ccb_request cannot
    551   1.1    bouyer  * contain the dcmd. rather than allocating separate dma memory to
    552   1.1    bouyer  * hold the dcmd, we reuse the sense memory buffer for it.
    553   1.1    bouyer  */
    554   1.1    bouyer 
    555   1.6      maxv static void	mfii_dcmd_start(struct mfii_softc *, struct mfii_ccb *);
    556   1.1    bouyer 
    557   1.1    bouyer static inline void
    558   1.1    bouyer mfii_dcmd_scrub(struct mfii_ccb *ccb)
    559   1.1    bouyer {
    560   1.1    bouyer 	memset(ccb->ccb_sense, 0, sizeof(*ccb->ccb_sense));
    561   1.1    bouyer }
    562   1.1    bouyer 
    563   1.1    bouyer static inline struct mfi_dcmd_frame *
    564   1.1    bouyer mfii_dcmd_frame(struct mfii_ccb *ccb)
    565   1.1    bouyer {
    566   1.1    bouyer 	CTASSERT(sizeof(struct mfi_dcmd_frame) <= sizeof(*ccb->ccb_sense));
    567   1.1    bouyer 	return ((struct mfi_dcmd_frame *)ccb->ccb_sense);
    568   1.1    bouyer }
    569   1.1    bouyer 
    570   1.1    bouyer static inline void
    571   1.1    bouyer mfii_dcmd_sync(struct mfii_softc *sc, struct mfii_ccb *ccb, int flags)
    572   1.1    bouyer {
    573   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_sense),
    574   1.1    bouyer 	    ccb->ccb_sense_offset, sizeof(*ccb->ccb_sense), flags);
    575   1.1    bouyer }
    576   1.1    bouyer 
    577   1.1    bouyer #define mfii_fw_state(_sc) mfii_read((_sc), MFI_OSP)
    578   1.1    bouyer 
    579   1.6      maxv static const struct mfii_iop mfii_iop_thunderbolt = {
    580   1.1    bouyer 	MFII_BAR,
    581   1.1    bouyer 	MFII_IOP_NUM_SGE_LOC_ORIG,
    582   1.1    bouyer 	0,
    583   1.1    bouyer 	MFII_REQ_TYPE_LDIO,
    584   1.1    bouyer 	0,
    585   1.1    bouyer 	MFII_SGE_CHAIN_ELEMENT | MFII_SGE_ADDR_IOCPLBNTA,
    586  1.23   msaitoh 	0,
    587   1.1    bouyer 	0
    588   1.1    bouyer };
    589   1.1    bouyer 
    590   1.1    bouyer /*
    591   1.1    bouyer  * a lot of these values depend on us not implementing fastpath yet.
    592   1.1    bouyer  */
    593   1.6      maxv static const struct mfii_iop mfii_iop_25 = {
    594   1.1    bouyer 	MFII_BAR,
    595   1.1    bouyer 	MFII_IOP_NUM_SGE_LOC_ORIG,
    596   1.1    bouyer 	MFII_RAID_CTX_RL_FLAGS_CPU0, /* | MFII_RAID_CTX_RL_FLAGS_SEQNO_EN */
    597   1.1    bouyer 	MFII_REQ_TYPE_NO_LOCK,
    598   1.1    bouyer 	MFII_RAID_CTX_TYPE_CUDA | 0x1,
    599   1.1    bouyer 	MFII_SGE_CHAIN_ELEMENT,
    600  1.23   msaitoh 	MFII_SGE_END_OF_LIST,
    601  1.23   msaitoh 	0
    602   1.1    bouyer };
    603   1.1    bouyer 
    604   1.6      maxv static const struct mfii_iop mfii_iop_35 = {
    605   1.1    bouyer 	MFII_BAR_35,
    606   1.1    bouyer 	MFII_IOP_NUM_SGE_LOC_35,
    607   1.1    bouyer 	MFII_RAID_CTX_ROUTING_FLAGS_CPU0, /* | MFII_RAID_CTX_ROUTING_FLAGS_SQN */
    608   1.1    bouyer 	MFII_REQ_TYPE_NO_LOCK,
    609   1.1    bouyer 	MFII_RAID_CTX_TYPE_CUDA | 0x1,
    610   1.1    bouyer 	MFII_SGE_CHAIN_ELEMENT,
    611  1.23   msaitoh 	MFII_SGE_END_OF_LIST,
    612  1.23   msaitoh 	0
    613   1.1    bouyer };
    614   1.1    bouyer 
    615  1.23   msaitoh static const struct mfii_iop mfii_iop_aero = {
    616  1.23   msaitoh 	MFII_BAR_35,
    617  1.23   msaitoh 	MFII_IOP_NUM_SGE_LOC_35,
    618  1.23   msaitoh 	MFII_RAID_CTX_ROUTING_FLAGS_CPU0, /* | MFII_RAID_CTX_ROUTING_FLAGS_SQN */
    619  1.23   msaitoh 	MFII_REQ_TYPE_NO_LOCK,
    620  1.23   msaitoh 	MFII_RAID_CTX_TYPE_CUDA | 0x1,
    621  1.23   msaitoh 	MFII_SGE_CHAIN_ELEMENT,
    622  1.23   msaitoh 	MFII_SGE_END_OF_LIST,
    623  1.23   msaitoh 	MFII_IOP_QUIRK_REGREAD | MFII_IOP_HAS_32BITDESC_BIT
    624  1.23   msaitoh };
    625  1.23   msaitoh 
    626   1.1    bouyer struct mfii_device {
    627   1.1    bouyer 	pcireg_t		mpd_vendor;
    628   1.1    bouyer 	pcireg_t		mpd_product;
    629   1.1    bouyer 	const struct mfii_iop	*mpd_iop;
    630   1.1    bouyer };
    631   1.1    bouyer 
    632   1.6      maxv static const struct mfii_device mfii_devices[] = {
    633  1.19   msaitoh 	/* Fusion */
    634   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_2208,
    635   1.1    bouyer 	    &mfii_iop_thunderbolt },
    636  1.17   msaitoh 	/* Fury */
    637   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3008,
    638   1.1    bouyer 	    &mfii_iop_25 },
    639  1.17   msaitoh 	/* Invader */
    640   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3108,
    641   1.1    bouyer 	    &mfii_iop_25 },
    642  1.18   msaitoh 	/* Intruder */
    643  1.18   msaitoh 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3316,
    644  1.18   msaitoh 	    &mfii_iop_25 },
    645  1.18   msaitoh 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3324,
    646  1.18   msaitoh 	    &mfii_iop_25 },
    647  1.18   msaitoh 	/* Cutlass */
    648  1.18   msaitoh 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_32XX_1,
    649  1.18   msaitoh 	    &mfii_iop_25 },
    650  1.18   msaitoh 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_32XX_2,
    651  1.18   msaitoh 	    &mfii_iop_25 },
    652  1.19   msaitoh 	/* Crusader */
    653   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3404,
    654   1.1    bouyer 	    &mfii_iop_35 },
    655  1.17   msaitoh 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3416,
    656  1.17   msaitoh 	    &mfii_iop_35 },
    657  1.19   msaitoh 	/* Ventura */
    658   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3504,
    659   1.1    bouyer 	    &mfii_iop_35 },
    660  1.17   msaitoh 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3516,
    661  1.17   msaitoh 	    &mfii_iop_35 },
    662  1.19   msaitoh 	/* Tomcat */
    663   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3408,
    664   1.1    bouyer 	    &mfii_iop_35 },
    665  1.19   msaitoh 	/* Harpoon */
    666   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3508,
    667  1.23   msaitoh 	    &mfii_iop_35 },
    668  1.23   msaitoh 	/* Aero */
    669  1.23   msaitoh 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_39XX_2,
    670  1.23   msaitoh 	    &mfii_iop_aero },
    671  1.23   msaitoh 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_39XX_3,
    672  1.23   msaitoh 	    &mfii_iop_aero },
    673  1.23   msaitoh 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_38XX_2,
    674  1.23   msaitoh 	    &mfii_iop_aero },
    675  1.23   msaitoh 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_38XX_3,
    676  1.23   msaitoh 	    &mfii_iop_aero }
    677   1.1    bouyer };
    678   1.1    bouyer 
    679   1.6      maxv static const struct mfii_iop *mfii_find_iop(struct pci_attach_args *);
    680   1.1    bouyer 
    681   1.6      maxv static const struct mfii_iop *
    682   1.1    bouyer mfii_find_iop(struct pci_attach_args *pa)
    683   1.1    bouyer {
    684   1.1    bouyer 	const struct mfii_device *mpd;
    685   1.1    bouyer 	int i;
    686   1.1    bouyer 
    687   1.1    bouyer 	for (i = 0; i < __arraycount(mfii_devices); i++) {
    688   1.1    bouyer 		mpd = &mfii_devices[i];
    689   1.1    bouyer 
    690   1.1    bouyer 		if (mpd->mpd_vendor == PCI_VENDOR(pa->pa_id) &&
    691   1.1    bouyer 		    mpd->mpd_product == PCI_PRODUCT(pa->pa_id))
    692   1.1    bouyer 			return (mpd->mpd_iop);
    693   1.1    bouyer 	}
    694   1.1    bouyer 
    695   1.1    bouyer 	return (NULL);
    696   1.1    bouyer }
    697   1.1    bouyer 
    698   1.6      maxv static int
    699   1.1    bouyer mfii_match(device_t parent, cfdata_t match, void *aux)
    700   1.1    bouyer {
    701   1.1    bouyer 	return ((mfii_find_iop(aux) != NULL) ? 2 : 0);
    702   1.1    bouyer }
    703   1.1    bouyer 
    704   1.6      maxv static void
    705   1.1    bouyer mfii_attach(device_t parent, device_t self, void *aux)
    706   1.1    bouyer {
    707   1.1    bouyer 	struct mfii_softc *sc = device_private(self);
    708   1.1    bouyer 	struct pci_attach_args *pa = aux;
    709   1.1    bouyer 	pcireg_t memtype;
    710  1.28    bouyer 	pci_intr_handle_t *ihp;
    711   1.1    bouyer 	char intrbuf[PCI_INTRSTR_LEN];
    712   1.1    bouyer 	const char *intrstr;
    713   1.1    bouyer 	u_int32_t status, scpad2, scpad3;
    714   1.1    bouyer 	int chain_frame_sz, nsge_in_io, nsge_in_chain, i;
    715   1.1    bouyer 	struct scsipi_adapter *adapt = &sc->sc_adapt;
    716   1.1    bouyer 	struct scsipi_channel *chan = &sc->sc_chan;
    717  1.24   msaitoh 	union mfi_mbox mbox;
    718   1.1    bouyer 
    719   1.1    bouyer 	/* init sc */
    720   1.1    bouyer 	sc->sc_dev = self;
    721   1.1    bouyer 	sc->sc_iop = mfii_find_iop(aux);
    722   1.1    bouyer 	sc->sc_dmat = pa->pa_dmat;
    723   1.1    bouyer 	if (pci_dma64_available(pa)) {
    724   1.1    bouyer 		sc->sc_dmat64 = pa->pa_dmat64;
    725   1.1    bouyer 		sc->sc_64bit_dma = 1;
    726   1.1    bouyer 	} else {
    727   1.1    bouyer 		sc->sc_dmat64 = pa->pa_dmat;
    728   1.1    bouyer 		sc->sc_64bit_dma = 0;
    729   1.1    bouyer 	}
    730   1.1    bouyer 	SIMPLEQ_INIT(&sc->sc_ccb_freeq);
    731   1.1    bouyer 	mutex_init(&sc->sc_ccb_mtx, MUTEX_DEFAULT, IPL_BIO);
    732   1.1    bouyer 	mutex_init(&sc->sc_post_mtx, MUTEX_DEFAULT, IPL_BIO);
    733   1.1    bouyer 	mutex_init(&sc->sc_reply_postq_mtx, MUTEX_DEFAULT, IPL_BIO);
    734   1.1    bouyer 
    735   1.1    bouyer 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
    736   1.1    bouyer 
    737   1.1    bouyer 	sc->sc_aen_ccb = NULL;
    738   1.1    bouyer 	snprintf(intrbuf, sizeof(intrbuf) - 1, "%saen", device_xname(self));
    739   1.1    bouyer 	workqueue_create(&sc->sc_aen_wq, intrbuf, mfii_aen, sc,
    740   1.1    bouyer 	    PRI_BIO, IPL_BIO, WQ_MPSAFE);
    741   1.1    bouyer 
    742   1.1    bouyer 	snprintf(intrbuf, sizeof(intrbuf) - 1, "%sabrt", device_xname(self));
    743   1.1    bouyer 	workqueue_create(&sc->sc_abort_wq, intrbuf, mfii_abort_task,
    744   1.1    bouyer 	    sc, PRI_BIO, IPL_BIO, WQ_MPSAFE);
    745   1.1    bouyer 
    746   1.1    bouyer 	mutex_init(&sc->sc_abort_mtx, MUTEX_DEFAULT, IPL_BIO);
    747   1.1    bouyer 	SIMPLEQ_INIT(&sc->sc_abort_list);
    748   1.1    bouyer 
    749   1.1    bouyer 	/* wire up the bus shizz */
    750   1.1    bouyer 	memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, sc->sc_iop->bar);
    751   1.1    bouyer 	memtype |= PCI_MAPREG_MEM_TYPE_32BIT;
    752   1.1    bouyer 	if (pci_mapreg_map(pa, sc->sc_iop->bar, memtype, 0,
    753   1.1    bouyer 	    &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_ios)) {
    754   1.1    bouyer 		aprint_error(": unable to map registers\n");
    755   1.1    bouyer 		return;
    756   1.1    bouyer 	}
    757   1.1    bouyer 
    758   1.1    bouyer 	/* disable interrupts */
    759   1.1    bouyer 	mfii_write(sc, MFI_OMSK, 0xffffffff);
    760   1.1    bouyer 
    761  1.28    bouyer 	if (pci_intr_alloc(pa, &ihp, NULL, 0)) {
    762   1.1    bouyer 		aprint_error(": unable to map interrupt\n");
    763   1.1    bouyer 		goto pci_unmap;
    764   1.1    bouyer 	}
    765  1.28    bouyer 	intrstr = pci_intr_string(pa->pa_pc, ihp[0], intrbuf, sizeof(intrbuf));
    766  1.28    bouyer 	pci_intr_setattr(pa->pa_pc, &ihp[0], PCI_INTR_MPSAFE, true);
    767   1.1    bouyer 
    768   1.1    bouyer 	/* lets get started */
    769   1.1    bouyer 	if (mfii_transition_firmware(sc))
    770   1.1    bouyer 		goto pci_unmap;
    771   1.1    bouyer 	sc->sc_running = true;
    772   1.1    bouyer 
    773   1.1    bouyer 	/* determine max_cmds (refer to the Linux megaraid_sas driver) */
    774   1.1    bouyer 	scpad3 = mfii_read(sc, MFII_OSP3);
    775   1.1    bouyer 	status = mfii_fw_state(sc);
    776   1.1    bouyer 	sc->sc_max_fw_cmds = scpad3 & MFI_STATE_MAXCMD_MASK;
    777   1.1    bouyer 	if (sc->sc_max_fw_cmds == 0)
    778   1.1    bouyer 		sc->sc_max_fw_cmds = status & MFI_STATE_MAXCMD_MASK;
    779   1.1    bouyer 	/*
    780   1.1    bouyer 	 * reduce max_cmds by 1 to ensure that the reply queue depth does not
    781   1.1    bouyer 	 * exceed FW supplied max_fw_cmds.
    782   1.1    bouyer 	 */
    783   1.1    bouyer 	sc->sc_max_cmds = uimin(sc->sc_max_fw_cmds, 1024) - 1;
    784   1.1    bouyer 
    785   1.1    bouyer 	/* determine max_sgl (refer to the Linux megaraid_sas driver) */
    786   1.1    bouyer 	scpad2 = mfii_read(sc, MFII_OSP2);
    787   1.1    bouyer 	chain_frame_sz =
    788   1.1    bouyer 		((scpad2 & MFII_MAX_CHAIN_MASK) >> MFII_MAX_CHAIN_SHIFT) *
    789   1.1    bouyer 		((scpad2 & MFII_MAX_CHAIN_UNIT) ? MFII_1MB_IO : MFII_256K_IO);
    790   1.1    bouyer 	if (chain_frame_sz < MFII_CHAIN_FRAME_MIN)
    791   1.1    bouyer 		chain_frame_sz = MFII_CHAIN_FRAME_MIN;
    792   1.1    bouyer 
    793   1.1    bouyer 	nsge_in_io = (MFII_REQUEST_SIZE -
    794   1.1    bouyer 		sizeof(struct mpii_msg_scsi_io) -
    795   1.1    bouyer 		sizeof(struct mfii_raid_context)) / sizeof(struct mfii_sge);
    796   1.1    bouyer 	nsge_in_chain = chain_frame_sz / sizeof(struct mfii_sge);
    797   1.1    bouyer 
    798   1.1    bouyer 	/* round down to nearest power of two */
    799   1.1    bouyer 	sc->sc_max_sgl = 1;
    800   1.1    bouyer 	while ((sc->sc_max_sgl << 1) <= (nsge_in_io + nsge_in_chain))
    801   1.1    bouyer 		sc->sc_max_sgl <<= 1;
    802   1.1    bouyer 
    803  1.23   msaitoh 	/* Check for atomic(32bit) descriptor */
    804  1.23   msaitoh 	if (((sc->sc_iop->iop_flag & MFII_IOP_HAS_32BITDESC_BIT) != 0) &&
    805  1.23   msaitoh 	    ((scpad2 & MFI_STATE_ATOMIC_DESCRIPTOR) != 0))
    806  1.23   msaitoh 		sc->sc_iop_flag |= MFII_IOP_DESC_32BIT;
    807  1.23   msaitoh 
    808   1.1    bouyer 	DNPRINTF(MFII_D_MISC, "%s: OSP 0x%08x, OSP2 0x%08x, OSP3 0x%08x\n",
    809   1.1    bouyer 	    DEVNAME(sc), status, scpad2, scpad3);
    810   1.1    bouyer 	DNPRINTF(MFII_D_MISC, "%s: max_fw_cmds %d, max_cmds %d\n",
    811   1.1    bouyer 	    DEVNAME(sc), sc->sc_max_fw_cmds, sc->sc_max_cmds);
    812   1.1    bouyer 	DNPRINTF(MFII_D_MISC, "%s: nsge_in_io %d, nsge_in_chain %d, "
    813   1.1    bouyer 	    "max_sgl %d\n", DEVNAME(sc), nsge_in_io, nsge_in_chain,
    814   1.1    bouyer 	    sc->sc_max_sgl);
    815   1.1    bouyer 
    816   1.1    bouyer 	/* sense memory */
    817   1.1    bouyer 	CTASSERT(sizeof(struct mfi_sense) == MFI_SENSE_SIZE);
    818   1.1    bouyer 	sc->sc_sense = mfii_dmamem_alloc(sc, sc->sc_max_cmds * MFI_SENSE_SIZE);
    819   1.1    bouyer 	if (sc->sc_sense == NULL) {
    820   1.1    bouyer 		aprint_error(": unable to allocate sense memory\n");
    821   1.1    bouyer 		goto pci_unmap;
    822   1.1    bouyer 	}
    823   1.1    bouyer 
    824   1.1    bouyer 	/* reply post queue */
    825   1.1    bouyer 	sc->sc_reply_postq_depth = roundup(sc->sc_max_fw_cmds, 16);
    826   1.1    bouyer 
    827   1.1    bouyer 	sc->sc_reply_postq = mfii_dmamem_alloc(sc,
    828   1.1    bouyer 	    sc->sc_reply_postq_depth * sizeof(struct mpii_reply_descr));
    829   1.1    bouyer 	if (sc->sc_reply_postq == NULL)
    830   1.1    bouyer 		goto free_sense;
    831   1.1    bouyer 
    832   1.1    bouyer 	memset(MFII_DMA_KVA(sc->sc_reply_postq), 0xff,
    833   1.1    bouyer 	    MFII_DMA_LEN(sc->sc_reply_postq));
    834   1.1    bouyer 
    835   1.1    bouyer 	/* MPII request frame array */
    836   1.1    bouyer 	sc->sc_requests = mfii_dmamem_alloc(sc,
    837   1.1    bouyer 	    MFII_REQUEST_SIZE * (sc->sc_max_cmds + 1));
    838   1.1    bouyer 	if (sc->sc_requests == NULL)
    839   1.1    bouyer 		goto free_reply_postq;
    840   1.1    bouyer 
    841   1.1    bouyer 	/* MFI command frame array */
    842   1.1    bouyer 	sc->sc_mfi = mfii_dmamem_alloc(sc, sc->sc_max_cmds * MFI_FRAME_SIZE);
    843   1.1    bouyer 	if (sc->sc_mfi == NULL)
    844   1.1    bouyer 		goto free_requests;
    845   1.1    bouyer 
    846   1.1    bouyer 	/* MPII SGL array */
    847   1.1    bouyer 	sc->sc_sgl = mfii_dmamem_alloc(sc, sc->sc_max_cmds *
    848   1.1    bouyer 	    sizeof(struct mfii_sge) * sc->sc_max_sgl);
    849   1.1    bouyer 	if (sc->sc_sgl == NULL)
    850   1.1    bouyer 		goto free_mfi;
    851   1.1    bouyer 
    852   1.1    bouyer 	if (mfii_init_ccb(sc) != 0) {
    853   1.1    bouyer 		aprint_error(": could not init ccb list\n");
    854   1.1    bouyer 		goto free_sgl;
    855   1.1    bouyer 	}
    856   1.1    bouyer 
    857   1.1    bouyer 	/* kickstart firmware with all addresses and pointers */
    858   1.1    bouyer 	if (mfii_initialise_firmware(sc) != 0) {
    859   1.1    bouyer 		aprint_error(": could not initialize firmware\n");
    860   1.1    bouyer 		goto free_sgl;
    861   1.1    bouyer 	}
    862   1.1    bouyer 
    863   1.1    bouyer 	mutex_enter(&sc->sc_lock);
    864   1.1    bouyer 	if (mfii_get_info(sc) != 0) {
    865   1.1    bouyer 		mutex_exit(&sc->sc_lock);
    866   1.1    bouyer 		aprint_error(": could not retrieve controller information\n");
    867   1.1    bouyer 		goto free_sgl;
    868   1.1    bouyer 	}
    869   1.1    bouyer 	mutex_exit(&sc->sc_lock);
    870   1.1    bouyer 
    871   1.1    bouyer 	aprint_normal(": \"%s\", firmware %s",
    872   1.1    bouyer 	    sc->sc_info.mci_product_name, sc->sc_info.mci_package_version);
    873   1.1    bouyer 	if (le16toh(sc->sc_info.mci_memory_size) > 0) {
    874   1.1    bouyer 		aprint_normal(", %uMB cache",
    875   1.1    bouyer 		    le16toh(sc->sc_info.mci_memory_size));
    876   1.1    bouyer 	}
    877   1.1    bouyer 	aprint_normal("\n");
    878   1.1    bouyer 	aprint_naive("\n");
    879   1.1    bouyer 
    880  1.28    bouyer 	sc->sc_ih = pci_intr_establish_xname(sc->sc_pc, ihp[0], IPL_BIO,
    881   1.1    bouyer 	    mfii_intr, sc, DEVNAME(sc));
    882   1.1    bouyer 	if (sc->sc_ih == NULL) {
    883   1.1    bouyer 		aprint_error_dev(self, "can't establish interrupt");
    884   1.1    bouyer 		if (intrstr)
    885   1.1    bouyer 			aprint_error(" at %s", intrstr);
    886   1.1    bouyer 		aprint_error("\n");
    887   1.1    bouyer 		goto free_sgl;
    888   1.1    bouyer 	}
    889   1.1    bouyer 	aprint_normal_dev(self, "interrupting at %s\n", intrstr);
    890   1.1    bouyer 
    891   1.1    bouyer 	for (i = 0; i < sc->sc_info.mci_lds_present; i++)
    892   1.1    bouyer 		sc->sc_ld[i].ld_present = 1;
    893   1.1    bouyer 
    894  1.24   msaitoh 	sc->sc_max256vd =
    895  1.24   msaitoh 	    (sc->sc_info.mci_adapter_ops3 & MFI_INFO_AOPS3_SUPP_MAX_EXT_LDS) ?
    896  1.24   msaitoh 	    true : false;
    897  1.24   msaitoh 
    898  1.24   msaitoh 	if (sc->sc_max256vd)
    899  1.24   msaitoh 		aprint_verbose_dev(self, "Max 256 VD support\n");
    900  1.24   msaitoh 
    901   1.1    bouyer 	memset(adapt, 0, sizeof(*adapt));
    902   1.1    bouyer 	adapt->adapt_dev = sc->sc_dev;
    903   1.1    bouyer 	adapt->adapt_nchannels = 1;
    904   1.1    bouyer 	/* keep a few commands for management */
    905   1.1    bouyer 	if (sc->sc_max_cmds > 4)
    906   1.1    bouyer 		adapt->adapt_openings = sc->sc_max_cmds - 4;
    907   1.1    bouyer 	else
    908   1.1    bouyer 		adapt->adapt_openings = sc->sc_max_cmds;
    909   1.1    bouyer 	adapt->adapt_max_periph = adapt->adapt_openings;
    910   1.1    bouyer 	adapt->adapt_request = mfii_scsipi_request;
    911   1.1    bouyer 	adapt->adapt_minphys = minphys;
    912   1.1    bouyer 	adapt->adapt_flags = SCSIPI_ADAPT_MPSAFE;
    913   1.1    bouyer 
    914   1.1    bouyer 	memset(chan, 0, sizeof(*chan));
    915   1.1    bouyer 	chan->chan_adapter = adapt;
    916   1.1    bouyer 	chan->chan_bustype = &scsi_sas_bustype;
    917   1.1    bouyer 	chan->chan_channel = 0;
    918   1.1    bouyer 	chan->chan_flags = 0;
    919   1.1    bouyer 	chan->chan_nluns = 8;
    920   1.1    bouyer 	chan->chan_ntargets = sc->sc_info.mci_max_lds;
    921   1.1    bouyer 	chan->chan_id = sc->sc_info.mci_max_lds;
    922   1.1    bouyer 
    923   1.8   thorpej 	mfii_rescan(sc->sc_dev, NULL, NULL);
    924   1.1    bouyer 
    925   1.1    bouyer 	if (mfii_aen_register(sc) != 0) {
    926   1.1    bouyer 		/* error printed by mfii_aen_register */
    927   1.1    bouyer 		goto intr_disestablish;
    928   1.1    bouyer 	}
    929   1.1    bouyer 
    930  1.24   msaitoh 	memset(&mbox, 0, sizeof(mbox));
    931  1.24   msaitoh 	if (sc->sc_max256vd)
    932  1.24   msaitoh 		mbox.b[0] = 1;
    933   1.1    bouyer 	mutex_enter(&sc->sc_lock);
    934  1.24   msaitoh 	if (mfii_mgmt(sc, MR_DCMD_LD_GET_LIST, &mbox, &sc->sc_ld_list,
    935   1.1    bouyer 	    sizeof(sc->sc_ld_list), MFII_DATA_IN, true) != 0) {
    936   1.1    bouyer 		mutex_exit(&sc->sc_lock);
    937   1.1    bouyer 		aprint_error_dev(self,
    938   1.1    bouyer 		    "getting list of logical disks failed\n");
    939   1.1    bouyer 		goto intr_disestablish;
    940   1.1    bouyer 	}
    941   1.1    bouyer 	mutex_exit(&sc->sc_lock);
    942   1.1    bouyer 	memset(sc->sc_target_lds, -1, sizeof(sc->sc_target_lds));
    943   1.1    bouyer 	for (i = 0; i < sc->sc_ld_list.mll_no_ld; i++) {
    944   1.1    bouyer 		int target = sc->sc_ld_list.mll_list[i].mll_ld.mld_target;
    945   1.1    bouyer 		sc->sc_target_lds[target] = i;
    946  1.25   msaitoh 		sc->sc_ld[i].ld_target_id = target;
    947   1.1    bouyer 	}
    948   1.1    bouyer 
    949   1.1    bouyer 	/* enable interrupts */
    950   1.1    bouyer 	mfii_write(sc, MFI_OSTS, 0xffffffff);
    951   1.1    bouyer 	mfii_write(sc, MFI_OMSK, ~MFII_OSTS_INTR_VALID);
    952   1.1    bouyer 
    953   1.1    bouyer #if NBIO > 0
    954   1.1    bouyer 	if (bio_register(sc->sc_dev, mfii_ioctl) != 0)
    955   1.1    bouyer 		panic("%s: controller registration failed", DEVNAME(sc));
    956   1.1    bouyer #endif /* NBIO > 0 */
    957   1.1    bouyer 
    958   1.1    bouyer 	if (mfii_create_sensors(sc) != 0)
    959   1.1    bouyer 		aprint_error_dev(self, "unable to create sensors\n");
    960   1.1    bouyer 
    961   1.1    bouyer 	if (!pmf_device_register1(sc->sc_dev, mfii_suspend, mfii_resume,
    962   1.1    bouyer 	    mfii_shutdown))
    963   1.1    bouyer 		aprint_error_dev(self, "couldn't establish power handler\n");
    964   1.1    bouyer 	return;
    965   1.1    bouyer intr_disestablish:
    966   1.1    bouyer 	pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
    967   1.1    bouyer free_sgl:
    968   1.1    bouyer 	mfii_dmamem_free(sc, sc->sc_sgl);
    969   1.1    bouyer free_mfi:
    970   1.1    bouyer 	mfii_dmamem_free(sc, sc->sc_mfi);
    971   1.1    bouyer free_requests:
    972   1.1    bouyer 	mfii_dmamem_free(sc, sc->sc_requests);
    973   1.1    bouyer free_reply_postq:
    974   1.1    bouyer 	mfii_dmamem_free(sc, sc->sc_reply_postq);
    975   1.1    bouyer free_sense:
    976   1.1    bouyer 	mfii_dmamem_free(sc, sc->sc_sense);
    977   1.1    bouyer pci_unmap:
    978   1.1    bouyer 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    979   1.1    bouyer }
    980   1.1    bouyer 
    981   1.1    bouyer #if 0
    982   1.1    bouyer struct srp_gc mfii_dev_handles_gc =
    983   1.1    bouyer     SRP_GC_INITIALIZER(mfii_dev_handles_dtor, NULL);
    984   1.1    bouyer 
    985   1.1    bouyer static inline uint16_t
    986   1.1    bouyer mfii_dev_handle(struct mfii_softc *sc, uint16_t target)
    987   1.1    bouyer {
    988   1.1    bouyer 	struct srp_ref sr;
    989   1.1    bouyer 	uint16_t *map, handle;
    990   1.1    bouyer 
    991   1.1    bouyer 	map = srp_enter(&sr, &sc->sc_pd->pd_dev_handles);
    992   1.1    bouyer 	handle = map[target];
    993   1.1    bouyer 	srp_leave(&sr);
    994   1.1    bouyer 
    995   1.1    bouyer 	return (handle);
    996   1.1    bouyer }
    997   1.1    bouyer 
    998   1.6      maxv static int
    999   1.1    bouyer mfii_dev_handles_update(struct mfii_softc *sc)
   1000   1.1    bouyer {
   1001   1.1    bouyer 	struct mfii_ld_map *lm;
   1002   1.1    bouyer 	uint16_t *dev_handles = NULL;
   1003   1.1    bouyer 	int i;
   1004   1.1    bouyer 	int rv = 0;
   1005   1.1    bouyer 
   1006   1.1    bouyer 	lm = malloc(sizeof(*lm), M_TEMP, M_WAITOK|M_ZERO);
   1007   1.1    bouyer 
   1008   1.1    bouyer 	rv = mfii_mgmt(sc, MR_DCMD_LD_MAP_GET_INFO, NULL, lm, sizeof(*lm),
   1009   1.1    bouyer 	    MFII_DATA_IN, false);
   1010   1.1    bouyer 
   1011   1.1    bouyer 	if (rv != 0) {
   1012   1.1    bouyer 		rv = EIO;
   1013   1.1    bouyer 		goto free_lm;
   1014   1.1    bouyer 	}
   1015   1.1    bouyer 
   1016   1.1    bouyer 	dev_handles = mallocarray(MFI_MAX_PD, sizeof(*dev_handles),
   1017   1.1    bouyer 	    M_DEVBUF, M_WAITOK);
   1018   1.1    bouyer 
   1019   1.1    bouyer 	for (i = 0; i < MFI_MAX_PD; i++)
   1020   1.1    bouyer 		dev_handles[i] = lm->mlm_dev_handle[i].mdh_cur_handle;
   1021   1.1    bouyer 
   1022   1.1    bouyer 	/* commit the updated info */
   1023   1.1    bouyer 	sc->sc_pd->pd_timeout = lm->mlm_pd_timeout;
   1024   1.1    bouyer 	srp_update_locked(&mfii_dev_handles_gc,
   1025   1.1    bouyer 	    &sc->sc_pd->pd_dev_handles, dev_handles);
   1026   1.1    bouyer 
   1027   1.1    bouyer free_lm:
   1028   1.1    bouyer 	free(lm, M_TEMP, sizeof(*lm));
   1029   1.1    bouyer 
   1030   1.1    bouyer 	return (rv);
   1031   1.1    bouyer }
   1032   1.1    bouyer 
   1033   1.6      maxv static void
   1034   1.1    bouyer mfii_dev_handles_dtor(void *null, void *v)
   1035   1.1    bouyer {
   1036   1.1    bouyer 	uint16_t *dev_handles = v;
   1037   1.1    bouyer 
   1038   1.1    bouyer 	free(dev_handles, M_DEVBUF, sizeof(*dev_handles) * MFI_MAX_PD);
   1039   1.1    bouyer }
   1040   1.1    bouyer #endif /* 0 */
   1041   1.1    bouyer 
   1042   1.6      maxv static int
   1043   1.1    bouyer mfii_detach(device_t self, int flags)
   1044   1.1    bouyer {
   1045   1.1    bouyer 	struct mfii_softc *sc = device_private(self);
   1046   1.1    bouyer 	int error;
   1047   1.1    bouyer 
   1048   1.1    bouyer 	if (sc->sc_ih == NULL)
   1049   1.1    bouyer 		return (0);
   1050   1.1    bouyer 
   1051   1.1    bouyer 	if ((error = config_detach_children(sc->sc_dev, flags)) != 0)
   1052   1.1    bouyer 		return error;
   1053   1.1    bouyer 
   1054   1.1    bouyer 	mfii_destroy_sensors(sc);
   1055   1.1    bouyer #if NBIO > 0
   1056   1.1    bouyer 	bio_unregister(sc->sc_dev);
   1057   1.1    bouyer #endif
   1058   1.1    bouyer 	mfii_shutdown(sc->sc_dev, 0);
   1059   1.1    bouyer 	mfii_write(sc, MFI_OMSK, 0xffffffff);
   1060   1.1    bouyer 
   1061   1.1    bouyer 	mfii_aen_unregister(sc);
   1062   1.1    bouyer 	pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
   1063   1.1    bouyer 	mfii_dmamem_free(sc, sc->sc_sgl);
   1064   1.1    bouyer 	mfii_dmamem_free(sc, sc->sc_mfi);
   1065   1.1    bouyer 	mfii_dmamem_free(sc, sc->sc_requests);
   1066   1.1    bouyer 	mfii_dmamem_free(sc, sc->sc_reply_postq);
   1067   1.1    bouyer 	mfii_dmamem_free(sc, sc->sc_sense);
   1068   1.1    bouyer 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
   1069   1.1    bouyer 
   1070   1.1    bouyer 	return (0);
   1071   1.1    bouyer }
   1072   1.1    bouyer 
   1073   1.6      maxv static int
   1074   1.1    bouyer mfii_rescan(device_t self, const char *ifattr, const int *locators)
   1075   1.1    bouyer {
   1076   1.1    bouyer 	struct mfii_softc *sc = device_private(self);
   1077   1.8   thorpej 
   1078   1.1    bouyer 	if (sc->sc_child != NULL)
   1079   1.1    bouyer 		return 0;
   1080   1.1    bouyer 
   1081  1.19   msaitoh 	sc->sc_child = config_found(self, &sc->sc_chan, scsiprint,
   1082  1.19   msaitoh 	    CFARGS_NONE);
   1083   1.1    bouyer 	return 0;
   1084   1.1    bouyer }
   1085   1.1    bouyer 
   1086   1.6      maxv static void
   1087   1.1    bouyer mfii_childdetached(device_t self, device_t child)
   1088   1.1    bouyer {
   1089   1.1    bouyer 	struct mfii_softc *sc = device_private(self);
   1090   1.1    bouyer 
   1091   1.1    bouyer 	KASSERT(self == sc->sc_dev);
   1092   1.1    bouyer 	KASSERT(child == sc->sc_child);
   1093   1.1    bouyer 
   1094   1.1    bouyer 	if (child == sc->sc_child)
   1095   1.1    bouyer 		sc->sc_child = NULL;
   1096   1.1    bouyer }
   1097   1.1    bouyer 
   1098  1.10   msaitoh static bool
   1099   1.1    bouyer mfii_suspend(device_t dev, const pmf_qual_t *q)
   1100   1.1    bouyer {
   1101   1.1    bouyer 	/* XXX to be implemented */
   1102   1.1    bouyer 	return false;
   1103   1.1    bouyer }
   1104   1.1    bouyer 
   1105   1.1    bouyer static bool
   1106   1.1    bouyer mfii_resume(device_t dev, const pmf_qual_t *q)
   1107  1.10   msaitoh {
   1108   1.1    bouyer 	/* XXX to be implemented */
   1109   1.1    bouyer 	return false;
   1110   1.1    bouyer }
   1111  1.10   msaitoh 
   1112   1.1    bouyer static bool
   1113   1.1    bouyer mfii_shutdown(device_t dev, int how)
   1114   1.1    bouyer {
   1115   1.1    bouyer 	struct mfii_softc	*sc = device_private(dev);
   1116   1.1    bouyer 	struct mfii_ccb *ccb;
   1117   1.1    bouyer 	union mfi_mbox		mbox;
   1118   1.7   msaitoh 	bool rv = true;
   1119   1.1    bouyer 
   1120   1.1    bouyer 	memset(&mbox, 0, sizeof(mbox));
   1121   1.1    bouyer 
   1122   1.1    bouyer 	mutex_enter(&sc->sc_lock);
   1123  1.15   msaitoh 	DNPRINTF(MFII_D_MISC, "%s: mfii_shutdown\n", DEVNAME(sc));
   1124   1.1    bouyer 	ccb = mfii_get_ccb(sc);
   1125   1.1    bouyer 	if (ccb == NULL)
   1126   1.1    bouyer 		return false;
   1127   1.1    bouyer 	mutex_enter(&sc->sc_ccb_mtx);
   1128   1.1    bouyer 	if (sc->sc_running) {
   1129   1.1    bouyer 		sc->sc_running = 0; /* prevent new commands */
   1130   1.1    bouyer 		mutex_exit(&sc->sc_ccb_mtx);
   1131   1.1    bouyer #if 0 /* XXX why does this hang ? */
   1132   1.1    bouyer 		mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
   1133   1.1    bouyer 		mfii_scrub_ccb(ccb);
   1134   1.1    bouyer 		if (mfii_do_mgmt(sc, ccb, MR_DCMD_CTRL_CACHE_FLUSH, &mbox,
   1135   1.1    bouyer 		    NULL, 0, MFII_DATA_NONE, true)) {
   1136  1.19   msaitoh 			aprint_error_dev(dev,
   1137  1.19   msaitoh 			    "shutdown: cache flush failed\n");
   1138   1.1    bouyer 			rv = false;
   1139   1.1    bouyer 			goto fail;
   1140   1.1    bouyer 		}
   1141   1.1    bouyer 		printf("ok1\n");
   1142   1.1    bouyer #endif
   1143   1.1    bouyer 		mbox.b[0] = 0;
   1144   1.1    bouyer 		mfii_scrub_ccb(ccb);
   1145   1.1    bouyer 		if (mfii_do_mgmt(sc, ccb, MR_DCMD_CTRL_SHUTDOWN, &mbox,
   1146   1.1    bouyer 		    NULL, 0, MFII_DATA_NONE, true)) {
   1147   1.1    bouyer 			aprint_error_dev(dev, "shutdown: "
   1148   1.1    bouyer 			    "firmware shutdown failed\n");
   1149  1.10   msaitoh 			rv = false;
   1150   1.1    bouyer 			goto fail;
   1151   1.1    bouyer 		}
   1152   1.1    bouyer 	} else {
   1153   1.1    bouyer 		mutex_exit(&sc->sc_ccb_mtx);
   1154   1.1    bouyer 	}
   1155   1.1    bouyer fail:
   1156   1.1    bouyer 	mfii_put_ccb(sc, ccb);
   1157   1.1    bouyer 	mutex_exit(&sc->sc_lock);
   1158   1.1    bouyer 	return rv;
   1159   1.1    bouyer }
   1160   1.1    bouyer 
   1161  1.23   msaitoh /* Register read function without retry */
   1162  1.23   msaitoh static inline u_int32_t
   1163  1.23   msaitoh mfii_read_wor(struct mfii_softc *sc, bus_size_t r)
   1164   1.1    bouyer {
   1165   1.1    bouyer 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
   1166   1.1    bouyer 	    BUS_SPACE_BARRIER_READ);
   1167   1.1    bouyer 	return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, r));
   1168   1.1    bouyer }
   1169   1.1    bouyer 
   1170  1.23   msaitoh static u_int32_t
   1171  1.23   msaitoh mfii_read(struct mfii_softc *sc, bus_size_t r)
   1172  1.23   msaitoh {
   1173  1.23   msaitoh 	uint32_t rv;
   1174  1.23   msaitoh 	int i = 0;
   1175  1.23   msaitoh 
   1176  1.23   msaitoh 	if ((sc->sc_iop->iop_flag & MFII_IOP_QUIRK_REGREAD) != 0) {
   1177  1.23   msaitoh 		do {
   1178  1.23   msaitoh 			rv = mfii_read_wor(sc, r);
   1179  1.23   msaitoh 			i++;
   1180  1.23   msaitoh 		} while ((rv == 0) && (i < 3));
   1181  1.23   msaitoh 	} else
   1182  1.23   msaitoh 		rv = mfii_read_wor(sc, r);
   1183  1.23   msaitoh 
   1184  1.23   msaitoh 	return rv;
   1185  1.23   msaitoh }
   1186  1.23   msaitoh 
   1187   1.1    bouyer static void
   1188   1.1    bouyer mfii_write(struct mfii_softc *sc, bus_size_t r, u_int32_t v)
   1189   1.1    bouyer {
   1190   1.1    bouyer 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
   1191   1.1    bouyer 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
   1192   1.1    bouyer 	    BUS_SPACE_BARRIER_WRITE);
   1193   1.1    bouyer }
   1194   1.1    bouyer 
   1195   1.6      maxv static struct mfii_dmamem *
   1196   1.1    bouyer mfii_dmamem_alloc(struct mfii_softc *sc, size_t size)
   1197   1.1    bouyer {
   1198   1.1    bouyer 	struct mfii_dmamem *m;
   1199   1.1    bouyer 	int nsegs;
   1200   1.1    bouyer 
   1201   1.5       chs 	m = malloc(sizeof(*m), M_DEVBUF, M_WAITOK | M_ZERO);
   1202   1.1    bouyer 	m->mdm_size = size;
   1203   1.1    bouyer 
   1204   1.1    bouyer 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
   1205   1.1    bouyer 	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &m->mdm_map) != 0)
   1206   1.1    bouyer 		goto mdmfree;
   1207   1.1    bouyer 
   1208   1.1    bouyer 	if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &m->mdm_seg, 1,
   1209   1.1    bouyer 	    &nsegs, BUS_DMA_NOWAIT) != 0)
   1210   1.1    bouyer 		goto destroy;
   1211   1.1    bouyer 
   1212   1.1    bouyer 	if (bus_dmamem_map(sc->sc_dmat, &m->mdm_seg, nsegs, size, &m->mdm_kva,
   1213   1.1    bouyer 	    BUS_DMA_NOWAIT) != 0)
   1214   1.1    bouyer 		goto free;
   1215   1.1    bouyer 
   1216   1.1    bouyer 	if (bus_dmamap_load(sc->sc_dmat, m->mdm_map, m->mdm_kva, size, NULL,
   1217   1.1    bouyer 	    BUS_DMA_NOWAIT) != 0)
   1218   1.1    bouyer 		goto unmap;
   1219   1.1    bouyer 
   1220   1.1    bouyer 	memset(m->mdm_kva, 0, size);
   1221   1.1    bouyer 	return (m);
   1222   1.1    bouyer 
   1223   1.1    bouyer unmap:
   1224   1.1    bouyer 	bus_dmamem_unmap(sc->sc_dmat, m->mdm_kva, m->mdm_size);
   1225   1.1    bouyer free:
   1226   1.1    bouyer 	bus_dmamem_free(sc->sc_dmat, &m->mdm_seg, 1);
   1227   1.1    bouyer destroy:
   1228   1.1    bouyer 	bus_dmamap_destroy(sc->sc_dmat, m->mdm_map);
   1229   1.1    bouyer mdmfree:
   1230   1.1    bouyer 	free(m, M_DEVBUF);
   1231   1.1    bouyer 
   1232   1.1    bouyer 	return (NULL);
   1233   1.1    bouyer }
   1234   1.1    bouyer 
   1235   1.6      maxv static void
   1236   1.1    bouyer mfii_dmamem_free(struct mfii_softc *sc, struct mfii_dmamem *m)
   1237   1.1    bouyer {
   1238   1.1    bouyer 	bus_dmamap_unload(sc->sc_dmat, m->mdm_map);
   1239   1.1    bouyer 	bus_dmamem_unmap(sc->sc_dmat, m->mdm_kva, m->mdm_size);
   1240   1.1    bouyer 	bus_dmamem_free(sc->sc_dmat, &m->mdm_seg, 1);
   1241   1.1    bouyer 	bus_dmamap_destroy(sc->sc_dmat, m->mdm_map);
   1242   1.1    bouyer 	free(m, M_DEVBUF);
   1243   1.1    bouyer }
   1244   1.1    bouyer 
   1245   1.6      maxv static void
   1246   1.1    bouyer mfii_dcmd_start(struct mfii_softc *sc, struct mfii_ccb *ccb)
   1247   1.1    bouyer {
   1248   1.1    bouyer 	struct mpii_msg_scsi_io *io = ccb->ccb_request;
   1249   1.1    bouyer 	struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
   1250   1.1    bouyer 	struct mfii_sge *sge = (struct mfii_sge *)(ctx + 1);
   1251   1.1    bouyer 
   1252   1.1    bouyer 	io->function = MFII_FUNCTION_PASSTHRU_IO;
   1253   1.1    bouyer 	io->sgl_offset0 = (uint32_t *)sge - (uint32_t *)io;
   1254   1.1    bouyer 	io->chain_offset = io->sgl_offset0 / 4;
   1255   1.1    bouyer 
   1256   1.1    bouyer 	sge->sg_addr = htole64(ccb->ccb_sense_dva);
   1257   1.1    bouyer 	sge->sg_len = htole32(sizeof(*ccb->ccb_sense));
   1258   1.1    bouyer 	sge->sg_flags = MFII_SGE_CHAIN_ELEMENT | MFII_SGE_ADDR_IOCPLBNTA;
   1259   1.1    bouyer 
   1260   1.1    bouyer 	ccb->ccb_req.flags = MFII_REQ_TYPE_SCSI;
   1261   1.1    bouyer 	ccb->ccb_req.smid = le16toh(ccb->ccb_smid);
   1262   1.1    bouyer 
   1263   1.1    bouyer 	mfii_start(sc, ccb);
   1264   1.1    bouyer }
   1265   1.1    bouyer 
   1266   1.6      maxv static int
   1267   1.1    bouyer mfii_aen_register(struct mfii_softc *sc)
   1268   1.1    bouyer {
   1269   1.1    bouyer 	struct mfi_evt_log_info mel;
   1270   1.1    bouyer 	struct mfii_ccb *ccb;
   1271   1.1    bouyer 	struct mfii_dmamem *mdm;
   1272   1.1    bouyer 	int rv;
   1273   1.1    bouyer 
   1274   1.1    bouyer 	ccb = mfii_get_ccb(sc);
   1275   1.1    bouyer 	if (ccb == NULL) {
   1276   1.1    bouyer 		printf("%s: unable to allocate ccb for aen\n", DEVNAME(sc));
   1277   1.1    bouyer 		return (ENOMEM);
   1278   1.1    bouyer 	}
   1279   1.1    bouyer 
   1280   1.1    bouyer 	memset(&mel, 0, sizeof(mel));
   1281   1.1    bouyer 	mfii_scrub_ccb(ccb);
   1282   1.1    bouyer 
   1283   1.1    bouyer 	rv = mfii_do_mgmt(sc, ccb, MR_DCMD_CTRL_EVENT_GET_INFO, NULL,
   1284   1.1    bouyer 	    &mel, sizeof(mel), MFII_DATA_IN, true);
   1285   1.1    bouyer 	if (rv != 0) {
   1286   1.1    bouyer 		mfii_put_ccb(sc, ccb);
   1287   1.1    bouyer 		aprint_error_dev(sc->sc_dev, "unable to get event info\n");
   1288   1.1    bouyer 		return (EIO);
   1289   1.1    bouyer 	}
   1290   1.1    bouyer 
   1291   1.1    bouyer 	mdm = mfii_dmamem_alloc(sc, sizeof(struct mfi_evt_detail));
   1292   1.1    bouyer 	if (mdm == NULL) {
   1293   1.1    bouyer 		mfii_put_ccb(sc, ccb);
   1294  1.19   msaitoh 		aprint_error_dev(sc->sc_dev,
   1295  1.19   msaitoh 		    "unable to allocate event data\n");
   1296   1.1    bouyer 		return (ENOMEM);
   1297   1.1    bouyer 	}
   1298   1.1    bouyer 
   1299   1.1    bouyer 	/* replay all the events from boot */
   1300   1.1    bouyer 	mfii_aen_start(sc, ccb, mdm, le32toh(mel.mel_boot_seq_num));
   1301   1.1    bouyer 
   1302   1.1    bouyer 	return (0);
   1303   1.1    bouyer }
   1304   1.1    bouyer 
   1305   1.6      maxv static void
   1306   1.1    bouyer mfii_aen_start(struct mfii_softc *sc, struct mfii_ccb *ccb,
   1307   1.1    bouyer     struct mfii_dmamem *mdm, uint32_t seq)
   1308   1.1    bouyer {
   1309   1.1    bouyer 	struct mfi_dcmd_frame *dcmd = mfii_dcmd_frame(ccb);
   1310   1.1    bouyer 	struct mfi_frame_header *hdr = &dcmd->mdf_header;
   1311   1.1    bouyer 	union mfi_sgl *sgl = &dcmd->mdf_sgl;
   1312   1.1    bouyer 	union mfi_evt_class_locale mec;
   1313   1.1    bouyer 
   1314   1.1    bouyer 	mfii_scrub_ccb(ccb);
   1315   1.1    bouyer 	mfii_dcmd_scrub(ccb);
   1316   1.1    bouyer 	memset(MFII_DMA_KVA(mdm), 0, MFII_DMA_LEN(mdm));
   1317   1.1    bouyer 
   1318   1.1    bouyer 	ccb->ccb_cookie = mdm;
   1319   1.1    bouyer 	ccb->ccb_done = mfii_aen_done;
   1320   1.1    bouyer 	sc->sc_aen_ccb = ccb;
   1321   1.1    bouyer 
   1322   1.1    bouyer 	mec.mec_members.class = MFI_EVT_CLASS_DEBUG;
   1323   1.1    bouyer 	mec.mec_members.reserved = 0;
   1324   1.1    bouyer 	mec.mec_members.locale = htole16(MFI_EVT_LOCALE_ALL);
   1325   1.1    bouyer 
   1326   1.1    bouyer 	hdr->mfh_cmd = MFI_CMD_DCMD;
   1327   1.1    bouyer 	hdr->mfh_sg_count = 1;
   1328   1.1    bouyer 	hdr->mfh_flags = htole16(MFI_FRAME_DIR_READ | MFI_FRAME_SGL64);
   1329   1.1    bouyer 	hdr->mfh_data_len = htole32(MFII_DMA_LEN(mdm));
   1330   1.1    bouyer 	dcmd->mdf_opcode = htole32(MR_DCMD_CTRL_EVENT_WAIT);
   1331   1.1    bouyer 	dcmd->mdf_mbox.w[0] = htole32(seq);
   1332   1.1    bouyer 	dcmd->mdf_mbox.w[1] = htole32(mec.mec_word);
   1333   1.1    bouyer 	sgl->sg64[0].addr = htole64(MFII_DMA_DVA(mdm));
   1334   1.1    bouyer 	sgl->sg64[0].len = htole32(MFII_DMA_LEN(mdm));
   1335   1.1    bouyer 
   1336   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(mdm),
   1337   1.1    bouyer 	    0, MFII_DMA_LEN(mdm), BUS_DMASYNC_PREREAD);
   1338   1.1    bouyer 
   1339   1.1    bouyer 	mfii_dcmd_sync(sc, ccb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
   1340   1.1    bouyer 	mfii_dcmd_start(sc, ccb);
   1341   1.1    bouyer }
   1342   1.1    bouyer 
   1343   1.6      maxv static void
   1344   1.1    bouyer mfii_aen_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
   1345   1.1    bouyer {
   1346   1.1    bouyer 	KASSERT(sc->sc_aen_ccb == ccb);
   1347   1.1    bouyer 
   1348   1.1    bouyer 	/*
   1349   1.1    bouyer 	 * defer to a thread with KERNEL_LOCK so we can run autoconf
   1350   1.1    bouyer 	 * We shouldn't have more than one AEN command pending at a time,
   1351   1.1    bouyer 	 * so no need to lock
   1352   1.1    bouyer 	 */
   1353   1.1    bouyer 	if (sc->sc_running)
   1354   1.1    bouyer 		workqueue_enqueue(sc->sc_aen_wq, &sc->sc_aen_work, NULL);
   1355   1.1    bouyer }
   1356   1.1    bouyer 
   1357   1.6      maxv static void
   1358   1.1    bouyer mfii_aen(struct work *wk, void *arg)
   1359   1.1    bouyer {
   1360   1.1    bouyer 	struct mfii_softc *sc = arg;
   1361   1.1    bouyer 	struct mfii_ccb *ccb = sc->sc_aen_ccb;
   1362   1.1    bouyer 	struct mfii_dmamem *mdm = ccb->ccb_cookie;
   1363   1.1    bouyer 	const struct mfi_evt_detail *med = MFII_DMA_KVA(mdm);
   1364   1.1    bouyer 
   1365   1.1    bouyer 	mfii_dcmd_sync(sc, ccb,
   1366   1.1    bouyer 	    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
   1367   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(mdm),
   1368   1.1    bouyer 	    0, MFII_DMA_LEN(mdm), BUS_DMASYNC_POSTREAD);
   1369   1.1    bouyer 
   1370   1.1    bouyer 	DNPRINTF(MFII_D_MISC, "%s: %u %08x %02x %s\n", DEVNAME(sc),
   1371   1.1    bouyer 	    le32toh(med->med_seq_num), le32toh(med->med_code),
   1372   1.1    bouyer 	    med->med_arg_type, med->med_description);
   1373   1.1    bouyer 
   1374   1.1    bouyer 	switch (le32toh(med->med_code)) {
   1375   1.1    bouyer 	case MR_EVT_PD_INSERTED_EXT:
   1376   1.1    bouyer 		if (med->med_arg_type != MR_EVT_ARGS_PD_ADDRESS)
   1377   1.1    bouyer 			break;
   1378  1.10   msaitoh 
   1379   1.1    bouyer 		mfii_aen_pd_insert(sc, &med->args.pd_address);
   1380   1.1    bouyer 		break;
   1381  1.10   msaitoh 	case MR_EVT_PD_REMOVED_EXT:
   1382   1.1    bouyer 		if (med->med_arg_type != MR_EVT_ARGS_PD_ADDRESS)
   1383   1.1    bouyer 			break;
   1384  1.10   msaitoh 
   1385   1.1    bouyer 		mfii_aen_pd_remove(sc, &med->args.pd_address);
   1386   1.1    bouyer 		break;
   1387   1.1    bouyer 
   1388   1.1    bouyer 	case MR_EVT_PD_STATE_CHANGE:
   1389   1.1    bouyer 		if (med->med_arg_type != MR_EVT_ARGS_PD_STATE)
   1390   1.1    bouyer 			break;
   1391   1.1    bouyer 
   1392   1.1    bouyer 		mfii_aen_pd_state_change(sc, &med->args.pd_state);
   1393   1.1    bouyer 		break;
   1394   1.1    bouyer 
   1395   1.1    bouyer 	case MR_EVT_LD_CREATED:
   1396   1.1    bouyer 	case MR_EVT_LD_DELETED:
   1397   1.1    bouyer 		mfii_aen_ld_update(sc);
   1398   1.1    bouyer 		break;
   1399   1.1    bouyer 
   1400   1.1    bouyer 	default:
   1401   1.1    bouyer 		break;
   1402   1.1    bouyer 	}
   1403   1.1    bouyer 
   1404   1.1    bouyer 	mfii_aen_start(sc, ccb, mdm, le32toh(med->med_seq_num) + 1);
   1405   1.1    bouyer }
   1406   1.1    bouyer 
   1407   1.6      maxv static void
   1408   1.1    bouyer mfii_aen_pd_insert(struct mfii_softc *sc,
   1409   1.1    bouyer     const struct mfi_evtarg_pd_address *pd)
   1410   1.1    bouyer {
   1411   1.1    bouyer 	printf("%s: physical disk inserted id %d enclosure %d\n", DEVNAME(sc),
   1412   1.1    bouyer 	    le16toh(pd->device_id), le16toh(pd->encl_id));
   1413   1.1    bouyer }
   1414   1.1    bouyer 
   1415   1.6      maxv static void
   1416   1.1    bouyer mfii_aen_pd_remove(struct mfii_softc *sc,
   1417   1.1    bouyer     const struct mfi_evtarg_pd_address *pd)
   1418   1.1    bouyer {
   1419   1.1    bouyer 	printf("%s: physical disk removed id %d enclosure %d\n", DEVNAME(sc),
   1420   1.1    bouyer 	    le16toh(pd->device_id), le16toh(pd->encl_id));
   1421   1.1    bouyer }
   1422   1.1    bouyer 
   1423   1.6      maxv static void
   1424   1.1    bouyer mfii_aen_pd_state_change(struct mfii_softc *sc,
   1425   1.1    bouyer     const struct mfi_evtarg_pd_state *state)
   1426   1.1    bouyer {
   1427   1.1    bouyer 	return;
   1428   1.1    bouyer }
   1429   1.1    bouyer 
   1430   1.6      maxv static void
   1431   1.1    bouyer mfii_aen_ld_update(struct mfii_softc *sc)
   1432   1.1    bouyer {
   1433  1.24   msaitoh 	union mfi_mbox mbox;
   1434  1.31  christos 	int i, target, old, nld;
   1435  1.24   msaitoh 	int newlds[MFII_MAX_LD_EXT];
   1436   1.1    bouyer 
   1437  1.24   msaitoh 	memset(&mbox, 0, sizeof(mbox));
   1438  1.24   msaitoh 	if (sc->sc_max256vd)
   1439  1.24   msaitoh 		mbox.b[0] = 1;
   1440   1.1    bouyer 	mutex_enter(&sc->sc_lock);
   1441  1.24   msaitoh 	if (mfii_mgmt(sc, MR_DCMD_LD_GET_LIST, &mbox, &sc->sc_ld_list,
   1442   1.1    bouyer 	    sizeof(sc->sc_ld_list), MFII_DATA_IN, false) != 0) {
   1443   1.1    bouyer 		mutex_exit(&sc->sc_lock);
   1444  1.19   msaitoh 		DNPRINTF(MFII_D_MISC,
   1445  1.19   msaitoh 		    "%s: getting list of logical disks failed\n", DEVNAME(sc));
   1446   1.1    bouyer 		return;
   1447   1.1    bouyer 	}
   1448   1.1    bouyer 	mutex_exit(&sc->sc_lock);
   1449   1.1    bouyer 
   1450   1.1    bouyer 	memset(newlds, -1, sizeof(newlds));
   1451   1.1    bouyer 
   1452   1.1    bouyer 	for (i = 0; i < sc->sc_ld_list.mll_no_ld; i++) {
   1453   1.1    bouyer 		target = sc->sc_ld_list.mll_list[i].mll_ld.mld_target;
   1454   1.1    bouyer 		DNPRINTF(MFII_D_MISC, "%s: target %d: state %d\n",
   1455   1.1    bouyer 		    DEVNAME(sc), target, sc->sc_ld_list.mll_list[i].mll_state);
   1456   1.1    bouyer 		newlds[target] = i;
   1457  1.25   msaitoh 		sc->sc_ld[i].ld_target_id = target;
   1458   1.1    bouyer 	}
   1459   1.1    bouyer 
   1460  1.24   msaitoh 	for (i = 0; i < MFII_MAX_LD_EXT; i++) {
   1461   1.1    bouyer 		old = sc->sc_target_lds[i];
   1462   1.1    bouyer 		nld = newlds[i];
   1463  1.10   msaitoh 
   1464   1.1    bouyer 		if (old == -1 && nld != -1) {
   1465   1.1    bouyer 			printf("%s: logical drive %d added (target %d)\n",
   1466   1.1    bouyer 			    DEVNAME(sc), i, nld);
   1467  1.29  christos 			sc->sc_ld[i].ld_present = 1;
   1468   1.1    bouyer 
   1469   1.1    bouyer 			// XXX scsi_probe_target(sc->sc_scsibus, i);
   1470   1.1    bouyer 
   1471  1.31  christos 			mfii_init_ld_sensor(sc, &sc->sc_ld_sensors[i], i);
   1472  1.31  christos 			mfii_attach_sensor(sc, &sc->sc_ld_sensors[i]);
   1473   1.1    bouyer 		} else if (nld == -1 && old != -1) {
   1474   1.1    bouyer 			printf("%s: logical drive %d removed (target %d)\n",
   1475   1.1    bouyer 			    DEVNAME(sc), i, old);
   1476  1.29  christos 			sc->sc_ld[i].ld_present = 0;
   1477   1.1    bouyer 
   1478   1.1    bouyer 			scsipi_target_detach(&sc->sc_chan, i, 0, DETACH_FORCE);
   1479   1.1    bouyer 			sysmon_envsys_sensor_detach(sc->sc_sme,
   1480  1.31  christos 			    &sc->sc_ld_sensors[i]);
   1481   1.1    bouyer 		}
   1482   1.1    bouyer 	}
   1483   1.1    bouyer 
   1484   1.1    bouyer 	memcpy(sc->sc_target_lds, newlds, sizeof(sc->sc_target_lds));
   1485   1.1    bouyer }
   1486   1.1    bouyer 
   1487   1.6      maxv static void
   1488   1.1    bouyer mfii_aen_unregister(struct mfii_softc *sc)
   1489   1.1    bouyer {
   1490   1.1    bouyer 	/* XXX */
   1491   1.1    bouyer }
   1492   1.1    bouyer 
   1493  1.32   msaitoh int
   1494  1.32   msaitoh mfii_reset_hard(struct mfii_softc *sc)
   1495  1.32   msaitoh {
   1496  1.32   msaitoh 	uint16_t		i;
   1497  1.32   msaitoh 
   1498  1.32   msaitoh 	mfii_write(sc, MFI_OSTS, 0);
   1499  1.32   msaitoh 
   1500  1.32   msaitoh 	/* enable diagnostic register */
   1501  1.32   msaitoh 	mfii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_FLUSH);
   1502  1.32   msaitoh 	mfii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_1);
   1503  1.32   msaitoh 	mfii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_2);
   1504  1.32   msaitoh 	mfii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_3);
   1505  1.32   msaitoh 	mfii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_4);
   1506  1.32   msaitoh 	mfii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_5);
   1507  1.32   msaitoh 	mfii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_6);
   1508  1.32   msaitoh 
   1509  1.32   msaitoh 	delay(100);
   1510  1.32   msaitoh 
   1511  1.32   msaitoh 	if ((mfii_read(sc, MPII_HOSTDIAG) & MPII_HOSTDIAG_DWRE) == 0) {
   1512  1.32   msaitoh 		aprint_error_dev(sc->sc_dev,
   1513  1.32   msaitoh 		    "failed to enable diagnostic read/write\n");
   1514  1.32   msaitoh 		return(1);
   1515  1.32   msaitoh 	}
   1516  1.32   msaitoh 
   1517  1.32   msaitoh 	/* reset ioc */
   1518  1.32   msaitoh 	mfii_write(sc, MPII_HOSTDIAG, MPII_HOSTDIAG_RESET_ADAPTER);
   1519  1.32   msaitoh 
   1520  1.32   msaitoh 	/* 240 milliseconds */
   1521  1.32   msaitoh 	delay(240000);
   1522  1.32   msaitoh 
   1523  1.32   msaitoh 	for (i = 0; i < 30000; i++) {
   1524  1.32   msaitoh 		if ((mfii_read(sc, MPII_HOSTDIAG) &
   1525  1.32   msaitoh 		    MPII_HOSTDIAG_RESET_ADAPTER) == 0)
   1526  1.32   msaitoh 			break;
   1527  1.32   msaitoh 		delay(10000);
   1528  1.32   msaitoh 	}
   1529  1.32   msaitoh 	if (i >= 30000) {
   1530  1.32   msaitoh 		aprint_error_dev(sc->sc_dev, "failed to reset device\n");
   1531  1.32   msaitoh 		return (1);
   1532  1.32   msaitoh 	}
   1533  1.32   msaitoh 
   1534  1.32   msaitoh 	/* disable diagnostic register */
   1535  1.32   msaitoh 	mfii_write(sc, MPII_WRITESEQ, 0xff);
   1536  1.32   msaitoh 
   1537  1.32   msaitoh 	return(0);
   1538  1.32   msaitoh }
   1539  1.32   msaitoh 
   1540   1.6      maxv static int
   1541   1.1    bouyer mfii_transition_firmware(struct mfii_softc *sc)
   1542   1.1    bouyer {
   1543   1.1    bouyer 	int32_t			fw_state, cur_state;
   1544  1.32   msaitoh 	int			max_wait, i, reset_on_fault = 1;
   1545   1.1    bouyer 
   1546   1.1    bouyer 	fw_state = mfii_fw_state(sc) & MFI_STATE_MASK;
   1547   1.1    bouyer 
   1548   1.1    bouyer 	while (fw_state != MFI_STATE_READY) {
   1549   1.1    bouyer 		cur_state = fw_state;
   1550   1.1    bouyer 		switch (fw_state) {
   1551   1.1    bouyer 		case MFI_STATE_FAULT:
   1552  1.32   msaitoh 			if (!reset_on_fault) {
   1553  1.32   msaitoh 				aprint_error_dev(sc->sc_dev,
   1554  1.32   msaitoh 				    "firmware fault\n");
   1555  1.32   msaitoh 				return (1);
   1556  1.32   msaitoh 			}
   1557  1.32   msaitoh 			aprint_verbose_dev(sc->sc_dev,
   1558  1.32   msaitoh 			    "firmware fault; attempting full device reset, "
   1559  1.32   msaitoh 			    "this can take some time\n");
   1560  1.32   msaitoh 			if (mfii_reset_hard(sc))
   1561  1.32   msaitoh 				return (1);
   1562  1.32   msaitoh 			max_wait = 20;
   1563  1.32   msaitoh 			reset_on_fault = 0;
   1564  1.32   msaitoh 			break;
   1565   1.1    bouyer 		case MFI_STATE_WAIT_HANDSHAKE:
   1566   1.1    bouyer 			mfii_write(sc, MFI_SKINNY_IDB,
   1567   1.1    bouyer 			    MFI_INIT_CLEAR_HANDSHAKE);
   1568   1.1    bouyer 			max_wait = 2;
   1569   1.1    bouyer 			break;
   1570   1.1    bouyer 		case MFI_STATE_OPERATIONAL:
   1571   1.1    bouyer 			mfii_write(sc, MFI_SKINNY_IDB, MFI_INIT_READY);
   1572   1.1    bouyer 			max_wait = 10;
   1573   1.1    bouyer 			break;
   1574   1.1    bouyer 		case MFI_STATE_BB_INIT:
   1575  1.32   msaitoh 			max_wait = 20;
   1576   1.1    bouyer 			break;
   1577  1.32   msaitoh 		case MFI_STATE_UNDEFINED:
   1578   1.1    bouyer 		case MFI_STATE_FW_INIT:
   1579  1.32   msaitoh 		case MFI_STATE_FW_INIT_2:
   1580   1.1    bouyer 		case MFI_STATE_DEVICE_SCAN:
   1581   1.1    bouyer 		case MFI_STATE_FLUSH_CACHE:
   1582  1.32   msaitoh 			max_wait = 40;
   1583  1.32   msaitoh 			break;
   1584  1.32   msaitoh 		case MFI_STATE_BOOT_MESSAGE_PENDING:
   1585  1.32   msaitoh 			mfii_write(sc, MFI_SKINNY_IDB, MFI_INIT_HOTPLUG);
   1586  1.32   msaitoh 			max_wait = 10;
   1587   1.1    bouyer 			break;
   1588   1.1    bouyer 		default:
   1589  1.32   msaitoh 			printf("%s: unknown firmware state %#x\n",
   1590   1.1    bouyer 			    DEVNAME(sc), fw_state);
   1591   1.1    bouyer 			return (1);
   1592   1.1    bouyer 		}
   1593   1.1    bouyer 		for (i = 0; i < (max_wait * 10); i++) {
   1594   1.1    bouyer 			fw_state = mfii_fw_state(sc) & MFI_STATE_MASK;
   1595   1.1    bouyer 			if (fw_state == cur_state)
   1596   1.1    bouyer 				DELAY(100000);
   1597   1.1    bouyer 			else
   1598   1.1    bouyer 				break;
   1599   1.1    bouyer 		}
   1600   1.1    bouyer 		if (fw_state == cur_state) {
   1601   1.1    bouyer 			printf("%s: firmware stuck in state %#x\n",
   1602   1.1    bouyer 			    DEVNAME(sc), fw_state);
   1603   1.1    bouyer 			return (1);
   1604  1.32   msaitoh 		} else {
   1605  1.32   msaitoh 			DPRINTF("%s: firmware state change %#x -> %#x after "
   1606  1.32   msaitoh 			    "%d iterations\n",
   1607  1.32   msaitoh 			    DEVNAME(sc), cur_state, fw_state, i);
   1608   1.1    bouyer 		}
   1609   1.1    bouyer 	}
   1610   1.1    bouyer 
   1611   1.1    bouyer 	return (0);
   1612   1.1    bouyer }
   1613   1.1    bouyer 
   1614   1.6      maxv static int
   1615   1.1    bouyer mfii_get_info(struct mfii_softc *sc)
   1616   1.1    bouyer {
   1617   1.1    bouyer 	int i, rv;
   1618   1.1    bouyer 
   1619   1.1    bouyer 	rv = mfii_mgmt(sc, MR_DCMD_CTRL_GET_INFO, NULL, &sc->sc_info,
   1620   1.1    bouyer 	    sizeof(sc->sc_info), MFII_DATA_IN, true);
   1621   1.1    bouyer 
   1622   1.1    bouyer 	if (rv != 0)
   1623   1.1    bouyer 		return (rv);
   1624   1.1    bouyer 
   1625   1.1    bouyer 	for (i = 0; i < sc->sc_info.mci_image_component_count; i++) {
   1626   1.1    bouyer 		DPRINTF("%s: active FW %s Version %s date %s time %s\n",
   1627   1.1    bouyer 		    DEVNAME(sc),
   1628   1.1    bouyer 		    sc->sc_info.mci_image_component[i].mic_name,
   1629   1.1    bouyer 		    sc->sc_info.mci_image_component[i].mic_version,
   1630   1.1    bouyer 		    sc->sc_info.mci_image_component[i].mic_build_date,
   1631   1.1    bouyer 		    sc->sc_info.mci_image_component[i].mic_build_time);
   1632   1.1    bouyer 	}
   1633   1.1    bouyer 
   1634   1.1    bouyer 	for (i = 0; i < sc->sc_info.mci_pending_image_component_count; i++) {
   1635   1.1    bouyer 		DPRINTF("%s: pending FW %s Version %s date %s time %s\n",
   1636   1.1    bouyer 		    DEVNAME(sc),
   1637   1.1    bouyer 		    sc->sc_info.mci_pending_image_component[i].mic_name,
   1638   1.1    bouyer 		    sc->sc_info.mci_pending_image_component[i].mic_version,
   1639   1.1    bouyer 		    sc->sc_info.mci_pending_image_component[i].mic_build_date,
   1640   1.1    bouyer 		    sc->sc_info.mci_pending_image_component[i].mic_build_time);
   1641   1.1    bouyer 	}
   1642   1.1    bouyer 
   1643   1.1    bouyer 	DPRINTF("%s: max_arms %d max_spans %d max_arrs %d max_lds %d name %s\n",
   1644   1.1    bouyer 	    DEVNAME(sc),
   1645   1.1    bouyer 	    sc->sc_info.mci_max_arms,
   1646   1.1    bouyer 	    sc->sc_info.mci_max_spans,
   1647   1.1    bouyer 	    sc->sc_info.mci_max_arrays,
   1648   1.1    bouyer 	    sc->sc_info.mci_max_lds,
   1649   1.1    bouyer 	    sc->sc_info.mci_product_name);
   1650   1.1    bouyer 
   1651   1.1    bouyer 	DPRINTF("%s: serial %s present %#x fw time %d max_cmds %d max_sg %d\n",
   1652   1.1    bouyer 	    DEVNAME(sc),
   1653   1.1    bouyer 	    sc->sc_info.mci_serial_number,
   1654   1.1    bouyer 	    sc->sc_info.mci_hw_present,
   1655   1.1    bouyer 	    sc->sc_info.mci_current_fw_time,
   1656   1.1    bouyer 	    sc->sc_info.mci_max_cmds,
   1657   1.1    bouyer 	    sc->sc_info.mci_max_sg_elements);
   1658   1.1    bouyer 
   1659   1.1    bouyer 	DPRINTF("%s: max_rq %d lds_pres %d lds_deg %d lds_off %d pd_pres %d\n",
   1660   1.1    bouyer 	    DEVNAME(sc),
   1661   1.1    bouyer 	    sc->sc_info.mci_max_request_size,
   1662   1.1    bouyer 	    sc->sc_info.mci_lds_present,
   1663   1.1    bouyer 	    sc->sc_info.mci_lds_degraded,
   1664   1.1    bouyer 	    sc->sc_info.mci_lds_offline,
   1665   1.1    bouyer 	    sc->sc_info.mci_pd_present);
   1666   1.1    bouyer 
   1667   1.1    bouyer 	DPRINTF("%s: pd_dsk_prs %d pd_dsk_pred_fail %d pd_dsk_fail %d\n",
   1668   1.1    bouyer 	    DEVNAME(sc),
   1669   1.1    bouyer 	    sc->sc_info.mci_pd_disks_present,
   1670   1.1    bouyer 	    sc->sc_info.mci_pd_disks_pred_failure,
   1671   1.1    bouyer 	    sc->sc_info.mci_pd_disks_failed);
   1672   1.1    bouyer 
   1673   1.1    bouyer 	DPRINTF("%s: nvram %d mem %d flash %d\n",
   1674   1.1    bouyer 	    DEVNAME(sc),
   1675   1.1    bouyer 	    sc->sc_info.mci_nvram_size,
   1676   1.1    bouyer 	    sc->sc_info.mci_memory_size,
   1677   1.1    bouyer 	    sc->sc_info.mci_flash_size);
   1678   1.1    bouyer 
   1679   1.1    bouyer 	DPRINTF("%s: ram_cor %d ram_uncor %d clus_all %d clus_act %d\n",
   1680   1.1    bouyer 	    DEVNAME(sc),
   1681   1.1    bouyer 	    sc->sc_info.mci_ram_correctable_errors,
   1682   1.1    bouyer 	    sc->sc_info.mci_ram_uncorrectable_errors,
   1683   1.1    bouyer 	    sc->sc_info.mci_cluster_allowed,
   1684   1.1    bouyer 	    sc->sc_info.mci_cluster_active);
   1685   1.1    bouyer 
   1686   1.1    bouyer 	DPRINTF("%s: max_strps_io %d raid_lvl %#x adapt_ops %#x ld_ops %#x\n",
   1687   1.1    bouyer 	    DEVNAME(sc),
   1688   1.1    bouyer 	    sc->sc_info.mci_max_strips_per_io,
   1689   1.1    bouyer 	    sc->sc_info.mci_raid_levels,
   1690   1.1    bouyer 	    sc->sc_info.mci_adapter_ops,
   1691   1.1    bouyer 	    sc->sc_info.mci_ld_ops);
   1692   1.1    bouyer 
   1693   1.1    bouyer 	DPRINTF("%s: strp_sz_min %d strp_sz_max %d pd_ops %#x pd_mix %#x\n",
   1694   1.1    bouyer 	    DEVNAME(sc),
   1695   1.1    bouyer 	    sc->sc_info.mci_stripe_sz_ops.min,
   1696   1.1    bouyer 	    sc->sc_info.mci_stripe_sz_ops.max,
   1697   1.1    bouyer 	    sc->sc_info.mci_pd_ops,
   1698   1.1    bouyer 	    sc->sc_info.mci_pd_mix_support);
   1699   1.1    bouyer 
   1700   1.1    bouyer 	DPRINTF("%s: ecc_bucket %d pckg_prop %s\n",
   1701   1.1    bouyer 	    DEVNAME(sc),
   1702   1.1    bouyer 	    sc->sc_info.mci_ecc_bucket_count,
   1703   1.1    bouyer 	    sc->sc_info.mci_package_version);
   1704   1.1    bouyer 
   1705   1.1    bouyer 	DPRINTF("%s: sq_nm %d prd_fail_poll %d intr_thrtl %d intr_thrtl_to %d\n",
   1706   1.1    bouyer 	    DEVNAME(sc),
   1707   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_seq_num,
   1708   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_pred_fail_poll_interval,
   1709   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_intr_throttle_cnt,
   1710   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_intr_throttle_timeout);
   1711   1.1    bouyer 
   1712   1.1    bouyer 	DPRINTF("%s: rbld_rate %d patr_rd_rate %d bgi_rate %d cc_rate %d\n",
   1713   1.1    bouyer 	    DEVNAME(sc),
   1714   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_rebuild_rate,
   1715   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_patrol_read_rate,
   1716   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_bgi_rate,
   1717   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_cc_rate);
   1718   1.1    bouyer 
   1719   1.1    bouyer 	DPRINTF("%s: rc_rate %d ch_flsh %d spin_cnt %d spin_dly %d clus_en %d\n",
   1720   1.1    bouyer 	    DEVNAME(sc),
   1721   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_recon_rate,
   1722   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_cache_flush_interval,
   1723   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_spinup_drv_cnt,
   1724   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_spinup_delay,
   1725   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_cluster_enable);
   1726   1.1    bouyer 
   1727   1.1    bouyer 	DPRINTF("%s: coerc %d alarm %d dis_auto_rbld %d dis_bat_wrn %d ecc %d\n",
   1728   1.1    bouyer 	    DEVNAME(sc),
   1729   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_coercion_mode,
   1730   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_alarm_enable,
   1731   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_disable_auto_rebuild,
   1732   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_disable_battery_warn,
   1733   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_ecc_bucket_size);
   1734   1.1    bouyer 
   1735   1.1    bouyer 	DPRINTF("%s: ecc_leak %d rest_hs %d exp_encl_dev %d\n",
   1736   1.1    bouyer 	    DEVNAME(sc),
   1737   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_ecc_bucket_leak_rate,
   1738   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_restore_hotspare_on_insertion,
   1739   1.1    bouyer 	    sc->sc_info.mci_properties.mcp_expose_encl_devices);
   1740   1.1    bouyer 
   1741   1.1    bouyer 	DPRINTF("%s: vendor %#x device %#x subvendor %#x subdevice %#x\n",
   1742   1.1    bouyer 	    DEVNAME(sc),
   1743   1.1    bouyer 	    sc->sc_info.mci_pci.mip_vendor,
   1744   1.1    bouyer 	    sc->sc_info.mci_pci.mip_device,
   1745   1.1    bouyer 	    sc->sc_info.mci_pci.mip_subvendor,
   1746   1.1    bouyer 	    sc->sc_info.mci_pci.mip_subdevice);
   1747   1.1    bouyer 
   1748   1.1    bouyer 	DPRINTF("%s: type %#x port_count %d port_addr ",
   1749   1.1    bouyer 	    DEVNAME(sc),
   1750   1.1    bouyer 	    sc->sc_info.mci_host.mih_type,
   1751   1.1    bouyer 	    sc->sc_info.mci_host.mih_port_count);
   1752   1.1    bouyer 
   1753   1.1    bouyer 	for (i = 0; i < 8; i++)
   1754  1.19   msaitoh 		DPRINTF("%.0" PRIx64 " ",
   1755  1.19   msaitoh 		    sc->sc_info.mci_host.mih_port_addr[i]);
   1756   1.1    bouyer 	DPRINTF("\n");
   1757   1.1    bouyer 
   1758   1.1    bouyer 	DPRINTF("%s: type %.x port_count %d port_addr ",
   1759   1.1    bouyer 	    DEVNAME(sc),
   1760   1.1    bouyer 	    sc->sc_info.mci_device.mid_type,
   1761   1.1    bouyer 	    sc->sc_info.mci_device.mid_port_count);
   1762   1.1    bouyer 
   1763   1.1    bouyer 	for (i = 0; i < 8; i++)
   1764  1.19   msaitoh 		DPRINTF("%.0" PRIx64 " ",
   1765  1.19   msaitoh 		    sc->sc_info.mci_device.mid_port_addr[i]);
   1766   1.1    bouyer 	DPRINTF("\n");
   1767   1.1    bouyer 
   1768   1.1    bouyer 	return (0);
   1769   1.1    bouyer }
   1770   1.1    bouyer 
   1771   1.6      maxv static int
   1772   1.1    bouyer mfii_mfa_poll(struct mfii_softc *sc, struct mfii_ccb *ccb)
   1773   1.1    bouyer {
   1774   1.1    bouyer 	struct mfi_frame_header	*hdr = ccb->ccb_request;
   1775   1.1    bouyer 	u_int64_t r;
   1776   1.1    bouyer 	int to = 0, rv = 0;
   1777   1.1    bouyer 
   1778   1.1    bouyer #ifdef DIAGNOSTIC
   1779   1.1    bouyer 	if (ccb->ccb_cookie != NULL || ccb->ccb_done != NULL)
   1780   1.1    bouyer 		panic("mfii_mfa_poll called with cookie or done set");
   1781   1.1    bouyer #endif
   1782   1.1    bouyer 
   1783   1.1    bouyer 	hdr->mfh_context = ccb->ccb_smid;
   1784   1.1    bouyer 	hdr->mfh_cmd_status = MFI_STAT_INVALID_STATUS;
   1785   1.1    bouyer 	hdr->mfh_flags |= htole16(MFI_FRAME_DONT_POST_IN_REPLY_QUEUE);
   1786   1.1    bouyer 
   1787   1.1    bouyer 	r = MFII_REQ_MFA(ccb->ccb_request_dva);
   1788   1.1    bouyer 	memcpy(&ccb->ccb_req, &r, sizeof(ccb->ccb_req));
   1789   1.1    bouyer 
   1790  1.23   msaitoh 	/*
   1791  1.23   msaitoh 	 * Even if the Aero card supports 32bit descriptor, 64bit descriptor
   1792  1.23   msaitoh 	 * access is required for MFI_CMD_INIT.
   1793  1.23   msaitoh 	 * Currently, mfii_mfa_poll() is called for MFI_CMD_INIT only.
   1794  1.23   msaitoh 	 */
   1795  1.23   msaitoh 	mfii_start64(sc, ccb);
   1796   1.1    bouyer 
   1797   1.1    bouyer 	for (;;) {
   1798   1.1    bouyer 		bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_requests),
   1799   1.1    bouyer 		    ccb->ccb_request_offset, MFII_REQUEST_SIZE,
   1800   1.1    bouyer 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
   1801   1.1    bouyer 
   1802   1.1    bouyer 		if (hdr->mfh_cmd_status != MFI_STAT_INVALID_STATUS)
   1803   1.1    bouyer 			break;
   1804   1.1    bouyer 
   1805   1.1    bouyer 		if (to++ > 5000) { /* XXX 5 seconds busywait sucks */
   1806   1.1    bouyer 			printf("%s: timeout on ccb %d\n", DEVNAME(sc),
   1807   1.1    bouyer 			    ccb->ccb_smid);
   1808   1.1    bouyer 			ccb->ccb_flags |= MFI_CCB_F_ERR;
   1809   1.1    bouyer 			rv = 1;
   1810   1.1    bouyer 			break;
   1811   1.1    bouyer 		}
   1812   1.1    bouyer 
   1813   1.1    bouyer 		bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_requests),
   1814   1.1    bouyer 		    ccb->ccb_request_offset, MFII_REQUEST_SIZE,
   1815   1.1    bouyer 		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
   1816   1.1    bouyer 
   1817   1.1    bouyer 		delay(1000);
   1818   1.1    bouyer 	}
   1819   1.1    bouyer 
   1820   1.1    bouyer 	if (ccb->ccb_len > 0) {
   1821   1.1    bouyer 		bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap32,
   1822   1.1    bouyer 		    0, ccb->ccb_dmamap32->dm_mapsize,
   1823   1.1    bouyer 		    (ccb->ccb_direction == MFII_DATA_IN) ?
   1824   1.1    bouyer 		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
   1825   1.1    bouyer 
   1826   1.1    bouyer 		bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap32);
   1827   1.1    bouyer 	}
   1828   1.1    bouyer 
   1829   1.1    bouyer 	return (rv);
   1830   1.1    bouyer }
   1831   1.1    bouyer 
   1832   1.6      maxv static int
   1833   1.1    bouyer mfii_poll(struct mfii_softc *sc, struct mfii_ccb *ccb)
   1834   1.1    bouyer {
   1835   1.1    bouyer 	void (*done)(struct mfii_softc *, struct mfii_ccb *);
   1836   1.1    bouyer 	void *cookie;
   1837   1.1    bouyer 	int rv = 1;
   1838   1.1    bouyer 
   1839   1.1    bouyer 	done = ccb->ccb_done;
   1840   1.1    bouyer 	cookie = ccb->ccb_cookie;
   1841   1.1    bouyer 
   1842   1.1    bouyer 	ccb->ccb_done = mfii_poll_done;
   1843   1.1    bouyer 	ccb->ccb_cookie = &rv;
   1844   1.1    bouyer 
   1845   1.1    bouyer 	mfii_start(sc, ccb);
   1846   1.1    bouyer 
   1847   1.1    bouyer 	do {
   1848   1.1    bouyer 		delay(10);
   1849   1.1    bouyer 		mfii_postq(sc);
   1850   1.1    bouyer 	} while (rv == 1);
   1851   1.1    bouyer 
   1852   1.1    bouyer 	ccb->ccb_cookie = cookie;
   1853   1.1    bouyer 	done(sc, ccb);
   1854   1.1    bouyer 
   1855   1.1    bouyer 	return (0);
   1856   1.1    bouyer }
   1857   1.1    bouyer 
   1858   1.6      maxv static void
   1859   1.1    bouyer mfii_poll_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
   1860   1.1    bouyer {
   1861   1.1    bouyer 	int *rv = ccb->ccb_cookie;
   1862   1.1    bouyer 
   1863   1.1    bouyer 	*rv = 0;
   1864   1.1    bouyer }
   1865   1.1    bouyer 
   1866   1.6      maxv static int
   1867   1.1    bouyer mfii_exec(struct mfii_softc *sc, struct mfii_ccb *ccb)
   1868   1.1    bouyer {
   1869   1.1    bouyer #ifdef DIAGNOSTIC
   1870   1.1    bouyer 	if (ccb->ccb_cookie != NULL || ccb->ccb_done != NULL)
   1871   1.1    bouyer 		panic("mfii_exec called with cookie or done set");
   1872   1.1    bouyer #endif
   1873   1.1    bouyer 
   1874   1.1    bouyer 	ccb->ccb_cookie = ccb;
   1875   1.1    bouyer 	ccb->ccb_done = mfii_exec_done;
   1876   1.1    bouyer 
   1877   1.1    bouyer 	mfii_start(sc, ccb);
   1878   1.1    bouyer 
   1879   1.1    bouyer 	mutex_enter(&ccb->ccb_mtx);
   1880   1.1    bouyer 	while (ccb->ccb_cookie != NULL)
   1881   1.1    bouyer 		cv_wait(&ccb->ccb_cv, &ccb->ccb_mtx);
   1882   1.1    bouyer 	mutex_exit(&ccb->ccb_mtx);
   1883   1.1    bouyer 
   1884   1.1    bouyer 	return (0);
   1885   1.1    bouyer }
   1886   1.1    bouyer 
   1887   1.6      maxv static void
   1888   1.1    bouyer mfii_exec_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
   1889   1.1    bouyer {
   1890   1.1    bouyer 	mutex_enter(&ccb->ccb_mtx);
   1891   1.1    bouyer 	ccb->ccb_cookie = NULL;
   1892   1.1    bouyer 	cv_signal(&ccb->ccb_cv);
   1893   1.1    bouyer 	mutex_exit(&ccb->ccb_mtx);
   1894   1.1    bouyer }
   1895   1.1    bouyer 
   1896   1.6      maxv static int
   1897   1.1    bouyer mfii_mgmt(struct mfii_softc *sc, uint32_t opc, const union mfi_mbox *mbox,
   1898   1.1    bouyer     void *buf, size_t len, mfii_direction_t dir, bool poll)
   1899   1.1    bouyer {
   1900   1.1    bouyer 	struct mfii_ccb *ccb;
   1901   1.1    bouyer 	int rv;
   1902   1.1    bouyer 
   1903   1.1    bouyer 	KASSERT(mutex_owned(&sc->sc_lock));
   1904   1.1    bouyer 	if (!sc->sc_running)
   1905   1.1    bouyer 		return EAGAIN;
   1906   1.1    bouyer 
   1907   1.1    bouyer 	ccb = mfii_get_ccb(sc);
   1908   1.1    bouyer 	if (ccb == NULL)
   1909   1.1    bouyer 		return (ENOMEM);
   1910   1.1    bouyer 
   1911   1.1    bouyer 	mfii_scrub_ccb(ccb);
   1912   1.1    bouyer 	rv = mfii_do_mgmt(sc, ccb, opc, mbox, buf, len, dir, poll);
   1913   1.1    bouyer 	mfii_put_ccb(sc, ccb);
   1914   1.1    bouyer 
   1915   1.1    bouyer 	return (rv);
   1916   1.1    bouyer }
   1917   1.1    bouyer 
   1918   1.6      maxv static int
   1919   1.1    bouyer mfii_do_mgmt(struct mfii_softc *sc, struct mfii_ccb *ccb, uint32_t opc,
   1920   1.1    bouyer     const union mfi_mbox *mbox, void *buf, size_t len, mfii_direction_t dir,
   1921   1.1    bouyer     bool poll)
   1922   1.1    bouyer {
   1923   1.1    bouyer 	struct mpii_msg_scsi_io *io = ccb->ccb_request;
   1924   1.1    bouyer 	struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
   1925   1.1    bouyer 	struct mfii_sge *sge = (struct mfii_sge *)(ctx + 1);
   1926   1.1    bouyer 	struct mfi_dcmd_frame *dcmd = ccb->ccb_mfi;
   1927   1.1    bouyer 	struct mfi_frame_header *hdr = &dcmd->mdf_header;
   1928   1.1    bouyer 	int rv = EIO;
   1929   1.1    bouyer 
   1930   1.1    bouyer 	if (cold)
   1931   1.1    bouyer 		poll = true;
   1932   1.1    bouyer 
   1933   1.1    bouyer 	ccb->ccb_data = buf;
   1934   1.1    bouyer 	ccb->ccb_len = len;
   1935   1.1    bouyer 	ccb->ccb_direction = dir;
   1936   1.1    bouyer 	switch (dir) {
   1937   1.1    bouyer 	case MFII_DATA_IN:
   1938   1.1    bouyer 		hdr->mfh_flags = htole16(MFI_FRAME_DIR_READ);
   1939   1.1    bouyer 		break;
   1940   1.1    bouyer 	case MFII_DATA_OUT:
   1941   1.1    bouyer 		hdr->mfh_flags = htole16(MFI_FRAME_DIR_WRITE);
   1942   1.1    bouyer 		break;
   1943   1.1    bouyer 	case MFII_DATA_NONE:
   1944   1.1    bouyer 		hdr->mfh_flags = htole16(MFI_FRAME_DIR_NONE);
   1945   1.1    bouyer 		break;
   1946   1.1    bouyer 	}
   1947   1.1    bouyer 
   1948   1.1    bouyer 	if (mfii_load_mfa(sc, ccb, &dcmd->mdf_sgl, poll) != 0) {
   1949   1.1    bouyer 		rv = ENOMEM;
   1950   1.1    bouyer 		goto done;
   1951   1.1    bouyer 	}
   1952   1.1    bouyer 
   1953   1.1    bouyer 	hdr->mfh_cmd = MFI_CMD_DCMD;
   1954   1.1    bouyer 	hdr->mfh_context = ccb->ccb_smid;
   1955   1.1    bouyer 	hdr->mfh_data_len = htole32(len);
   1956   1.1    bouyer 	hdr->mfh_sg_count = ccb->ccb_dmamap32->dm_nsegs;
   1957   1.1    bouyer 	KASSERT(!ccb->ccb_dma64);
   1958   1.1    bouyer 
   1959   1.1    bouyer 	dcmd->mdf_opcode = opc;
   1960   1.1    bouyer 	/* handle special opcodes */
   1961   1.1    bouyer 	if (mbox != NULL)
   1962   1.1    bouyer 		memcpy(&dcmd->mdf_mbox, mbox, sizeof(dcmd->mdf_mbox));
   1963   1.1    bouyer 
   1964   1.1    bouyer 	io->function = MFII_FUNCTION_PASSTHRU_IO;
   1965   1.1    bouyer 	io->sgl_offset0 = ((u_int8_t *)sge - (u_int8_t *)io) / 4;
   1966   1.1    bouyer 	io->chain_offset = ((u_int8_t *)sge - (u_int8_t *)io) / 16;
   1967   1.1    bouyer 
   1968   1.1    bouyer 	sge->sg_addr = htole64(ccb->ccb_mfi_dva);
   1969   1.1    bouyer 	sge->sg_len = htole32(MFI_FRAME_SIZE);
   1970   1.1    bouyer 	sge->sg_flags = MFII_SGE_CHAIN_ELEMENT | MFII_SGE_ADDR_IOCPLBNTA;
   1971   1.1    bouyer 
   1972   1.1    bouyer 	ccb->ccb_req.flags = MFII_REQ_TYPE_SCSI;
   1973   1.1    bouyer 	ccb->ccb_req.smid = le16toh(ccb->ccb_smid);
   1974   1.1    bouyer 
   1975   1.1    bouyer 	if (poll) {
   1976   1.1    bouyer 		ccb->ccb_done = mfii_empty_done;
   1977   1.1    bouyer 		mfii_poll(sc, ccb);
   1978   1.1    bouyer 	} else
   1979   1.1    bouyer 		mfii_exec(sc, ccb);
   1980   1.1    bouyer 
   1981   1.1    bouyer 	if (hdr->mfh_cmd_status == MFI_STAT_OK) {
   1982   1.1    bouyer 		rv = 0;
   1983   1.1    bouyer 	}
   1984   1.1    bouyer 
   1985   1.1    bouyer done:
   1986   1.1    bouyer 	return (rv);
   1987   1.1    bouyer }
   1988   1.1    bouyer 
   1989   1.6      maxv static void
   1990   1.1    bouyer mfii_empty_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
   1991   1.1    bouyer {
   1992   1.1    bouyer 	return;
   1993   1.1    bouyer }
   1994   1.1    bouyer 
   1995   1.6      maxv static int
   1996   1.1    bouyer mfii_load_mfa(struct mfii_softc *sc, struct mfii_ccb *ccb,
   1997   1.1    bouyer     void *sglp, int nosleep)
   1998   1.1    bouyer {
   1999   1.1    bouyer 	union mfi_sgl *sgl = sglp;
   2000   1.1    bouyer 	bus_dmamap_t dmap = ccb->ccb_dmamap32;
   2001   1.1    bouyer 	int error;
   2002   1.1    bouyer 	int i;
   2003   1.1    bouyer 
   2004   1.1    bouyer 	KASSERT(!ccb->ccb_dma64);
   2005   1.1    bouyer 	if (ccb->ccb_len == 0)
   2006   1.1    bouyer 		return (0);
   2007   1.1    bouyer 
   2008   1.1    bouyer 	error = bus_dmamap_load(sc->sc_dmat, dmap,
   2009   1.1    bouyer 	    ccb->ccb_data, ccb->ccb_len, NULL,
   2010   1.1    bouyer 	    nosleep ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
   2011   1.1    bouyer 	if (error) {
   2012   1.1    bouyer 		printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
   2013   1.1    bouyer 		return (1);
   2014   1.1    bouyer 	}
   2015   1.1    bouyer 
   2016   1.1    bouyer 	for (i = 0; i < dmap->dm_nsegs; i++) {
   2017   1.1    bouyer 		sgl->sg32[i].addr = htole32(dmap->dm_segs[i].ds_addr);
   2018   1.1    bouyer 		sgl->sg32[i].len = htole32(dmap->dm_segs[i].ds_len);
   2019   1.1    bouyer 	}
   2020   1.1    bouyer 
   2021   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
   2022   1.1    bouyer 	    ccb->ccb_direction == MFII_DATA_OUT ?
   2023   1.1    bouyer 	    BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
   2024   1.1    bouyer 
   2025   1.1    bouyer 	return (0);
   2026   1.1    bouyer }
   2027   1.1    bouyer 
   2028   1.6      maxv static void
   2029   1.1    bouyer mfii_start(struct mfii_softc *sc, struct mfii_ccb *ccb)
   2030   1.1    bouyer {
   2031  1.23   msaitoh 
   2032  1.23   msaitoh 	mfii_start_common(sc, ccb,
   2033  1.23   msaitoh 	    ((sc->sc_iop_flag & MFII_IOP_DESC_32BIT) != 0) ? true : false);
   2034  1.23   msaitoh }
   2035  1.23   msaitoh 
   2036  1.23   msaitoh static void
   2037  1.23   msaitoh mfii_start64(struct mfii_softc *sc, struct mfii_ccb *ccb)
   2038  1.23   msaitoh {
   2039  1.23   msaitoh 
   2040  1.23   msaitoh 	mfii_start_common(sc, ccb, false);
   2041  1.23   msaitoh }
   2042  1.23   msaitoh 
   2043  1.23   msaitoh static void
   2044  1.23   msaitoh mfii_start_common(struct mfii_softc *sc, struct mfii_ccb *ccb, bool do32)
   2045  1.23   msaitoh {
   2046  1.16   msaitoh 	uint32_t *r = (uint32_t *)&ccb->ccb_req;
   2047   1.1    bouyer 
   2048   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_requests),
   2049   1.1    bouyer 	    ccb->ccb_request_offset, MFII_REQUEST_SIZE,
   2050   1.1    bouyer 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
   2051   1.1    bouyer 
   2052  1.23   msaitoh 	if (do32)
   2053  1.23   msaitoh 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, MFI_ISQP, r[0]);
   2054  1.23   msaitoh 	else {
   2055  1.22   msaitoh #if defined(__LP64__)
   2056  1.23   msaitoh 		uint64_t buf;
   2057  1.23   msaitoh 
   2058  1.23   msaitoh 		buf = ((uint64_t)r[1] << 32) | r[0];
   2059  1.23   msaitoh 		bus_space_write_8(sc->sc_iot, sc->sc_ioh, MFI_IQPL, buf);
   2060   1.1    bouyer #else
   2061  1.23   msaitoh 		mutex_enter(&sc->sc_post_mtx);
   2062  1.23   msaitoh 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, MFI_IQPL, r[0]);
   2063  1.23   msaitoh 		bus_space_write_4(sc->sc_iot, sc->sc_ioh, MFI_IQPH, r[1]);
   2064  1.23   msaitoh 		bus_space_barrier(sc->sc_iot, sc->sc_ioh,
   2065  1.23   msaitoh 		    MFI_IQPL, 8, BUS_SPACE_BARRIER_WRITE);
   2066  1.23   msaitoh 		mutex_exit(&sc->sc_post_mtx);
   2067   1.1    bouyer #endif
   2068  1.23   msaitoh 	}
   2069   1.1    bouyer }
   2070   1.1    bouyer 
   2071   1.6      maxv static void
   2072   1.1    bouyer mfii_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
   2073   1.1    bouyer {
   2074   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_requests),
   2075   1.1    bouyer 	    ccb->ccb_request_offset, MFII_REQUEST_SIZE,
   2076   1.1    bouyer 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
   2077   1.1    bouyer 
   2078   1.1    bouyer 	if (ccb->ccb_sgl_len > 0) {
   2079   1.1    bouyer 		bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_sgl),
   2080   1.1    bouyer 		    ccb->ccb_sgl_offset, ccb->ccb_sgl_len,
   2081   1.1    bouyer 		    BUS_DMASYNC_POSTWRITE);
   2082   1.1    bouyer 	}
   2083   1.1    bouyer 
   2084   1.1    bouyer 	if (ccb->ccb_dma64) {
   2085   1.1    bouyer 		KASSERT(ccb->ccb_len > 0);
   2086   1.1    bouyer 		bus_dmamap_sync(sc->sc_dmat64, ccb->ccb_dmamap64,
   2087   1.1    bouyer 		    0, ccb->ccb_dmamap64->dm_mapsize,
   2088   1.1    bouyer 		    (ccb->ccb_direction == MFII_DATA_IN) ?
   2089   1.1    bouyer 		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
   2090   1.1    bouyer 
   2091   1.1    bouyer 		bus_dmamap_unload(sc->sc_dmat64, ccb->ccb_dmamap64);
   2092   1.1    bouyer 	} else if (ccb->ccb_len > 0) {
   2093   1.1    bouyer 		bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap32,
   2094   1.1    bouyer 		    0, ccb->ccb_dmamap32->dm_mapsize,
   2095   1.1    bouyer 		    (ccb->ccb_direction == MFII_DATA_IN) ?
   2096   1.1    bouyer 		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
   2097   1.1    bouyer 
   2098   1.1    bouyer 		bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap32);
   2099   1.1    bouyer 	}
   2100   1.1    bouyer 
   2101   1.1    bouyer 	ccb->ccb_done(sc, ccb);
   2102   1.1    bouyer }
   2103   1.1    bouyer 
   2104   1.6      maxv static int
   2105   1.1    bouyer mfii_initialise_firmware(struct mfii_softc *sc)
   2106   1.1    bouyer {
   2107   1.1    bouyer 	struct mpii_msg_iocinit_request *iiq;
   2108   1.1    bouyer 	struct mfii_dmamem *m;
   2109   1.1    bouyer 	struct mfii_ccb *ccb;
   2110   1.1    bouyer 	struct mfi_init_frame *init;
   2111   1.1    bouyer 	int rv;
   2112   1.1    bouyer 
   2113   1.1    bouyer 	m = mfii_dmamem_alloc(sc, sizeof(*iiq));
   2114   1.1    bouyer 	if (m == NULL)
   2115   1.1    bouyer 		return (1);
   2116   1.1    bouyer 
   2117   1.1    bouyer 	iiq = MFII_DMA_KVA(m);
   2118   1.1    bouyer 	memset(iiq, 0, sizeof(*iiq));
   2119   1.1    bouyer 
   2120   1.1    bouyer 	iiq->function = MPII_FUNCTION_IOC_INIT;
   2121   1.1    bouyer 	iiq->whoinit = MPII_WHOINIT_HOST_DRIVER;
   2122   1.1    bouyer 
   2123   1.1    bouyer 	iiq->msg_version_maj = 0x02;
   2124   1.1    bouyer 	iiq->msg_version_min = 0x00;
   2125   1.1    bouyer 	iiq->hdr_version_unit = 0x10;
   2126   1.1    bouyer 	iiq->hdr_version_dev = 0x0;
   2127   1.1    bouyer 
   2128   1.1    bouyer 	iiq->system_request_frame_size = htole16(MFII_REQUEST_SIZE / 4);
   2129   1.1    bouyer 
   2130   1.1    bouyer 	iiq->reply_descriptor_post_queue_depth =
   2131   1.1    bouyer 	    htole16(sc->sc_reply_postq_depth);
   2132   1.1    bouyer 	iiq->reply_free_queue_depth = htole16(0);
   2133   1.1    bouyer 
   2134   1.1    bouyer 	iiq->sense_buffer_address_high = htole32(
   2135   1.1    bouyer 	    MFII_DMA_DVA(sc->sc_sense) >> 32);
   2136   1.1    bouyer 
   2137   1.3    bouyer 	iiq->reply_descriptor_post_queue_address_lo =
   2138   1.3    bouyer 	    htole32(MFII_DMA_DVA(sc->sc_reply_postq));
   2139   1.3    bouyer 	iiq->reply_descriptor_post_queue_address_hi =
   2140   1.3    bouyer 	    htole32(MFII_DMA_DVA(sc->sc_reply_postq) >> 32);
   2141   1.3    bouyer 
   2142  1.10   msaitoh 	iiq->system_request_frame_base_address_lo =
   2143   1.3    bouyer 	    htole32(MFII_DMA_DVA(sc->sc_requests));
   2144  1.10   msaitoh 	iiq->system_request_frame_base_address_hi =
   2145   1.3    bouyer 	    htole32(MFII_DMA_DVA(sc->sc_requests) >> 32);
   2146   1.1    bouyer 
   2147   1.1    bouyer 	iiq->timestamp = htole64(time_uptime);
   2148   1.1    bouyer 
   2149   1.1    bouyer 	ccb = mfii_get_ccb(sc);
   2150   1.1    bouyer 	if (ccb == NULL) {
   2151   1.1    bouyer 		/* shouldn't ever run out of ccbs during attach */
   2152   1.1    bouyer 		return (1);
   2153   1.1    bouyer 	}
   2154   1.1    bouyer 	mfii_scrub_ccb(ccb);
   2155   1.1    bouyer 	init = ccb->ccb_request;
   2156   1.1    bouyer 
   2157   1.1    bouyer 	init->mif_header.mfh_cmd = MFI_CMD_INIT;
   2158   1.1    bouyer 	init->mif_header.mfh_data_len = htole32(sizeof(*iiq));
   2159   1.1    bouyer 	init->mif_qinfo_new_addr_lo = htole32(MFII_DMA_DVA(m));
   2160   1.1    bouyer 	init->mif_qinfo_new_addr_hi = htole32((uint64_t)MFII_DMA_DVA(m) >> 32);
   2161   1.1    bouyer 
   2162   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_reply_postq),
   2163   1.1    bouyer 	    0, MFII_DMA_LEN(sc->sc_reply_postq),
   2164   1.1    bouyer 	    BUS_DMASYNC_PREREAD);
   2165   1.1    bouyer 
   2166   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(m),
   2167   1.1    bouyer 	    0, sizeof(*iiq), BUS_DMASYNC_PREREAD);
   2168   1.1    bouyer 
   2169   1.1    bouyer 	rv = mfii_mfa_poll(sc, ccb);
   2170   1.1    bouyer 
   2171   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(m),
   2172   1.1    bouyer 	    0, sizeof(*iiq), BUS_DMASYNC_POSTREAD);
   2173   1.1    bouyer 
   2174   1.1    bouyer 	mfii_put_ccb(sc, ccb);
   2175   1.1    bouyer 	mfii_dmamem_free(sc, m);
   2176   1.1    bouyer 
   2177   1.1    bouyer 	return (rv);
   2178   1.1    bouyer }
   2179   1.1    bouyer 
   2180   1.6      maxv static int
   2181   1.1    bouyer mfii_my_intr(struct mfii_softc *sc)
   2182   1.1    bouyer {
   2183   1.1    bouyer 	u_int32_t status;
   2184   1.1    bouyer 
   2185   1.1    bouyer 	status = mfii_read(sc, MFI_OSTS);
   2186   1.1    bouyer 
   2187   1.1    bouyer 	DNPRINTF(MFII_D_INTR, "%s: intr status 0x%x\n", DEVNAME(sc), status);
   2188   1.1    bouyer 	if (ISSET(status, 0x1)) {
   2189   1.1    bouyer 		mfii_write(sc, MFI_OSTS, status);
   2190   1.1    bouyer 		return (1);
   2191   1.1    bouyer 	}
   2192   1.1    bouyer 
   2193   1.1    bouyer 	return (ISSET(status, MFII_OSTS_INTR_VALID) ? 1 : 0);
   2194   1.1    bouyer }
   2195   1.1    bouyer 
   2196   1.6      maxv static int
   2197   1.1    bouyer mfii_intr(void *arg)
   2198   1.1    bouyer {
   2199   1.1    bouyer 	struct mfii_softc *sc = arg;
   2200   1.1    bouyer 
   2201   1.1    bouyer 	if (!mfii_my_intr(sc))
   2202   1.1    bouyer 		return (0);
   2203   1.1    bouyer 
   2204   1.1    bouyer 	mfii_postq(sc);
   2205   1.1    bouyer 
   2206   1.1    bouyer 	return (1);
   2207   1.1    bouyer }
   2208   1.1    bouyer 
   2209   1.6      maxv static void
   2210   1.1    bouyer mfii_postq(struct mfii_softc *sc)
   2211   1.1    bouyer {
   2212   1.1    bouyer 	struct mfii_ccb_list ccbs = SIMPLEQ_HEAD_INITIALIZER(ccbs);
   2213   1.1    bouyer 	struct mpii_reply_descr *postq = MFII_DMA_KVA(sc->sc_reply_postq);
   2214   1.1    bouyer 	struct mpii_reply_descr *rdp;
   2215   1.1    bouyer 	struct mfii_ccb *ccb;
   2216   1.1    bouyer 	int rpi = 0;
   2217   1.1    bouyer 
   2218   1.1    bouyer 	mutex_enter(&sc->sc_reply_postq_mtx);
   2219   1.1    bouyer 
   2220   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_reply_postq),
   2221   1.1    bouyer 	    0, MFII_DMA_LEN(sc->sc_reply_postq),
   2222   1.1    bouyer 	    BUS_DMASYNC_POSTREAD);
   2223   1.1    bouyer 
   2224   1.1    bouyer 	for (;;) {
   2225   1.1    bouyer 		rdp = &postq[sc->sc_reply_postq_index];
   2226  1.19   msaitoh 		DNPRINTF(MFII_D_INTR,
   2227  1.19   msaitoh 		    "%s: mfii_postq index %d flags 0x%x data 0x%x\n",
   2228   1.1    bouyer 		    DEVNAME(sc), sc->sc_reply_postq_index, rdp->reply_flags,
   2229   1.1    bouyer 			rdp->data == 0xffffffff);
   2230   1.1    bouyer 		if ((rdp->reply_flags & MPII_REPLY_DESCR_TYPE_MASK) ==
   2231   1.1    bouyer 		    MPII_REPLY_DESCR_UNUSED)
   2232   1.1    bouyer 			break;
   2233   1.1    bouyer 		if (rdp->data == 0xffffffff) {
   2234   1.1    bouyer 			/*
   2235   1.1    bouyer 			 * ioc is still writing to the reply post queue
   2236   1.1    bouyer 			 * race condition - bail!
   2237   1.1    bouyer 			 */
   2238   1.1    bouyer 			break;
   2239   1.1    bouyer 		}
   2240   1.1    bouyer 
   2241   1.1    bouyer 		ccb = &sc->sc_ccb[le16toh(rdp->smid) - 1];
   2242   1.1    bouyer 		SIMPLEQ_INSERT_TAIL(&ccbs, ccb, ccb_link);
   2243   1.1    bouyer 		memset(rdp, 0xff, sizeof(*rdp));
   2244   1.1    bouyer 
   2245   1.1    bouyer 		sc->sc_reply_postq_index++;
   2246   1.1    bouyer 		sc->sc_reply_postq_index %= sc->sc_reply_postq_depth;
   2247   1.1    bouyer 		rpi = 1;
   2248   1.1    bouyer 	}
   2249   1.1    bouyer 
   2250   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_reply_postq),
   2251   1.1    bouyer 	    0, MFII_DMA_LEN(sc->sc_reply_postq),
   2252   1.1    bouyer 	    BUS_DMASYNC_PREREAD);
   2253   1.1    bouyer 
   2254   1.1    bouyer 	if (rpi)
   2255   1.1    bouyer 		mfii_write(sc, MFII_RPI, sc->sc_reply_postq_index);
   2256   1.1    bouyer 
   2257   1.1    bouyer 	mutex_exit(&sc->sc_reply_postq_mtx);
   2258   1.1    bouyer 
   2259   1.1    bouyer 	while ((ccb = SIMPLEQ_FIRST(&ccbs)) != NULL) {
   2260   1.1    bouyer 		SIMPLEQ_REMOVE_HEAD(&ccbs, ccb_link);
   2261   1.1    bouyer 		mfii_done(sc, ccb);
   2262   1.1    bouyer 	}
   2263   1.1    bouyer }
   2264   1.1    bouyer 
   2265   1.6      maxv static void
   2266   1.1    bouyer mfii_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
   2267  1.10   msaitoh     void *arg)
   2268   1.1    bouyer {
   2269   1.1    bouyer 	struct scsipi_periph    *periph;
   2270   1.1    bouyer 	struct scsipi_xfer	*xs;
   2271   1.1    bouyer 	struct scsipi_adapter   *adapt = chan->chan_adapter;
   2272   1.1    bouyer 	struct mfii_softc	*sc = device_private(adapt->adapt_dev);
   2273   1.1    bouyer 	struct mfii_ccb *ccb;
   2274   1.1    bouyer 	int timeout;
   2275   1.1    bouyer 	int target;
   2276   1.1    bouyer 
   2277  1.10   msaitoh 	switch (req) {
   2278   1.1    bouyer 		case ADAPTER_REQ_GROW_RESOURCES:
   2279   1.1    bouyer 		/* Not supported. */
   2280   1.1    bouyer 		return;
   2281   1.1    bouyer 	case ADAPTER_REQ_SET_XFER_MODE:
   2282   1.1    bouyer 	{
   2283   1.1    bouyer 		struct scsipi_xfer_mode *xm = arg;
   2284   1.1    bouyer 		xm->xm_mode = PERIPH_CAP_TQING;
   2285   1.1    bouyer 		xm->xm_period = 0;
   2286   1.1    bouyer 		xm->xm_offset = 0;
   2287   1.1    bouyer 		scsipi_async_event(&sc->sc_chan, ASYNC_EVENT_XFER_MODE, xm);
   2288   1.1    bouyer 		return;
   2289   1.1    bouyer 	}
   2290   1.1    bouyer 	case ADAPTER_REQ_RUN_XFER:
   2291   1.1    bouyer 		break;
   2292   1.1    bouyer 	}
   2293   1.1    bouyer 
   2294   1.1    bouyer 	xs = arg;
   2295   1.1    bouyer 	periph = xs->xs_periph;
   2296   1.1    bouyer 	target = periph->periph_target;
   2297   1.1    bouyer 
   2298  1.24   msaitoh 	if (target >= MFII_MAX_LD_EXT || !sc->sc_ld[target].ld_present ||
   2299   1.1    bouyer 	    periph->periph_lun != 0) {
   2300   1.1    bouyer 		xs->error = XS_SELTIMEOUT;
   2301   1.1    bouyer 		scsipi_done(xs);
   2302   1.1    bouyer 		return;
   2303   1.1    bouyer 	}
   2304   1.1    bouyer 
   2305   1.1    bouyer 	if ((xs->cmd->opcode == SCSI_SYNCHRONIZE_CACHE_10 ||
   2306   1.1    bouyer 	    xs->cmd->opcode == SCSI_SYNCHRONIZE_CACHE_16) && sc->sc_bbuok) {
   2307   1.1    bouyer 		/* the cache is stable storage, don't flush */
   2308   1.1    bouyer 		xs->error = XS_NOERROR;
   2309   1.1    bouyer 		xs->status = SCSI_OK;
   2310   1.1    bouyer 		xs->resid = 0;
   2311   1.1    bouyer 		scsipi_done(xs);
   2312   1.1    bouyer 		return;
   2313   1.1    bouyer 	}
   2314   1.1    bouyer 
   2315   1.1    bouyer 	ccb = mfii_get_ccb(sc);
   2316   1.1    bouyer 	if (ccb == NULL) {
   2317   1.1    bouyer 		xs->error = XS_RESOURCE_SHORTAGE;
   2318   1.1    bouyer 		scsipi_done(xs);
   2319   1.1    bouyer 		return;
   2320   1.1    bouyer 	}
   2321   1.1    bouyer 	mfii_scrub_ccb(ccb);
   2322   1.1    bouyer 	ccb->ccb_cookie = xs;
   2323   1.1    bouyer 	ccb->ccb_done = mfii_scsi_cmd_done;
   2324   1.1    bouyer 	ccb->ccb_data = xs->data;
   2325   1.1    bouyer 	ccb->ccb_len = xs->datalen;
   2326   1.1    bouyer 
   2327   1.1    bouyer 	timeout = mstohz(xs->timeout);
   2328   1.1    bouyer 	if (timeout == 0)
   2329   1.1    bouyer 		timeout = 1;
   2330   1.1    bouyer 	callout_reset(&xs->xs_callout, timeout, mfii_scsi_cmd_tmo, ccb);
   2331   1.1    bouyer 
   2332   1.1    bouyer 	switch (xs->cmd->opcode) {
   2333   1.1    bouyer 	case SCSI_READ_6_COMMAND:
   2334   1.1    bouyer 	case READ_10:
   2335   1.1    bouyer 	case READ_12:
   2336   1.1    bouyer 	case READ_16:
   2337   1.1    bouyer 	case SCSI_WRITE_6_COMMAND:
   2338   1.1    bouyer 	case WRITE_10:
   2339   1.1    bouyer 	case WRITE_12:
   2340   1.1    bouyer 	case WRITE_16:
   2341   1.1    bouyer 		if (mfii_scsi_cmd_io(sc, ccb, xs) != 0)
   2342   1.1    bouyer 			goto stuffup;
   2343   1.1    bouyer 		break;
   2344   1.1    bouyer 
   2345   1.1    bouyer 	default:
   2346   1.1    bouyer 		if (mfii_scsi_cmd_cdb(sc, ccb, xs) != 0)
   2347   1.1    bouyer 			goto stuffup;
   2348   1.1    bouyer 		break;
   2349   1.1    bouyer 	}
   2350   1.1    bouyer 
   2351   1.1    bouyer 	xs->error = XS_NOERROR;
   2352   1.1    bouyer 	xs->resid = 0;
   2353   1.1    bouyer 
   2354   1.1    bouyer 	DNPRINTF(MFII_D_CMD, "%s: start io %d cmd %d\n", DEVNAME(sc), target,
   2355   1.1    bouyer 	    xs->cmd->opcode);
   2356   1.1    bouyer 
   2357   1.1    bouyer 	if (xs->xs_control & XS_CTL_POLL) {
   2358   1.1    bouyer 		if (mfii_poll(sc, ccb) != 0)
   2359   1.1    bouyer 			goto stuffup;
   2360   1.1    bouyer 		return;
   2361   1.1    bouyer 	}
   2362   1.1    bouyer 
   2363   1.1    bouyer 	mfii_start(sc, ccb);
   2364   1.1    bouyer 
   2365   1.1    bouyer 	return;
   2366   1.1    bouyer 
   2367   1.1    bouyer stuffup:
   2368   1.1    bouyer 	xs->error = XS_DRIVER_STUFFUP;
   2369   1.1    bouyer 	scsipi_done(xs);
   2370   1.1    bouyer 	mfii_put_ccb(sc, ccb);
   2371   1.1    bouyer }
   2372   1.1    bouyer 
   2373   1.6      maxv static void
   2374   1.1    bouyer mfii_scsi_cmd_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
   2375   1.1    bouyer {
   2376   1.1    bouyer 	struct scsipi_xfer *xs = ccb->ccb_cookie;
   2377   1.1    bouyer 	struct mpii_msg_scsi_io *io = ccb->ccb_request;
   2378   1.1    bouyer 	struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
   2379   1.1    bouyer 
   2380   1.1    bouyer 	if (callout_stop(&xs->xs_callout) != 0)
   2381   1.4    bouyer 		return;
   2382   1.1    bouyer 
   2383   1.1    bouyer 	switch (ctx->status) {
   2384   1.1    bouyer 	case MFI_STAT_OK:
   2385   1.1    bouyer 		break;
   2386   1.1    bouyer 
   2387   1.1    bouyer 	case MFI_STAT_SCSI_DONE_WITH_ERROR:
   2388   1.1    bouyer 		xs->error = XS_SENSE;
   2389   1.1    bouyer 		memset(&xs->sense, 0, sizeof(xs->sense));
   2390   1.1    bouyer 		memcpy(&xs->sense, ccb->ccb_sense, sizeof(xs->sense));
   2391   1.1    bouyer 		break;
   2392   1.1    bouyer 
   2393   1.1    bouyer 	case MFI_STAT_LD_OFFLINE:
   2394   1.1    bouyer 	case MFI_STAT_DEVICE_NOT_FOUND:
   2395   1.1    bouyer 		xs->error = XS_SELTIMEOUT;
   2396   1.1    bouyer 		break;
   2397   1.1    bouyer 
   2398   1.1    bouyer 	default:
   2399   1.1    bouyer 		xs->error = XS_DRIVER_STUFFUP;
   2400   1.1    bouyer 		break;
   2401   1.1    bouyer 	}
   2402   1.1    bouyer 
   2403   1.4    bouyer 	scsipi_done(xs);
   2404   1.4    bouyer 	mfii_put_ccb(sc, ccb);
   2405   1.1    bouyer }
   2406   1.1    bouyer 
   2407   1.6      maxv static int
   2408   1.1    bouyer mfii_scsi_cmd_io(struct mfii_softc *sc, struct mfii_ccb *ccb,
   2409   1.1    bouyer     struct scsipi_xfer *xs)
   2410   1.1    bouyer {
   2411   1.1    bouyer 	struct scsipi_periph *periph = xs->xs_periph;
   2412   1.1    bouyer 	struct mpii_msg_scsi_io *io = ccb->ccb_request;
   2413   1.1    bouyer 	struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
   2414  1.25   msaitoh 	int segs, target;
   2415   1.1    bouyer 
   2416  1.25   msaitoh 	target = sc->sc_ld[periph->periph_target].ld_target_id;
   2417  1.25   msaitoh 	io->dev_handle = htole16(target);
   2418   1.1    bouyer 	io->function = MFII_FUNCTION_LDIO_REQUEST;
   2419   1.1    bouyer 	io->sense_buffer_low_address = htole32(ccb->ccb_sense_dva);
   2420   1.1    bouyer 	io->sgl_flags = htole16(0x02); /* XXX */
   2421   1.1    bouyer 	io->sense_buffer_length = sizeof(xs->sense);
   2422   1.1    bouyer 	io->sgl_offset0 = (sizeof(*io) + sizeof(*ctx)) / 4;
   2423   1.1    bouyer 	io->data_length = htole32(xs->datalen);
   2424   1.1    bouyer 	io->io_flags = htole16(xs->cmdlen);
   2425   1.1    bouyer 	switch (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
   2426   1.1    bouyer 	case XS_CTL_DATA_IN:
   2427   1.1    bouyer 		ccb->ccb_direction = MFII_DATA_IN;
   2428   1.1    bouyer 		io->direction = MPII_SCSIIO_DIR_READ;
   2429   1.1    bouyer 		break;
   2430   1.1    bouyer 	case XS_CTL_DATA_OUT:
   2431   1.1    bouyer 		ccb->ccb_direction = MFII_DATA_OUT;
   2432   1.1    bouyer 		io->direction = MPII_SCSIIO_DIR_WRITE;
   2433   1.1    bouyer 		break;
   2434   1.1    bouyer 	default:
   2435   1.1    bouyer 		ccb->ccb_direction = MFII_DATA_NONE;
   2436   1.1    bouyer 		io->direction = MPII_SCSIIO_DIR_NONE;
   2437   1.1    bouyer 		break;
   2438   1.1    bouyer 	}
   2439   1.1    bouyer 	memcpy(io->cdb, xs->cmd, xs->cmdlen);
   2440   1.1    bouyer 
   2441   1.1    bouyer 	ctx->type_nseg = sc->sc_iop->ldio_ctx_type_nseg;
   2442   1.1    bouyer 	ctx->timeout_value = htole16(0x14); /* XXX */
   2443   1.1    bouyer 	ctx->reg_lock_flags = htole16(sc->sc_iop->ldio_ctx_reg_lock_flags);
   2444  1.25   msaitoh 	ctx->virtual_disk_target_id = htole16(target);
   2445   1.1    bouyer 
   2446   1.1    bouyer 	if (mfii_load_ccb(sc, ccb, ctx + 1,
   2447   1.1    bouyer 	    ISSET(xs->xs_control, XS_CTL_NOSLEEP)) != 0)
   2448   1.1    bouyer 		return (1);
   2449   1.1    bouyer 
   2450   1.1    bouyer 	KASSERT(ccb->ccb_len == 0 || ccb->ccb_dma64);
   2451   1.1    bouyer 	segs = (ccb->ccb_len == 0) ? 0 : ccb->ccb_dmamap64->dm_nsegs;
   2452   1.1    bouyer 	switch (sc->sc_iop->num_sge_loc) {
   2453   1.1    bouyer 	case MFII_IOP_NUM_SGE_LOC_ORIG:
   2454   1.1    bouyer 		ctx->num_sge = segs;
   2455   1.1    bouyer 		break;
   2456   1.1    bouyer 	case MFII_IOP_NUM_SGE_LOC_35:
   2457   1.1    bouyer 		/* 12 bit field, but we're only using the lower 8 */
   2458   1.1    bouyer 		ctx->span_arm = segs;
   2459   1.1    bouyer 		break;
   2460   1.1    bouyer 	}
   2461   1.1    bouyer 
   2462   1.1    bouyer 	ccb->ccb_req.flags = sc->sc_iop->ldio_req_type;
   2463   1.1    bouyer 	ccb->ccb_req.smid = le16toh(ccb->ccb_smid);
   2464   1.1    bouyer 
   2465   1.1    bouyer 	return (0);
   2466   1.1    bouyer }
   2467   1.1    bouyer 
   2468   1.6      maxv static int
   2469   1.1    bouyer mfii_scsi_cmd_cdb(struct mfii_softc *sc, struct mfii_ccb *ccb,
   2470   1.1    bouyer     struct scsipi_xfer *xs)
   2471   1.1    bouyer {
   2472   1.1    bouyer 	struct scsipi_periph *periph = xs->xs_periph;
   2473   1.1    bouyer 	struct mpii_msg_scsi_io *io = ccb->ccb_request;
   2474   1.1    bouyer 	struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
   2475  1.25   msaitoh 	int target;
   2476   1.1    bouyer 
   2477  1.25   msaitoh 	target = sc->sc_ld[periph->periph_target].ld_target_id;
   2478  1.25   msaitoh 	io->dev_handle = htole16(target);
   2479   1.1    bouyer 	io->function = MFII_FUNCTION_LDIO_REQUEST;
   2480   1.1    bouyer 	io->sense_buffer_low_address = htole32(ccb->ccb_sense_dva);
   2481   1.1    bouyer 	io->sgl_flags = htole16(0x02); /* XXX */
   2482   1.1    bouyer 	io->sense_buffer_length = sizeof(xs->sense);
   2483   1.1    bouyer 	io->sgl_offset0 = (sizeof(*io) + sizeof(*ctx)) / 4;
   2484   1.1    bouyer 	io->data_length = htole32(xs->datalen);
   2485   1.1    bouyer 	io->io_flags = htole16(xs->cmdlen);
   2486   1.1    bouyer 	io->lun[0] = htobe16(periph->periph_lun);
   2487   1.1    bouyer 	switch (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
   2488   1.1    bouyer 	case XS_CTL_DATA_IN:
   2489   1.1    bouyer 		ccb->ccb_direction = MFII_DATA_IN;
   2490   1.1    bouyer 		io->direction = MPII_SCSIIO_DIR_READ;
   2491   1.1    bouyer 		break;
   2492   1.1    bouyer 	case XS_CTL_DATA_OUT:
   2493   1.1    bouyer 		ccb->ccb_direction = MFII_DATA_OUT;
   2494   1.1    bouyer 		io->direction = MPII_SCSIIO_DIR_WRITE;
   2495   1.1    bouyer 		break;
   2496   1.1    bouyer 	default:
   2497   1.1    bouyer 		ccb->ccb_direction = MFII_DATA_NONE;
   2498   1.1    bouyer 		io->direction = MPII_SCSIIO_DIR_NONE;
   2499   1.1    bouyer 		break;
   2500   1.1    bouyer 	}
   2501   1.1    bouyer 	memcpy(io->cdb, xs->cmd, xs->cmdlen);
   2502   1.1    bouyer 
   2503  1.25   msaitoh 	ctx->virtual_disk_target_id = htole16(target);
   2504   1.1    bouyer 
   2505   1.1    bouyer 	if (mfii_load_ccb(sc, ccb, ctx + 1,
   2506   1.1    bouyer 	    ISSET(xs->xs_control, XS_CTL_NOSLEEP)) != 0)
   2507   1.1    bouyer 		return (1);
   2508   1.1    bouyer 
   2509   1.1    bouyer 	ctx->num_sge = (ccb->ccb_len == 0) ? 0 : ccb->ccb_dmamap64->dm_nsegs;
   2510   1.1    bouyer 	KASSERT(ccb->ccb_len == 0 || ccb->ccb_dma64);
   2511   1.1    bouyer 
   2512   1.1    bouyer 	ccb->ccb_req.flags = MFII_REQ_TYPE_SCSI;
   2513   1.1    bouyer 	ccb->ccb_req.smid = le16toh(ccb->ccb_smid);
   2514   1.1    bouyer 
   2515   1.1    bouyer 	return (0);
   2516   1.1    bouyer }
   2517   1.1    bouyer 
   2518   1.1    bouyer #if 0
   2519   1.1    bouyer void
   2520   1.1    bouyer mfii_pd_scsi_cmd(struct scsipi_xfer *xs)
   2521   1.1    bouyer {
   2522   1.1    bouyer 	struct scsi_link *link = xs->sc_link;
   2523   1.1    bouyer 	struct mfii_softc *sc = link->adapter_softc;
   2524   1.1    bouyer 	struct mfii_ccb *ccb = xs->io;
   2525   1.1    bouyer 
   2526   1.1    bouyer 	mfii_scrub_ccb(ccb);
   2527   1.1    bouyer 	ccb->ccb_cookie = xs;
   2528   1.1    bouyer 	ccb->ccb_done = mfii_scsi_cmd_done;
   2529   1.1    bouyer 	ccb->ccb_data = xs->data;
   2530   1.1    bouyer 	ccb->ccb_len = xs->datalen;
   2531   1.1    bouyer 
   2532   1.1    bouyer 	// XXX timeout_set(&xs->stimeout, mfii_scsi_cmd_tmo, xs);
   2533   1.1    bouyer 
   2534   1.1    bouyer 	xs->error = mfii_pd_scsi_cmd_cdb(sc, xs);
   2535   1.1    bouyer 	if (xs->error != XS_NOERROR)
   2536   1.1    bouyer 		goto done;
   2537   1.1    bouyer 
   2538   1.1    bouyer 	xs->resid = 0;
   2539   1.1    bouyer 
   2540   1.1    bouyer 	if (ISSET(xs->xs_control, XS_CTL_POLL)) {
   2541   1.1    bouyer 		if (mfii_poll(sc, ccb) != 0)
   2542   1.1    bouyer 			goto stuffup;
   2543   1.1    bouyer 		return;
   2544   1.1    bouyer 	}
   2545   1.1    bouyer 
   2546   1.1    bouyer 	// XXX timeout_add_msec(&xs->stimeout, xs->timeout);
   2547   1.1    bouyer 	mfii_start(sc, ccb);
   2548   1.1    bouyer 
   2549   1.1    bouyer 	return;
   2550   1.1    bouyer 
   2551   1.1    bouyer stuffup:
   2552   1.1    bouyer 	xs->error = XS_DRIVER_STUFFUP;
   2553   1.1    bouyer done:
   2554   1.1    bouyer 	scsi_done(xs);
   2555   1.1    bouyer }
   2556   1.1    bouyer 
   2557   1.1    bouyer int
   2558   1.1    bouyer mfii_pd_scsi_probe(struct scsi_link *link)
   2559   1.1    bouyer {
   2560   1.1    bouyer 	struct mfii_softc *sc = link->adapter_softc;
   2561   1.1    bouyer 	struct mfi_pd_details mpd;
   2562   1.1    bouyer 	union mfi_mbox mbox;
   2563   1.1    bouyer 	int rv;
   2564   1.1    bouyer 
   2565   1.1    bouyer 	if (link->lun > 0)
   2566   1.1    bouyer 		return (0);
   2567   1.1    bouyer 
   2568   1.1    bouyer 	memset(&mbox, 0, sizeof(mbox));
   2569   1.1    bouyer 	mbox.s[0] = htole16(link->target);
   2570   1.1    bouyer 
   2571   1.1    bouyer 	rv = mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, &mpd, sizeof(mpd),
   2572   1.1    bouyer 	    MFII_DATA_IN, true);
   2573   1.1    bouyer 	if (rv != 0)
   2574   1.1    bouyer 		return (EIO);
   2575   1.1    bouyer 
   2576   1.1    bouyer 	if (mpd.mpd_fw_state != htole16(MFI_PD_SYSTEM))
   2577   1.1    bouyer 		return (ENXIO);
   2578   1.1    bouyer 
   2579   1.1    bouyer 	return (0);
   2580   1.1    bouyer }
   2581   1.1    bouyer 
   2582   1.1    bouyer int
   2583   1.1    bouyer mfii_pd_scsi_cmd_cdb(struct mfii_softc *sc, struct mfii_ccb *ccb,
   2584   1.1    bouyer     struct scsipi_xfer *xs)
   2585   1.1    bouyer {
   2586   1.1    bouyer 	struct scsi_link *link = xs->sc_link;
   2587   1.1    bouyer 	struct mpii_msg_scsi_io *io = ccb->ccb_request;
   2588   1.1    bouyer 	struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
   2589   1.1    bouyer 	uint16_t dev_handle;
   2590   1.1    bouyer 
   2591   1.1    bouyer 	dev_handle = mfii_dev_handle(sc, link->target);
   2592   1.1    bouyer 	if (dev_handle == htole16(0xffff))
   2593   1.1    bouyer 		return (XS_SELTIMEOUT);
   2594   1.1    bouyer 
   2595   1.1    bouyer 	io->dev_handle = dev_handle;
   2596   1.1    bouyer 	io->function = 0;
   2597   1.1    bouyer 	io->sense_buffer_low_address = htole32(ccb->ccb_sense_dva);
   2598   1.1    bouyer 	io->sgl_flags = htole16(0x02); /* XXX */
   2599   1.1    bouyer 	io->sense_buffer_length = sizeof(xs->sense);
   2600   1.1    bouyer 	io->sgl_offset0 = (sizeof(*io) + sizeof(*ctx)) / 4;
   2601   1.1    bouyer 	io->data_length = htole32(xs->datalen);
   2602   1.1    bouyer 	io->io_flags = htole16(xs->cmdlen);
   2603   1.1    bouyer 	io->lun[0] = htobe16(link->lun);
   2604   1.1    bouyer 	switch (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
   2605   1.1    bouyer 	case XS_CTL_DATA_IN:
   2606   1.1    bouyer 		ccb->ccb_direction = MFII_DATA_IN;
   2607   1.1    bouyer 		io->direction = MPII_SCSIIO_DIR_READ;
   2608   1.1    bouyer 		break;
   2609   1.1    bouyer 	case XS_CTL_DATA_OUT:
   2610   1.1    bouyer 		ccb->ccb_direction = MFII_DATA_OUT;
   2611   1.1    bouyer 		io->direction = MPII_SCSIIO_DIR_WRITE;
   2612   1.1    bouyer 		break;
   2613   1.1    bouyer 	default:
   2614   1.1    bouyer 		ccb->ccb_direction = MFII_DATA_NONE;
   2615   1.1    bouyer 		io->direction = MPII_SCSIIO_DIR_NONE;
   2616   1.1    bouyer 		break;
   2617   1.1    bouyer 	}
   2618   1.1    bouyer 	memcpy(io->cdb, xs->cmd, xs->cmdlen);
   2619   1.1    bouyer 
   2620   1.1    bouyer 	ctx->virtual_disk_target_id = htole16(link->target);
   2621   1.1    bouyer 	ctx->raid_flags = MFII_RAID_CTX_IO_TYPE_SYSPD;
   2622   1.1    bouyer 	ctx->timeout_value = sc->sc_pd->pd_timeout;
   2623   1.1    bouyer 
   2624   1.1    bouyer 	if (mfii_load_ccb(sc, ccb, ctx + 1,
   2625   1.1    bouyer 	    ISSET(xs->xs_control, XS_CTL_NOSLEEP)) != 0)
   2626   1.1    bouyer 		return (XS_DRIVER_STUFFUP);
   2627   1.1    bouyer 
   2628   1.1    bouyer 	ctx->num_sge = (ccb->ccb_len == 0) ? 0 : ccb->ccb_dmamap64->dm_nsegs;
   2629   1.1    bouyer 	KASSERT(ccb->ccb_dma64);
   2630   1.1    bouyer 
   2631   1.1    bouyer 	ccb->ccb_req.flags = MFII_REQ_TYPE_HI_PRI;
   2632   1.1    bouyer 	ccb->ccb_req.smid = le16toh(ccb->ccb_smid);
   2633   1.1    bouyer 	ccb->ccb_req.dev_handle = dev_handle;
   2634   1.1    bouyer 
   2635   1.1    bouyer 	return (XS_NOERROR);
   2636   1.1    bouyer }
   2637   1.1    bouyer #endif
   2638   1.1    bouyer 
   2639   1.6      maxv static int
   2640   1.1    bouyer mfii_load_ccb(struct mfii_softc *sc, struct mfii_ccb *ccb, void *sglp,
   2641   1.1    bouyer     int nosleep)
   2642   1.1    bouyer {
   2643   1.1    bouyer 	struct mpii_msg_request *req = ccb->ccb_request;
   2644   1.1    bouyer 	struct mfii_sge *sge = NULL, *nsge = sglp;
   2645   1.1    bouyer 	struct mfii_sge *ce = NULL;
   2646   1.1    bouyer 	bus_dmamap_t dmap = ccb->ccb_dmamap64;
   2647   1.1    bouyer 	u_int space;
   2648   1.1    bouyer 	int i;
   2649   1.1    bouyer 
   2650   1.1    bouyer 	int error;
   2651   1.1    bouyer 
   2652   1.1    bouyer 	if (ccb->ccb_len == 0)
   2653   1.1    bouyer 		return (0);
   2654   1.1    bouyer 
   2655   1.1    bouyer 	ccb->ccb_dma64 = true;
   2656   1.1    bouyer 	error = bus_dmamap_load(sc->sc_dmat64, dmap,
   2657   1.1    bouyer 	    ccb->ccb_data, ccb->ccb_len, NULL,
   2658   1.1    bouyer 	    nosleep ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
   2659   1.1    bouyer 	if (error) {
   2660   1.1    bouyer 		printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
   2661   1.1    bouyer 		return (1);
   2662   1.1    bouyer 	}
   2663   1.1    bouyer 
   2664   1.1    bouyer 	space = (MFII_REQUEST_SIZE - ((u_int8_t *)nsge - (u_int8_t *)req)) /
   2665   1.1    bouyer 	    sizeof(*nsge);
   2666   1.1    bouyer 	if (dmap->dm_nsegs > space) {
   2667   1.1    bouyer 		space--;
   2668   1.1    bouyer 
   2669   1.1    bouyer 		ccb->ccb_sgl_len = (dmap->dm_nsegs - space) * sizeof(*nsge);
   2670   1.1    bouyer 		memset(ccb->ccb_sgl, 0, ccb->ccb_sgl_len);
   2671   1.1    bouyer 
   2672   1.1    bouyer 		ce = nsge + space;
   2673   1.1    bouyer 		ce->sg_addr = htole64(ccb->ccb_sgl_dva);
   2674   1.1    bouyer 		ce->sg_len = htole32(ccb->ccb_sgl_len);
   2675   1.1    bouyer 		ce->sg_flags = sc->sc_iop->sge_flag_chain;
   2676   1.1    bouyer 
   2677   1.1    bouyer 		req->chain_offset = ((u_int8_t *)ce - (u_int8_t *)req) / 16;
   2678   1.1    bouyer 	}
   2679   1.1    bouyer 
   2680   1.1    bouyer 	for (i = 0; i < dmap->dm_nsegs; i++) {
   2681   1.1    bouyer 		if (nsge == ce)
   2682   1.1    bouyer 			nsge = ccb->ccb_sgl;
   2683   1.1    bouyer 
   2684   1.1    bouyer 		sge = nsge;
   2685   1.1    bouyer 
   2686   1.1    bouyer 		sge->sg_addr = htole64(dmap->dm_segs[i].ds_addr);
   2687   1.1    bouyer 		sge->sg_len = htole32(dmap->dm_segs[i].ds_len);
   2688   1.1    bouyer 		sge->sg_flags = MFII_SGE_ADDR_SYSTEM;
   2689   1.1    bouyer 
   2690   1.1    bouyer 		nsge = sge + 1;
   2691   1.1    bouyer 	}
   2692   1.1    bouyer 	sge->sg_flags |= sc->sc_iop->sge_flag_eol;
   2693   1.1    bouyer 
   2694   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat64, dmap, 0, dmap->dm_mapsize,
   2695   1.1    bouyer 	    ccb->ccb_direction == MFII_DATA_OUT ?
   2696   1.1    bouyer 	    BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
   2697   1.1    bouyer 
   2698   1.1    bouyer 	if (ccb->ccb_sgl_len > 0) {
   2699   1.1    bouyer 		bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_sgl),
   2700   1.1    bouyer 		    ccb->ccb_sgl_offset, ccb->ccb_sgl_len,
   2701   1.1    bouyer 		    BUS_DMASYNC_PREWRITE);
   2702   1.1    bouyer 	}
   2703   1.1    bouyer 
   2704   1.1    bouyer 	return (0);
   2705   1.1    bouyer }
   2706   1.1    bouyer 
   2707   1.6      maxv static void
   2708   1.1    bouyer mfii_scsi_cmd_tmo(void *p)
   2709   1.1    bouyer {
   2710   1.1    bouyer 	struct mfii_ccb *ccb = p;
   2711   1.1    bouyer 	struct mfii_softc *sc = ccb->ccb_sc;
   2712   1.1    bouyer 	bool start_abort;
   2713   1.1    bouyer 
   2714   1.1    bouyer 	printf("%s: cmd timeout ccb %p\n", DEVNAME(sc), p);
   2715   1.1    bouyer 
   2716   1.1    bouyer 	mutex_enter(&sc->sc_abort_mtx);
   2717   1.1    bouyer 	start_abort = (SIMPLEQ_FIRST(&sc->sc_abort_list) == 0);
   2718   1.1    bouyer 	SIMPLEQ_INSERT_TAIL(&sc->sc_abort_list, ccb, ccb_link);
   2719   1.1    bouyer 	if (start_abort)
   2720   1.1    bouyer 		workqueue_enqueue(sc->sc_abort_wq, &sc->sc_abort_work, NULL);
   2721   1.1    bouyer 	mutex_exit(&sc->sc_abort_mtx);
   2722   1.1    bouyer }
   2723   1.1    bouyer 
   2724   1.6      maxv static void
   2725   1.1    bouyer mfii_abort_task(struct work *wk, void *scp)
   2726   1.1    bouyer {
   2727   1.1    bouyer 	struct mfii_softc *sc = scp;
   2728   1.1    bouyer 	struct mfii_ccb *list;
   2729   1.1    bouyer 
   2730   1.1    bouyer 	mutex_enter(&sc->sc_abort_mtx);
   2731   1.1    bouyer 	list = SIMPLEQ_FIRST(&sc->sc_abort_list);
   2732   1.1    bouyer 	SIMPLEQ_INIT(&sc->sc_abort_list);
   2733   1.1    bouyer 	mutex_exit(&sc->sc_abort_mtx);
   2734   1.1    bouyer 
   2735   1.1    bouyer 	while (list != NULL) {
   2736   1.1    bouyer 		struct mfii_ccb *ccb = list;
   2737   1.1    bouyer 		struct scsipi_xfer *xs = ccb->ccb_cookie;
   2738   1.1    bouyer 		struct scsipi_periph *periph = xs->xs_periph;
   2739   1.1    bouyer 		struct mfii_ccb *accb;
   2740   1.1    bouyer 
   2741   1.1    bouyer 		list = SIMPLEQ_NEXT(ccb, ccb_link);
   2742   1.1    bouyer 
   2743   1.1    bouyer 		if (!sc->sc_ld[periph->periph_target].ld_present) {
   2744   1.1    bouyer 			/* device is gone */
   2745   1.4    bouyer 			xs->error = XS_SELTIMEOUT;
   2746   1.4    bouyer 			scsipi_done(xs);
   2747   1.4    bouyer 			mfii_put_ccb(sc, ccb);
   2748   1.1    bouyer 			continue;
   2749   1.1    bouyer 		}
   2750   1.1    bouyer 
   2751   1.1    bouyer 		accb = mfii_get_ccb(sc);
   2752   1.1    bouyer 		mfii_scrub_ccb(accb);
   2753   1.1    bouyer 		mfii_abort(sc, accb, periph->periph_target, ccb->ccb_smid,
   2754   1.1    bouyer 		    MPII_SCSI_TASK_ABORT_TASK,
   2755   1.1    bouyer 		    htole32(MFII_TASK_MGMT_FLAGS_PD));
   2756   1.1    bouyer 
   2757   1.1    bouyer 		accb->ccb_cookie = ccb;
   2758   1.1    bouyer 		accb->ccb_done = mfii_scsi_cmd_abort_done;
   2759   1.1    bouyer 
   2760   1.1    bouyer 		mfii_start(sc, accb);
   2761   1.1    bouyer 	}
   2762   1.1    bouyer }
   2763   1.1    bouyer 
   2764   1.6      maxv static void
   2765   1.1    bouyer mfii_abort(struct mfii_softc *sc, struct mfii_ccb *accb, uint16_t dev_handle,
   2766   1.1    bouyer     uint16_t smid, uint8_t type, uint32_t flags)
   2767   1.1    bouyer {
   2768   1.1    bouyer 	struct mfii_task_mgmt *msg;
   2769   1.1    bouyer 	struct mpii_msg_scsi_task_request *req;
   2770   1.1    bouyer 
   2771   1.1    bouyer 	msg = accb->ccb_request;
   2772   1.1    bouyer 	req = &msg->mpii_request;
   2773   1.1    bouyer 	req->dev_handle = dev_handle;
   2774   1.1    bouyer 	req->function = MPII_FUNCTION_SCSI_TASK_MGMT;
   2775   1.1    bouyer 	req->task_type = type;
   2776   1.1    bouyer 	req->task_mid = htole16( smid);
   2777   1.1    bouyer 	msg->flags = flags;
   2778   1.1    bouyer 
   2779   1.1    bouyer 	accb->ccb_req.flags = MFII_REQ_TYPE_HI_PRI;
   2780   1.1    bouyer 	accb->ccb_req.smid = le16toh(accb->ccb_smid);
   2781   1.1    bouyer }
   2782   1.1    bouyer 
   2783   1.6      maxv static void
   2784   1.1    bouyer mfii_scsi_cmd_abort_done(struct mfii_softc *sc, struct mfii_ccb *accb)
   2785   1.1    bouyer {
   2786   1.1    bouyer 	struct mfii_ccb *ccb = accb->ccb_cookie;
   2787   1.1    bouyer 	struct scsipi_xfer *xs = ccb->ccb_cookie;
   2788   1.1    bouyer 
   2789   1.1    bouyer 	/* XXX check accb completion? */
   2790   1.1    bouyer 
   2791   1.1    bouyer 	mfii_put_ccb(sc, accb);
   2792   1.4    bouyer 	printf("%s: cmd aborted ccb %p\n", DEVNAME(sc), ccb);
   2793   1.1    bouyer 
   2794   1.4    bouyer 	xs->error = XS_TIMEOUT;
   2795   1.4    bouyer 	scsipi_done(xs);
   2796   1.4    bouyer 	mfii_put_ccb(sc, ccb);
   2797   1.1    bouyer }
   2798   1.1    bouyer 
   2799   1.6      maxv static struct mfii_ccb *
   2800   1.1    bouyer mfii_get_ccb(struct mfii_softc *sc)
   2801   1.1    bouyer {
   2802   1.1    bouyer 	struct mfii_ccb *ccb;
   2803   1.1    bouyer 
   2804   1.1    bouyer 	mutex_enter(&sc->sc_ccb_mtx);
   2805   1.1    bouyer 	if (!sc->sc_running) {
   2806   1.1    bouyer 		ccb = NULL;
   2807   1.1    bouyer 	} else {
   2808   1.1    bouyer 		ccb = SIMPLEQ_FIRST(&sc->sc_ccb_freeq);
   2809   1.1    bouyer 		if (ccb != NULL)
   2810   1.1    bouyer 			SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_freeq, ccb_link);
   2811   1.1    bouyer 	}
   2812   1.1    bouyer 	mutex_exit(&sc->sc_ccb_mtx);
   2813   1.1    bouyer 	return (ccb);
   2814   1.1    bouyer }
   2815   1.1    bouyer 
   2816   1.6      maxv static void
   2817   1.1    bouyer mfii_scrub_ccb(struct mfii_ccb *ccb)
   2818   1.1    bouyer {
   2819   1.1    bouyer 	ccb->ccb_cookie = NULL;
   2820   1.1    bouyer 	ccb->ccb_done = NULL;
   2821   1.1    bouyer 	ccb->ccb_flags = 0;
   2822   1.1    bouyer 	ccb->ccb_data = NULL;
   2823   1.1    bouyer 	ccb->ccb_direction = MFII_DATA_NONE;
   2824   1.1    bouyer 	ccb->ccb_dma64 = false;
   2825   1.1    bouyer 	ccb->ccb_len = 0;
   2826   1.1    bouyer 	ccb->ccb_sgl_len = 0;
   2827   1.1    bouyer 	memset(&ccb->ccb_req, 0, sizeof(ccb->ccb_req));
   2828   1.1    bouyer 	memset(ccb->ccb_request, 0, MFII_REQUEST_SIZE);
   2829   1.1    bouyer 	memset(ccb->ccb_mfi, 0, MFI_FRAME_SIZE);
   2830   1.1    bouyer }
   2831   1.1    bouyer 
   2832   1.6      maxv static void
   2833   1.1    bouyer mfii_put_ccb(struct mfii_softc *sc, struct mfii_ccb *ccb)
   2834   1.1    bouyer {
   2835   1.1    bouyer 	mutex_enter(&sc->sc_ccb_mtx);
   2836   1.1    bouyer 	SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_freeq, ccb, ccb_link);
   2837   1.1    bouyer 	mutex_exit(&sc->sc_ccb_mtx);
   2838   1.1    bouyer }
   2839   1.1    bouyer 
   2840   1.6      maxv static int
   2841   1.1    bouyer mfii_init_ccb(struct mfii_softc *sc)
   2842   1.1    bouyer {
   2843   1.1    bouyer 	struct mfii_ccb *ccb;
   2844   1.1    bouyer 	u_int8_t *request = MFII_DMA_KVA(sc->sc_requests);
   2845   1.1    bouyer 	u_int8_t *mfi = MFII_DMA_KVA(sc->sc_mfi);
   2846   1.1    bouyer 	u_int8_t *sense = MFII_DMA_KVA(sc->sc_sense);
   2847   1.1    bouyer 	u_int8_t *sgl = MFII_DMA_KVA(sc->sc_sgl);
   2848   1.1    bouyer 	u_int i;
   2849   1.1    bouyer 	int error;
   2850   1.1    bouyer 
   2851   1.1    bouyer 	sc->sc_ccb = malloc(sc->sc_max_cmds * sizeof(struct mfii_ccb),
   2852   1.1    bouyer 	    M_DEVBUF, M_WAITOK|M_ZERO);
   2853   1.1    bouyer 
   2854   1.1    bouyer 	for (i = 0; i < sc->sc_max_cmds; i++) {
   2855   1.1    bouyer 		ccb = &sc->sc_ccb[i];
   2856   1.1    bouyer 		ccb->ccb_sc = sc;
   2857   1.1    bouyer 
   2858   1.1    bouyer 		/* create a dma map for transfer */
   2859   1.1    bouyer 		error = bus_dmamap_create(sc->sc_dmat,
   2860   1.1    bouyer 		    MAXPHYS, sc->sc_max_sgl, MAXPHYS, 0,
   2861   1.1    bouyer 		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ccb_dmamap32);
   2862   1.1    bouyer 		if (error) {
   2863   1.1    bouyer 			printf("%s: cannot create ccb dmamap32 (%d)\n",
   2864   1.1    bouyer 			    DEVNAME(sc), error);
   2865   1.1    bouyer 			goto destroy;
   2866   1.1    bouyer 		}
   2867   1.1    bouyer 		error = bus_dmamap_create(sc->sc_dmat64,
   2868   1.1    bouyer 		    MAXPHYS, sc->sc_max_sgl, MAXPHYS, 0,
   2869   1.1    bouyer 		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ccb_dmamap64);
   2870   1.1    bouyer 		if (error) {
   2871   1.1    bouyer 			printf("%s: cannot create ccb dmamap64 (%d)\n",
   2872   1.1    bouyer 			    DEVNAME(sc), error);
   2873   1.1    bouyer 			goto destroy32;
   2874   1.1    bouyer 		}
   2875   1.1    bouyer 
   2876   1.1    bouyer 		/* select i + 1'th request. 0 is reserved for events */
   2877   1.1    bouyer 		ccb->ccb_smid = i + 1;
   2878   1.1    bouyer 		ccb->ccb_request_offset = MFII_REQUEST_SIZE * (i + 1);
   2879   1.1    bouyer 		ccb->ccb_request = request + ccb->ccb_request_offset;
   2880   1.1    bouyer 		ccb->ccb_request_dva = MFII_DMA_DVA(sc->sc_requests) +
   2881   1.1    bouyer 		    ccb->ccb_request_offset;
   2882   1.1    bouyer 
   2883   1.1    bouyer 		/* select i'th MFI command frame */
   2884   1.1    bouyer 		ccb->ccb_mfi_offset = MFI_FRAME_SIZE * i;
   2885   1.1    bouyer 		ccb->ccb_mfi = mfi + ccb->ccb_mfi_offset;
   2886   1.1    bouyer 		ccb->ccb_mfi_dva = MFII_DMA_DVA(sc->sc_mfi) +
   2887   1.1    bouyer 		    ccb->ccb_mfi_offset;
   2888   1.1    bouyer 
   2889   1.1    bouyer 		/* select i'th sense */
   2890   1.1    bouyer 		ccb->ccb_sense_offset = MFI_SENSE_SIZE * i;
   2891   1.1    bouyer 		ccb->ccb_sense = (struct mfi_sense *)(sense +
   2892   1.1    bouyer 		    ccb->ccb_sense_offset);
   2893   1.1    bouyer 		ccb->ccb_sense_dva = MFII_DMA_DVA(sc->sc_sense) +
   2894   1.1    bouyer 		    ccb->ccb_sense_offset;
   2895   1.1    bouyer 
   2896   1.1    bouyer 		/* select i'th sgl */
   2897   1.1    bouyer 		ccb->ccb_sgl_offset = sizeof(struct mfii_sge) *
   2898   1.1    bouyer 		    sc->sc_max_sgl * i;
   2899   1.1    bouyer 		ccb->ccb_sgl = (struct mfii_sge *)(sgl + ccb->ccb_sgl_offset);
   2900   1.1    bouyer 		ccb->ccb_sgl_dva = MFII_DMA_DVA(sc->sc_sgl) +
   2901   1.1    bouyer 		    ccb->ccb_sgl_offset;
   2902   1.1    bouyer 
   2903   1.1    bouyer 		mutex_init(&ccb->ccb_mtx, MUTEX_DEFAULT, IPL_BIO);
   2904   1.1    bouyer 		cv_init(&ccb->ccb_cv, "mfiiexec");
   2905   1.1    bouyer 
   2906   1.1    bouyer 		/* add ccb to queue */
   2907   1.1    bouyer 		mfii_put_ccb(sc, ccb);
   2908   1.1    bouyer 	}
   2909   1.1    bouyer 
   2910   1.1    bouyer 	return (0);
   2911   1.1    bouyer 
   2912   1.1    bouyer destroy32:
   2913   1.1    bouyer 	bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap32);
   2914   1.1    bouyer destroy:
   2915   1.1    bouyer 	/* free dma maps and ccb memory */
   2916   1.1    bouyer 	while ((ccb = mfii_get_ccb(sc)) != NULL) {
   2917   1.1    bouyer 		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap32);
   2918   1.1    bouyer 		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap64);
   2919   1.1    bouyer 	}
   2920   1.1    bouyer 
   2921   1.1    bouyer 	free(sc->sc_ccb, M_DEVBUF);
   2922   1.1    bouyer 
   2923   1.1    bouyer 	return (1);
   2924   1.1    bouyer }
   2925   1.1    bouyer 
   2926   1.1    bouyer #if NBIO > 0
   2927   1.6      maxv static int
   2928   1.1    bouyer mfii_ioctl(device_t dev, u_long cmd, void *addr)
   2929   1.1    bouyer {
   2930   1.1    bouyer 	struct mfii_softc	*sc = device_private(dev);
   2931   1.1    bouyer 	int error = 0;
   2932   1.1    bouyer 
   2933   1.1    bouyer 	DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl ", DEVNAME(sc));
   2934   1.1    bouyer 
   2935   1.1    bouyer 	mutex_enter(&sc->sc_lock);
   2936   1.1    bouyer 
   2937   1.1    bouyer 	switch (cmd) {
   2938   1.1    bouyer 	case BIOCINQ:
   2939   1.1    bouyer 		DNPRINTF(MFII_D_IOCTL, "inq\n");
   2940   1.1    bouyer 		error = mfii_ioctl_inq(sc, (struct bioc_inq *)addr);
   2941   1.1    bouyer 		break;
   2942   1.1    bouyer 
   2943   1.1    bouyer 	case BIOCVOL:
   2944   1.1    bouyer 		DNPRINTF(MFII_D_IOCTL, "vol\n");
   2945   1.1    bouyer 		error = mfii_ioctl_vol(sc, (struct bioc_vol *)addr);
   2946   1.1    bouyer 		break;
   2947   1.1    bouyer 
   2948   1.1    bouyer 	case BIOCDISK:
   2949   1.1    bouyer 		DNPRINTF(MFII_D_IOCTL, "disk\n");
   2950   1.1    bouyer 		error = mfii_ioctl_disk(sc, (struct bioc_disk *)addr);
   2951   1.1    bouyer 		break;
   2952   1.1    bouyer 
   2953   1.1    bouyer 	case BIOCALARM:
   2954   1.1    bouyer 		DNPRINTF(MFII_D_IOCTL, "alarm\n");
   2955   1.1    bouyer 		error = mfii_ioctl_alarm(sc, (struct bioc_alarm *)addr);
   2956   1.1    bouyer 		break;
   2957   1.1    bouyer 
   2958   1.1    bouyer 	case BIOCBLINK:
   2959   1.1    bouyer 		DNPRINTF(MFII_D_IOCTL, "blink\n");
   2960   1.1    bouyer 		error = mfii_ioctl_blink(sc, (struct bioc_blink *)addr);
   2961   1.1    bouyer 		break;
   2962   1.1    bouyer 
   2963   1.1    bouyer 	case BIOCSETSTATE:
   2964   1.1    bouyer 		DNPRINTF(MFII_D_IOCTL, "setstate\n");
   2965   1.1    bouyer 		error = mfii_ioctl_setstate(sc, (struct bioc_setstate *)addr);
   2966   1.1    bouyer 		break;
   2967   1.1    bouyer 
   2968   1.1    bouyer #if 0
   2969   1.1    bouyer 	case BIOCPATROL:
   2970   1.1    bouyer 		DNPRINTF(MFII_D_IOCTL, "patrol\n");
   2971   1.1    bouyer 		error = mfii_ioctl_patrol(sc, (struct bioc_patrol *)addr);
   2972   1.1    bouyer 		break;
   2973   1.1    bouyer #endif
   2974   1.1    bouyer 
   2975   1.1    bouyer 	default:
   2976   1.1    bouyer 		DNPRINTF(MFII_D_IOCTL, " invalid ioctl\n");
   2977   1.1    bouyer 		error = ENOTTY;
   2978   1.1    bouyer 	}
   2979   1.1    bouyer 
   2980   1.1    bouyer 	mutex_exit(&sc->sc_lock);
   2981   1.1    bouyer 
   2982   1.1    bouyer 	return (error);
   2983   1.1    bouyer }
   2984   1.1    bouyer 
   2985   1.6      maxv static int
   2986   1.1    bouyer mfii_bio_getitall(struct mfii_softc *sc)
   2987   1.1    bouyer {
   2988   1.1    bouyer 	int			i, d, rv = EINVAL;
   2989   1.1    bouyer 	size_t			size;
   2990   1.1    bouyer 	union mfi_mbox		mbox;
   2991   1.1    bouyer 	struct mfi_conf		*cfg = NULL;
   2992   1.1    bouyer 	struct mfi_ld_details	*ld_det = NULL;
   2993   1.1    bouyer 
   2994   1.1    bouyer 	/* get info */
   2995   1.1    bouyer 	if (mfii_get_info(sc)) {
   2996   1.1    bouyer 		DNPRINTF(MFII_D_IOCTL, "%s: mfii_get_info failed\n",
   2997   1.1    bouyer 		    DEVNAME(sc));
   2998   1.1    bouyer 		goto done;
   2999   1.1    bouyer 	}
   3000   1.1    bouyer 
   3001   1.1    bouyer 	/* send single element command to retrieve size for full structure */
   3002   1.1    bouyer 	cfg = malloc(sizeof *cfg, M_DEVBUF, M_NOWAIT | M_ZERO);
   3003   1.1    bouyer 	if (cfg == NULL)
   3004   1.1    bouyer 		goto done;
   3005   1.1    bouyer 	if (mfii_mgmt(sc, MR_DCMD_CONF_GET, NULL, cfg, sizeof(*cfg),
   3006   1.1    bouyer 	    MFII_DATA_IN, false)) {
   3007   1.1    bouyer 		free(cfg, M_DEVBUF);
   3008   1.1    bouyer 		goto done;
   3009   1.1    bouyer 	}
   3010   1.1    bouyer 
   3011   1.1    bouyer 	size = cfg->mfc_size;
   3012   1.1    bouyer 	free(cfg, M_DEVBUF);
   3013   1.1    bouyer 
   3014   1.1    bouyer 	/* memory for read config */
   3015   1.1    bouyer 	cfg = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
   3016   1.1    bouyer 	if (cfg == NULL)
   3017   1.1    bouyer 		goto done;
   3018   1.1    bouyer 	if (mfii_mgmt(sc, MR_DCMD_CONF_GET, NULL, cfg, size,
   3019   1.1    bouyer 	    MFII_DATA_IN, false)) {
   3020   1.1    bouyer 		free(cfg, M_DEVBUF);
   3021   1.1    bouyer 		goto done;
   3022   1.1    bouyer 	}
   3023   1.1    bouyer 
   3024   1.1    bouyer 	/* replace current pointer with new one */
   3025   1.1    bouyer 	if (sc->sc_cfg)
   3026   1.1    bouyer 		free(sc->sc_cfg, M_DEVBUF);
   3027   1.1    bouyer 	sc->sc_cfg = cfg;
   3028   1.1    bouyer 
   3029   1.1    bouyer 	/* get all ld info */
   3030  1.24   msaitoh 	memset(&mbox, 0, sizeof(mbox));
   3031  1.24   msaitoh 	if (sc->sc_max256vd)
   3032  1.24   msaitoh 		mbox.b[0] = 1;
   3033  1.24   msaitoh 	if (mfii_mgmt(sc, MR_DCMD_LD_GET_LIST, &mbox, &sc->sc_ld_list,
   3034   1.1    bouyer 	    sizeof(sc->sc_ld_list), MFII_DATA_IN, false))
   3035   1.1    bouyer 		goto done;
   3036   1.1    bouyer 
   3037   1.1    bouyer 	/* get memory for all ld structures */
   3038   1.1    bouyer 	size = cfg->mfc_no_ld * sizeof(struct mfi_ld_details);
   3039   1.1    bouyer 	if (sc->sc_ld_sz != size) {
   3040   1.1    bouyer 		if (sc->sc_ld_details)
   3041   1.1    bouyer 			free(sc->sc_ld_details, M_DEVBUF);
   3042   1.1    bouyer 
   3043   1.1    bouyer 		ld_det = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
   3044   1.1    bouyer 		if (ld_det == NULL)
   3045   1.1    bouyer 			goto done;
   3046   1.1    bouyer 		sc->sc_ld_sz = size;
   3047   1.1    bouyer 		sc->sc_ld_details = ld_det;
   3048   1.1    bouyer 	}
   3049   1.1    bouyer 
   3050   1.1    bouyer 	/* find used physical disks */
   3051   1.1    bouyer 	size = sizeof(struct mfi_ld_details);
   3052   1.1    bouyer 	for (i = 0, d = 0; i < cfg->mfc_no_ld; i++) {
   3053   1.1    bouyer 		memset(&mbox, 0, sizeof(mbox));
   3054   1.1    bouyer 		mbox.b[0] = sc->sc_ld_list.mll_list[i].mll_ld.mld_target;
   3055   1.1    bouyer 		if (mfii_mgmt(sc, MR_DCMD_LD_GET_INFO, &mbox,
   3056   1.1    bouyer 		    &sc->sc_ld_details[i], size, MFII_DATA_IN, false))
   3057   1.1    bouyer 			goto done;
   3058   1.1    bouyer 
   3059   1.1    bouyer 		d += sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_no_drv_per_span *
   3060   1.1    bouyer 		    sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_span_depth;
   3061   1.1    bouyer 	}
   3062   1.1    bouyer 	sc->sc_no_pd = d;
   3063   1.1    bouyer 
   3064   1.1    bouyer 	rv = 0;
   3065   1.1    bouyer done:
   3066   1.1    bouyer 	return (rv);
   3067   1.1    bouyer }
   3068   1.1    bouyer 
   3069   1.6      maxv static int
   3070   1.1    bouyer mfii_ioctl_inq(struct mfii_softc *sc, struct bioc_inq *bi)
   3071   1.1    bouyer {
   3072   1.1    bouyer 	int			rv = EINVAL;
   3073   1.1    bouyer 	struct mfi_conf		*cfg = NULL;
   3074   1.1    bouyer 
   3075   1.1    bouyer 	DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_inq\n", DEVNAME(sc));
   3076   1.1    bouyer 
   3077   1.1    bouyer 	if (mfii_bio_getitall(sc)) {
   3078   1.1    bouyer 		DNPRINTF(MFII_D_IOCTL, "%s: mfii_bio_getitall failed\n",
   3079   1.1    bouyer 		    DEVNAME(sc));
   3080   1.1    bouyer 		goto done;
   3081   1.1    bouyer 	}
   3082   1.1    bouyer 
   3083   1.1    bouyer 	/* count unused disks as volumes */
   3084   1.1    bouyer 	if (sc->sc_cfg == NULL)
   3085   1.1    bouyer 		goto done;
   3086   1.1    bouyer 	cfg = sc->sc_cfg;
   3087   1.1    bouyer 
   3088   1.1    bouyer 	bi->bi_nodisk = sc->sc_info.mci_pd_disks_present;
   3089   1.1    bouyer 	bi->bi_novol = cfg->mfc_no_ld + cfg->mfc_no_hs;
   3090   1.1    bouyer #if notyet
   3091   1.1    bouyer 	bi->bi_novol = cfg->mfc_no_ld + cfg->mfc_no_hs +
   3092   1.1    bouyer 	    (bi->bi_nodisk - sc->sc_no_pd);
   3093   1.1    bouyer #endif
   3094   1.1    bouyer 	/* tell bio who we are */
   3095   1.1    bouyer 	strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev));
   3096   1.1    bouyer 
   3097   1.1    bouyer 	rv = 0;
   3098   1.1    bouyer done:
   3099   1.1    bouyer 	return (rv);
   3100   1.1    bouyer }
   3101   1.1    bouyer 
   3102   1.6      maxv static int
   3103   1.1    bouyer mfii_ioctl_vol(struct mfii_softc *sc, struct bioc_vol *bv)
   3104   1.1    bouyer {
   3105   1.1    bouyer 	int			i, per, rv = EINVAL;
   3106   1.1    bouyer 
   3107   1.1    bouyer 	DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_vol %#x\n",
   3108   1.1    bouyer 	    DEVNAME(sc), bv->bv_volid);
   3109   1.1    bouyer 
   3110   1.1    bouyer 	/* we really could skip and expect that inq took care of it */
   3111   1.1    bouyer 	if (mfii_bio_getitall(sc)) {
   3112   1.1    bouyer 		DNPRINTF(MFII_D_IOCTL, "%s: mfii_bio_getitall failed\n",
   3113   1.1    bouyer 		    DEVNAME(sc));
   3114   1.1    bouyer 		goto done;
   3115   1.1    bouyer 	}
   3116   1.1    bouyer 
   3117   1.1    bouyer 	if (bv->bv_volid >= sc->sc_ld_list.mll_no_ld) {
   3118   1.1    bouyer 		/* go do hotspares & unused disks */
   3119   1.1    bouyer 		rv = mfii_bio_hs(sc, bv->bv_volid, MFI_MGMT_VD, bv);
   3120   1.1    bouyer 		goto done;
   3121   1.1    bouyer 	}
   3122   1.1    bouyer 
   3123   1.1    bouyer 	i = bv->bv_volid;
   3124   1.1    bouyer 	strlcpy(bv->bv_dev, sc->sc_ld_details[i].mld_cfg.mlc_prop.mlp_name,
   3125   1.1    bouyer 	    sizeof(bv->bv_dev));
   3126   1.1    bouyer 
   3127  1.10   msaitoh 	switch (sc->sc_ld_list.mll_list[i].mll_state) {
   3128   1.1    bouyer 	case MFI_LD_OFFLINE:
   3129   1.1    bouyer 		bv->bv_status = BIOC_SVOFFLINE;
   3130   1.1    bouyer 		break;
   3131   1.1    bouyer 
   3132   1.1    bouyer 	case MFI_LD_PART_DEGRADED:
   3133   1.1    bouyer 	case MFI_LD_DEGRADED:
   3134   1.1    bouyer 		bv->bv_status = BIOC_SVDEGRADED;
   3135   1.1    bouyer 		break;
   3136   1.1    bouyer 
   3137   1.1    bouyer 	case MFI_LD_ONLINE:
   3138   1.1    bouyer 		bv->bv_status = BIOC_SVONLINE;
   3139   1.1    bouyer 		break;
   3140   1.1    bouyer 
   3141   1.1    bouyer 	default:
   3142   1.1    bouyer 		bv->bv_status = BIOC_SVINVALID;
   3143   1.1    bouyer 		DNPRINTF(MFII_D_IOCTL, "%s: invalid logical disk state %#x\n",
   3144   1.1    bouyer 		    DEVNAME(sc),
   3145   1.1    bouyer 		    sc->sc_ld_list.mll_list[i].mll_state);
   3146   1.1    bouyer 	}
   3147   1.1    bouyer 
   3148   1.1    bouyer 	/* additional status can modify MFI status */
   3149   1.1    bouyer 	switch (sc->sc_ld_details[i].mld_progress.mlp_in_prog) {
   3150   1.1    bouyer 	case MFI_LD_PROG_CC:
   3151   1.1    bouyer 		bv->bv_status = BIOC_SVSCRUB;
   3152   1.1    bouyer 		per = (int)sc->sc_ld_details[i].mld_progress.mlp_cc.mp_progress;
   3153   1.1    bouyer 		bv->bv_percent = (per * 100) / 0xffff;
   3154   1.1    bouyer 		bv->bv_seconds =
   3155   1.1    bouyer 		    sc->sc_ld_details[i].mld_progress.mlp_cc.mp_elapsed_seconds;
   3156   1.1    bouyer 		break;
   3157   1.1    bouyer 
   3158  1.11   msaitoh 	case MFI_LD_PROG_BGI:
   3159  1.11   msaitoh 		bv->bv_status = BIOC_SVSCRUB;
   3160  1.11   msaitoh 		per = (int)sc->sc_ld_details[i].mld_progress.mlp_bgi.mp_progress;
   3161  1.11   msaitoh 		bv->bv_percent = (per * 100) / 0xffff;
   3162  1.11   msaitoh 		bv->bv_seconds =
   3163  1.11   msaitoh 		    sc->sc_ld_details[i].mld_progress.mlp_bgi.mp_elapsed_seconds;
   3164  1.11   msaitoh 		break;
   3165  1.11   msaitoh 
   3166   1.1    bouyer 	case MFI_LD_PROG_FGI:
   3167   1.1    bouyer 	case MFI_LD_PROG_RECONSTRUCT:
   3168   1.1    bouyer 		/* nothing yet */
   3169   1.1    bouyer 		break;
   3170   1.1    bouyer 	}
   3171   1.1    bouyer 
   3172   1.1    bouyer #if 0
   3173   1.1    bouyer 	if (sc->sc_ld_details[i].mld_cfg.mlc_prop.mlp_cur_cache_policy & 0x01)
   3174   1.1    bouyer 		bv->bv_cache = BIOC_CVWRITEBACK;
   3175   1.1    bouyer 	else
   3176   1.1    bouyer 		bv->bv_cache = BIOC_CVWRITETHROUGH;
   3177   1.1    bouyer #endif
   3178   1.1    bouyer 
   3179   1.1    bouyer 	/*
   3180   1.1    bouyer 	 * The RAID levels are determined per the SNIA DDF spec, this is only
   3181   1.1    bouyer 	 * a subset that is valid for the MFI controller.
   3182   1.1    bouyer 	 */
   3183   1.1    bouyer 	bv->bv_level = sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_pri_raid;
   3184   1.1    bouyer 	if (sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_span_depth > 1)
   3185   1.1    bouyer 		bv->bv_level *= 10;
   3186   1.1    bouyer 
   3187  1.19   msaitoh 	bv->bv_nodisk =
   3188  1.19   msaitoh 	    sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_no_drv_per_span *
   3189   1.1    bouyer 	    sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_span_depth;
   3190   1.1    bouyer 
   3191   1.1    bouyer 	bv->bv_size = sc->sc_ld_details[i].mld_size * 512; /* bytes per block */
   3192  1.12   msaitoh 	bv->bv_stripe_size =
   3193  1.12   msaitoh 	    (512 << sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_stripe_size)
   3194  1.12   msaitoh 	    / 1024; /* in KB */
   3195   1.1    bouyer 
   3196   1.1    bouyer 	rv = 0;
   3197   1.1    bouyer done:
   3198   1.1    bouyer 	return (rv);
   3199   1.1    bouyer }
   3200   1.1    bouyer 
   3201   1.6      maxv static int
   3202   1.1    bouyer mfii_ioctl_disk(struct mfii_softc *sc, struct bioc_disk *bd)
   3203   1.1    bouyer {
   3204   1.1    bouyer 	struct mfi_conf		*cfg;
   3205   1.1    bouyer 	struct mfi_array	*ar;
   3206   1.1    bouyer 	struct mfi_ld_cfg	*ld;
   3207   1.1    bouyer 	struct mfi_pd_details	*pd;
   3208   1.1    bouyer 	struct mfi_pd_list	*pl;
   3209   1.1    bouyer 	struct scsipi_inquiry_data *inqbuf;
   3210   1.1    bouyer 	char			vend[8+16+4+1], *vendp;
   3211   1.1    bouyer 	int			i, rv = EINVAL;
   3212   1.1    bouyer 	int			arr, vol, disk, span;
   3213   1.1    bouyer 	union mfi_mbox		mbox;
   3214   1.1    bouyer 
   3215   1.1    bouyer 	DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_disk %#x\n",
   3216   1.1    bouyer 	    DEVNAME(sc), bd->bd_diskid);
   3217   1.1    bouyer 
   3218   1.1    bouyer 	/* we really could skip and expect that inq took care of it */
   3219   1.1    bouyer 	if (mfii_bio_getitall(sc)) {
   3220   1.1    bouyer 		DNPRINTF(MFII_D_IOCTL, "%s: mfii_bio_getitall failed\n",
   3221   1.1    bouyer 		    DEVNAME(sc));
   3222   1.1    bouyer 		return (rv);
   3223   1.1    bouyer 	}
   3224   1.1    bouyer 	cfg = sc->sc_cfg;
   3225   1.1    bouyer 
   3226   1.1    bouyer 	pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
   3227   1.1    bouyer 	pl = malloc(sizeof *pl, M_DEVBUF, M_WAITOK);
   3228   1.1    bouyer 
   3229   1.1    bouyer 	ar = cfg->mfc_array;
   3230   1.1    bouyer 	vol = bd->bd_volid;
   3231   1.1    bouyer 	if (vol >= cfg->mfc_no_ld) {
   3232   1.1    bouyer 		/* do hotspares */
   3233   1.1    bouyer 		rv = mfii_bio_hs(sc, bd->bd_volid, MFI_MGMT_SD, bd);
   3234   1.1    bouyer 		goto freeme;
   3235   1.1    bouyer 	}
   3236   1.1    bouyer 
   3237   1.1    bouyer 	/* calculate offset to ld structure */
   3238   1.1    bouyer 	ld = (struct mfi_ld_cfg *)(
   3239   1.1    bouyer 	    ((uint8_t *)cfg) + offsetof(struct mfi_conf, mfc_array) +
   3240   1.1    bouyer 	    cfg->mfc_array_size * cfg->mfc_no_array);
   3241   1.1    bouyer 
   3242   1.1    bouyer 	/* use span 0 only when raid group is not spanned */
   3243   1.1    bouyer 	if (ld[vol].mlc_parm.mpa_span_depth > 1)
   3244   1.1    bouyer 		span = bd->bd_diskid / ld[vol].mlc_parm.mpa_no_drv_per_span;
   3245   1.1    bouyer 	else
   3246   1.1    bouyer 		span = 0;
   3247   1.1    bouyer 	arr = ld[vol].mlc_span[span].mls_index;
   3248   1.1    bouyer 
   3249   1.1    bouyer 	/* offset disk into pd list */
   3250   1.1    bouyer 	disk = bd->bd_diskid % ld[vol].mlc_parm.mpa_no_drv_per_span;
   3251   1.1    bouyer 
   3252   1.1    bouyer 	if (ar[arr].pd[disk].mar_pd.mfp_id == 0xffffU) {
   3253   1.1    bouyer 		/* disk is missing but succeed command */
   3254   1.1    bouyer 		bd->bd_status = BIOC_SDFAILED;
   3255   1.1    bouyer 		rv = 0;
   3256   1.1    bouyer 
   3257   1.1    bouyer 		/* try to find an unused disk for the target to rebuild */
   3258   1.1    bouyer 		if (mfii_mgmt(sc, MR_DCMD_PD_GET_LIST, NULL, pl, sizeof(*pl),
   3259   1.1    bouyer 		    MFII_DATA_IN, false))
   3260   1.1    bouyer 			goto freeme;
   3261   1.1    bouyer 
   3262   1.1    bouyer 		for (i = 0; i < pl->mpl_no_pd; i++) {
   3263   1.1    bouyer 			if (pl->mpl_address[i].mpa_scsi_type != 0)
   3264   1.1    bouyer 				continue;
   3265   1.1    bouyer 
   3266   1.1    bouyer 			memset(&mbox, 0, sizeof(mbox));
   3267   1.1    bouyer 			mbox.s[0] = pl->mpl_address[i].mpa_pd_id;
   3268   1.1    bouyer 			if (mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox,
   3269   1.1    bouyer 			    pd, sizeof(*pd), MFII_DATA_IN, false))
   3270   1.1    bouyer 				continue;
   3271   1.1    bouyer 
   3272   1.1    bouyer 			if (pd->mpd_fw_state == MFI_PD_UNCONFIG_GOOD ||
   3273   1.1    bouyer 			    pd->mpd_fw_state == MFI_PD_UNCONFIG_BAD)
   3274   1.1    bouyer 				break;
   3275   1.1    bouyer 		}
   3276   1.1    bouyer 
   3277   1.1    bouyer 		if (i == pl->mpl_no_pd)
   3278   1.1    bouyer 			goto freeme;
   3279   1.1    bouyer 	} else {
   3280   1.1    bouyer 		memset(&mbox, 0, sizeof(mbox));
   3281   1.1    bouyer 		mbox.s[0] = ar[arr].pd[disk].mar_pd.mfp_id;
   3282   1.1    bouyer 		if (mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
   3283   1.1    bouyer 		    MFII_DATA_IN, false)) {
   3284   1.1    bouyer 			bd->bd_status = BIOC_SDINVALID;
   3285   1.1    bouyer 			goto freeme;
   3286   1.1    bouyer 		}
   3287   1.1    bouyer 	}
   3288   1.1    bouyer 
   3289   1.1    bouyer 	/* get the remaining fields */
   3290   1.1    bouyer 	bd->bd_channel = pd->mpd_enc_idx;
   3291   1.1    bouyer 	bd->bd_target = pd->mpd_enc_slot;
   3292   1.1    bouyer 
   3293   1.1    bouyer 	/* get status */
   3294   1.1    bouyer 	switch (pd->mpd_fw_state){
   3295   1.1    bouyer 	case MFI_PD_UNCONFIG_GOOD:
   3296   1.1    bouyer 	case MFI_PD_UNCONFIG_BAD:
   3297   1.1    bouyer 		bd->bd_status = BIOC_SDUNUSED;
   3298   1.1    bouyer 		break;
   3299   1.1    bouyer 
   3300   1.1    bouyer 	case MFI_PD_HOTSPARE: /* XXX dedicated hotspare part of array? */
   3301   1.1    bouyer 		bd->bd_status = BIOC_SDHOTSPARE;
   3302   1.1    bouyer 		break;
   3303   1.1    bouyer 
   3304   1.1    bouyer 	case MFI_PD_OFFLINE:
   3305   1.1    bouyer 		bd->bd_status = BIOC_SDOFFLINE;
   3306   1.1    bouyer 		break;
   3307   1.1    bouyer 
   3308   1.1    bouyer 	case MFI_PD_FAILED:
   3309   1.1    bouyer 		bd->bd_status = BIOC_SDFAILED;
   3310   1.1    bouyer 		break;
   3311   1.1    bouyer 
   3312   1.1    bouyer 	case MFI_PD_REBUILD:
   3313   1.1    bouyer 		bd->bd_status = BIOC_SDREBUILD;
   3314   1.1    bouyer 		break;
   3315   1.1    bouyer 
   3316   1.1    bouyer 	case MFI_PD_ONLINE:
   3317   1.1    bouyer 		bd->bd_status = BIOC_SDONLINE;
   3318   1.1    bouyer 		break;
   3319   1.1    bouyer 
   3320   1.1    bouyer 	case MFI_PD_COPYBACK:
   3321   1.1    bouyer 	case MFI_PD_SYSTEM:
   3322   1.1    bouyer 	default:
   3323   1.1    bouyer 		bd->bd_status = BIOC_SDINVALID;
   3324   1.1    bouyer 		break;
   3325   1.1    bouyer 	}
   3326   1.1    bouyer 
   3327   1.1    bouyer 	bd->bd_size = pd->mpd_size * 512; /* bytes per block */
   3328   1.1    bouyer 
   3329   1.1    bouyer 	inqbuf = (struct scsipi_inquiry_data *)&pd->mpd_inq_data;
   3330   1.1    bouyer 	vendp = inqbuf->vendor;
   3331   1.1    bouyer 	memcpy(vend, vendp, sizeof vend - 1);
   3332   1.1    bouyer 	vend[sizeof vend - 1] = '\0';
   3333   1.1    bouyer 	strlcpy(bd->bd_vendor, vend, sizeof(bd->bd_vendor));
   3334   1.1    bouyer 
   3335   1.1    bouyer 	/* XXX find a way to retrieve serial nr from drive */
   3336   1.1    bouyer 	/* XXX find a way to get bd_procdev */
   3337   1.1    bouyer 
   3338   1.1    bouyer #if 0
   3339   1.1    bouyer 	mfp = &pd->mpd_progress;
   3340   1.1    bouyer 	if (mfp->mfp_in_prog & MFI_PD_PROG_PR) {
   3341   1.1    bouyer 		mp = &mfp->mfp_patrol_read;
   3342   1.1    bouyer 		bd->bd_patrol.bdp_percent = (mp->mp_progress * 100) / 0xffff;
   3343   1.1    bouyer 		bd->bd_patrol.bdp_seconds = mp->mp_elapsed_seconds;
   3344   1.1    bouyer 	}
   3345   1.1    bouyer #endif
   3346   1.1    bouyer 
   3347   1.1    bouyer 	rv = 0;
   3348   1.1    bouyer freeme:
   3349   1.1    bouyer 	free(pd, M_DEVBUF);
   3350   1.1    bouyer 	free(pl, M_DEVBUF);
   3351   1.1    bouyer 
   3352   1.1    bouyer 	return (rv);
   3353   1.1    bouyer }
   3354   1.1    bouyer 
   3355   1.6      maxv static int
   3356   1.1    bouyer mfii_ioctl_alarm(struct mfii_softc *sc, struct bioc_alarm *ba)
   3357   1.1    bouyer {
   3358   1.1    bouyer 	uint32_t		opc;
   3359   1.1    bouyer 	int			rv = 0;
   3360   1.1    bouyer 	int8_t			ret;
   3361   1.1    bouyer 	mfii_direction_t dir = MFII_DATA_NONE;
   3362   1.1    bouyer 
   3363  1.10   msaitoh 	switch (ba->ba_opcode) {
   3364   1.1    bouyer 	case BIOC_SADISABLE:
   3365   1.1    bouyer 		opc = MR_DCMD_SPEAKER_DISABLE;
   3366   1.1    bouyer 		break;
   3367   1.1    bouyer 
   3368   1.1    bouyer 	case BIOC_SAENABLE:
   3369   1.1    bouyer 		opc = MR_DCMD_SPEAKER_ENABLE;
   3370   1.1    bouyer 		break;
   3371   1.1    bouyer 
   3372   1.1    bouyer 	case BIOC_SASILENCE:
   3373   1.1    bouyer 		opc = MR_DCMD_SPEAKER_SILENCE;
   3374   1.1    bouyer 		break;
   3375   1.1    bouyer 
   3376   1.1    bouyer 	case BIOC_GASTATUS:
   3377   1.1    bouyer 		opc = MR_DCMD_SPEAKER_GET;
   3378   1.1    bouyer 		dir = MFII_DATA_IN;
   3379   1.1    bouyer 		break;
   3380   1.1    bouyer 
   3381   1.1    bouyer 	case BIOC_SATEST:
   3382   1.1    bouyer 		opc = MR_DCMD_SPEAKER_TEST;
   3383   1.1    bouyer 		break;
   3384   1.1    bouyer 
   3385   1.1    bouyer 	default:
   3386  1.19   msaitoh 		DNPRINTF(MFII_D_IOCTL,
   3387  1.19   msaitoh 		    "%s: mfii_ioctl_alarm biocalarm invalid opcode %x\n",
   3388  1.19   msaitoh 		    DEVNAME(sc), ba->ba_opcode);
   3389   1.1    bouyer 		return (EINVAL);
   3390   1.1    bouyer 	}
   3391   1.1    bouyer 
   3392   1.1    bouyer 	if (mfii_mgmt(sc, opc, NULL, &ret, sizeof(ret), dir, false))
   3393   1.1    bouyer 		rv = EINVAL;
   3394   1.1    bouyer 	else
   3395   1.1    bouyer 		if (ba->ba_opcode == BIOC_GASTATUS)
   3396   1.1    bouyer 			ba->ba_status = ret;
   3397   1.1    bouyer 		else
   3398   1.1    bouyer 			ba->ba_status = 0;
   3399   1.1    bouyer 
   3400   1.1    bouyer 	return (rv);
   3401   1.1    bouyer }
   3402   1.1    bouyer 
   3403   1.6      maxv static int
   3404   1.1    bouyer mfii_ioctl_blink(struct mfii_softc *sc, struct bioc_blink *bb)
   3405   1.1    bouyer {
   3406   1.1    bouyer 	int			i, found, rv = EINVAL;
   3407   1.1    bouyer 	union mfi_mbox		mbox;
   3408   1.1    bouyer 	uint32_t		cmd;
   3409   1.1    bouyer 	struct mfi_pd_list	*pd;
   3410   1.1    bouyer 
   3411   1.1    bouyer 	DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_blink %x\n", DEVNAME(sc),
   3412   1.1    bouyer 	    bb->bb_status);
   3413   1.1    bouyer 
   3414   1.1    bouyer 	/* channel 0 means not in an enclosure so can't be blinked */
   3415   1.1    bouyer 	if (bb->bb_channel == 0)
   3416   1.1    bouyer 		return (EINVAL);
   3417   1.1    bouyer 
   3418   1.1    bouyer 	pd = malloc(sizeof(*pd), M_DEVBUF, M_WAITOK);
   3419   1.1    bouyer 
   3420   1.1    bouyer 	if (mfii_mgmt(sc, MR_DCMD_PD_GET_LIST, NULL, pd, sizeof(*pd),
   3421   1.1    bouyer 	    MFII_DATA_IN, false))
   3422   1.1    bouyer 		goto done;
   3423   1.1    bouyer 
   3424   1.1    bouyer 	for (i = 0, found = 0; i < pd->mpl_no_pd; i++)
   3425   1.1    bouyer 		if (bb->bb_channel == pd->mpl_address[i].mpa_enc_index &&
   3426   1.1    bouyer 		    bb->bb_target == pd->mpl_address[i].mpa_enc_slot) {
   3427   1.1    bouyer 			found = 1;
   3428   1.1    bouyer 			break;
   3429   1.1    bouyer 		}
   3430   1.1    bouyer 
   3431   1.1    bouyer 	if (!found)
   3432   1.1    bouyer 		goto done;
   3433   1.1    bouyer 
   3434   1.1    bouyer 	memset(&mbox, 0, sizeof(mbox));
   3435   1.1    bouyer 	mbox.s[0] = pd->mpl_address[i].mpa_pd_id;
   3436   1.1    bouyer 
   3437   1.1    bouyer 	switch (bb->bb_status) {
   3438   1.1    bouyer 	case BIOC_SBUNBLINK:
   3439   1.1    bouyer 		cmd = MR_DCMD_PD_UNBLINK;
   3440   1.1    bouyer 		break;
   3441   1.1    bouyer 
   3442   1.1    bouyer 	case BIOC_SBBLINK:
   3443   1.1    bouyer 		cmd = MR_DCMD_PD_BLINK;
   3444   1.1    bouyer 		break;
   3445   1.1    bouyer 
   3446   1.1    bouyer 	case BIOC_SBALARM:
   3447   1.1    bouyer 	default:
   3448  1.19   msaitoh 		DNPRINTF(MFII_D_IOCTL,
   3449  1.19   msaitoh 		    "%s: mfii_ioctl_blink biocblink invalid opcode %x\n",
   3450  1.19   msaitoh 		    DEVNAME(sc), bb->bb_status);
   3451   1.1    bouyer 		goto done;
   3452   1.1    bouyer 	}
   3453   1.1    bouyer 
   3454   1.1    bouyer 
   3455   1.1    bouyer 	if (mfii_mgmt(sc, cmd, &mbox, NULL, 0, MFII_DATA_NONE, false))
   3456   1.1    bouyer 		goto done;
   3457   1.1    bouyer 
   3458   1.1    bouyer 	rv = 0;
   3459   1.1    bouyer done:
   3460   1.1    bouyer 	free(pd, M_DEVBUF);
   3461   1.1    bouyer 	return (rv);
   3462   1.1    bouyer }
   3463   1.1    bouyer 
   3464   1.1    bouyer static int
   3465   1.1    bouyer mfii_makegood(struct mfii_softc *sc, uint16_t pd_id)
   3466   1.1    bouyer {
   3467   1.1    bouyer 	struct mfii_foreign_scan_info *fsi;
   3468   1.1    bouyer 	struct mfi_pd_details	*pd;
   3469   1.1    bouyer 	union mfi_mbox		mbox;
   3470   1.1    bouyer 	int			rv;
   3471   1.1    bouyer 
   3472   1.1    bouyer 	fsi = malloc(sizeof *fsi, M_DEVBUF, M_WAITOK);
   3473   1.1    bouyer 	pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
   3474   1.1    bouyer 
   3475   1.1    bouyer 	memset(&mbox, 0, sizeof mbox);
   3476   1.1    bouyer 	mbox.s[0] = pd_id;
   3477   1.1    bouyer 	rv = mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
   3478   1.1    bouyer 	    MFII_DATA_IN, false);
   3479   1.1    bouyer 	if (rv != 0)
   3480   1.1    bouyer 		goto done;
   3481   1.1    bouyer 
   3482   1.1    bouyer 	if (pd->mpd_fw_state == MFI_PD_UNCONFIG_BAD) {
   3483   1.1    bouyer 		mbox.s[0] = pd_id;
   3484   1.1    bouyer 		mbox.s[1] = pd->mpd_pd.mfp_seq;
   3485   1.1    bouyer 		mbox.b[4] = MFI_PD_UNCONFIG_GOOD;
   3486   1.1    bouyer 		rv = mfii_mgmt(sc, MR_DCMD_PD_SET_STATE, &mbox, NULL, 0,
   3487   1.1    bouyer 		    MFII_DATA_NONE, false);
   3488   1.1    bouyer 		if (rv != 0)
   3489   1.1    bouyer 			goto done;
   3490   1.1    bouyer 	}
   3491   1.1    bouyer 
   3492   1.1    bouyer 	memset(&mbox, 0, sizeof mbox);
   3493   1.1    bouyer 	mbox.s[0] = pd_id;
   3494   1.1    bouyer 	rv = mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
   3495   1.1    bouyer 	    MFII_DATA_IN, false);
   3496   1.1    bouyer 	if (rv != 0)
   3497   1.1    bouyer 		goto done;
   3498   1.1    bouyer 
   3499   1.1    bouyer 	if (pd->mpd_ddf_state & MFI_DDF_FOREIGN) {
   3500   1.1    bouyer 		rv = mfii_mgmt(sc, MR_DCMD_CFG_FOREIGN_SCAN, NULL,
   3501   1.1    bouyer 		    fsi, sizeof(*fsi), MFII_DATA_IN, false);
   3502   1.1    bouyer 		if (rv != 0)
   3503   1.1    bouyer 			goto done;
   3504   1.1    bouyer 
   3505   1.1    bouyer 		if (fsi->count > 0) {
   3506   1.1    bouyer 			rv = mfii_mgmt(sc, MR_DCMD_CFG_FOREIGN_CLEAR, NULL,
   3507   1.1    bouyer 			    NULL, 0, MFII_DATA_NONE, false);
   3508   1.1    bouyer 			if (rv != 0)
   3509   1.1    bouyer 				goto done;
   3510   1.1    bouyer 		}
   3511   1.1    bouyer 	}
   3512   1.1    bouyer 
   3513   1.1    bouyer 	memset(&mbox, 0, sizeof mbox);
   3514   1.1    bouyer 	mbox.s[0] = pd_id;
   3515   1.1    bouyer 	rv = mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
   3516   1.1    bouyer 	    MFII_DATA_IN, false);
   3517   1.1    bouyer 	if (rv != 0)
   3518   1.1    bouyer 		goto done;
   3519   1.1    bouyer 
   3520   1.1    bouyer 	if (pd->mpd_fw_state != MFI_PD_UNCONFIG_GOOD ||
   3521   1.1    bouyer 	    pd->mpd_ddf_state & MFI_DDF_FOREIGN)
   3522   1.1    bouyer 		rv = ENXIO;
   3523   1.1    bouyer 
   3524   1.1    bouyer done:
   3525   1.1    bouyer 	free(fsi, M_DEVBUF);
   3526   1.1    bouyer 	free(pd, M_DEVBUF);
   3527   1.1    bouyer 
   3528   1.1    bouyer 	return (rv);
   3529   1.1    bouyer }
   3530   1.1    bouyer 
   3531   1.1    bouyer static int
   3532   1.1    bouyer mfii_makespare(struct mfii_softc *sc, uint16_t pd_id)
   3533   1.1    bouyer {
   3534   1.1    bouyer 	struct mfi_hotspare	*hs;
   3535   1.1    bouyer 	struct mfi_pd_details	*pd;
   3536   1.1    bouyer 	union mfi_mbox		mbox;
   3537   1.1    bouyer 	size_t			size;
   3538   1.1    bouyer 	int			rv = EINVAL;
   3539   1.1    bouyer 
   3540   1.1    bouyer 	/* we really could skip and expect that inq took care of it */
   3541   1.1    bouyer 	if (mfii_bio_getitall(sc)) {
   3542   1.1    bouyer 		DNPRINTF(MFII_D_IOCTL, "%s: mfii_bio_getitall failed\n",
   3543   1.1    bouyer 		    DEVNAME(sc));
   3544   1.1    bouyer 		return (rv);
   3545   1.1    bouyer 	}
   3546   1.1    bouyer 	size = sizeof *hs + sizeof(uint16_t) * sc->sc_cfg->mfc_no_array;
   3547   1.1    bouyer 
   3548   1.1    bouyer 	hs = malloc(size, M_DEVBUF, M_WAITOK);
   3549   1.1    bouyer 	pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
   3550   1.1    bouyer 
   3551   1.1    bouyer 	memset(&mbox, 0, sizeof mbox);
   3552   1.1    bouyer 	mbox.s[0] = pd_id;
   3553   1.1    bouyer 	rv = mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
   3554   1.1    bouyer 	    MFII_DATA_IN, false);
   3555   1.1    bouyer 	if (rv != 0)
   3556   1.1    bouyer 		goto done;
   3557   1.1    bouyer 
   3558   1.1    bouyer 	memset(hs, 0, size);
   3559   1.1    bouyer 	hs->mhs_pd.mfp_id = pd->mpd_pd.mfp_id;
   3560   1.1    bouyer 	hs->mhs_pd.mfp_seq = pd->mpd_pd.mfp_seq;
   3561   1.1    bouyer 	rv = mfii_mgmt(sc, MR_DCMD_CFG_MAKE_SPARE, NULL, hs, size,
   3562   1.1    bouyer 	    MFII_DATA_OUT, false);
   3563   1.1    bouyer 
   3564   1.1    bouyer done:
   3565   1.1    bouyer 	free(hs, M_DEVBUF);
   3566   1.1    bouyer 	free(pd, M_DEVBUF);
   3567   1.1    bouyer 
   3568   1.1    bouyer 	return (rv);
   3569   1.1    bouyer }
   3570   1.1    bouyer 
   3571   1.6      maxv static int
   3572   1.1    bouyer mfii_ioctl_setstate(struct mfii_softc *sc, struct bioc_setstate *bs)
   3573   1.1    bouyer {
   3574   1.1    bouyer 	struct mfi_pd_details	*pd;
   3575   1.1    bouyer 	struct mfi_pd_list	*pl;
   3576   1.1    bouyer 	int			i, found, rv = EINVAL;
   3577   1.1    bouyer 	union mfi_mbox		mbox;
   3578   1.1    bouyer 
   3579   1.1    bouyer 	DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_setstate %x\n", DEVNAME(sc),
   3580   1.1    bouyer 	    bs->bs_status);
   3581   1.1    bouyer 
   3582   1.1    bouyer 	pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
   3583   1.1    bouyer 	pl = malloc(sizeof *pl, M_DEVBUF, M_WAITOK);
   3584   1.1    bouyer 
   3585   1.1    bouyer 	if (mfii_mgmt(sc, MR_DCMD_PD_GET_LIST, NULL, pl, sizeof(*pl),
   3586   1.1    bouyer 	    MFII_DATA_IN, false))
   3587   1.1    bouyer 		goto done;
   3588   1.1    bouyer 
   3589   1.1    bouyer 	for (i = 0, found = 0; i < pl->mpl_no_pd; i++)
   3590   1.1    bouyer 		if (bs->bs_channel == pl->mpl_address[i].mpa_enc_index &&
   3591   1.1    bouyer 		    bs->bs_target == pl->mpl_address[i].mpa_enc_slot) {
   3592   1.1    bouyer 			found = 1;
   3593   1.1    bouyer 			break;
   3594   1.1    bouyer 		}
   3595   1.1    bouyer 
   3596   1.1    bouyer 	if (!found)
   3597   1.1    bouyer 		goto done;
   3598   1.1    bouyer 
   3599   1.1    bouyer 	memset(&mbox, 0, sizeof(mbox));
   3600   1.1    bouyer 	mbox.s[0] = pl->mpl_address[i].mpa_pd_id;
   3601   1.1    bouyer 
   3602   1.1    bouyer 	if (mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
   3603   1.1    bouyer 	    MFII_DATA_IN, false))
   3604   1.1    bouyer 		goto done;
   3605   1.1    bouyer 
   3606   1.1    bouyer 	mbox.s[0] = pl->mpl_address[i].mpa_pd_id;
   3607   1.1    bouyer 	mbox.s[1] = pd->mpd_pd.mfp_seq;
   3608   1.1    bouyer 
   3609   1.1    bouyer 	switch (bs->bs_status) {
   3610   1.1    bouyer 	case BIOC_SSONLINE:
   3611   1.1    bouyer 		mbox.b[4] = MFI_PD_ONLINE;
   3612   1.1    bouyer 		break;
   3613   1.1    bouyer 
   3614   1.1    bouyer 	case BIOC_SSOFFLINE:
   3615   1.1    bouyer 		mbox.b[4] = MFI_PD_OFFLINE;
   3616   1.1    bouyer 		break;
   3617   1.1    bouyer 
   3618   1.1    bouyer 	case BIOC_SSHOTSPARE:
   3619   1.1    bouyer 		mbox.b[4] = MFI_PD_HOTSPARE;
   3620   1.1    bouyer 		break;
   3621   1.1    bouyer 
   3622   1.1    bouyer 	case BIOC_SSREBUILD:
   3623   1.1    bouyer 		if (pd->mpd_fw_state != MFI_PD_OFFLINE) {
   3624   1.1    bouyer 			if ((rv = mfii_makegood(sc,
   3625   1.1    bouyer 			    pl->mpl_address[i].mpa_pd_id)))
   3626   1.1    bouyer 				goto done;
   3627   1.1    bouyer 
   3628   1.1    bouyer 			if ((rv = mfii_makespare(sc,
   3629   1.1    bouyer 			    pl->mpl_address[i].mpa_pd_id)))
   3630   1.1    bouyer 				goto done;
   3631   1.1    bouyer 
   3632   1.1    bouyer 			memset(&mbox, 0, sizeof(mbox));
   3633   1.1    bouyer 			mbox.s[0] = pl->mpl_address[i].mpa_pd_id;
   3634   1.1    bouyer 			rv = mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox,
   3635   1.1    bouyer 			    pd, sizeof(*pd), MFII_DATA_IN, false);
   3636   1.1    bouyer 			if (rv != 0)
   3637   1.1    bouyer 				goto done;
   3638   1.1    bouyer 
   3639   1.1    bouyer 			/* rebuilding might be started by mfii_makespare() */
   3640   1.1    bouyer 			if (pd->mpd_fw_state == MFI_PD_REBUILD) {
   3641   1.1    bouyer 				rv = 0;
   3642   1.1    bouyer 				goto done;
   3643   1.1    bouyer 			}
   3644   1.1    bouyer 
   3645   1.1    bouyer 			mbox.s[0] = pl->mpl_address[i].mpa_pd_id;
   3646   1.1    bouyer 			mbox.s[1] = pd->mpd_pd.mfp_seq;
   3647   1.1    bouyer 		}
   3648   1.1    bouyer 		mbox.b[4] = MFI_PD_REBUILD;
   3649   1.1    bouyer 		break;
   3650   1.1    bouyer 
   3651   1.1    bouyer 	default:
   3652   1.1    bouyer 		DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_setstate invalid "
   3653   1.1    bouyer 		    "opcode %x\n", DEVNAME(sc), bs->bs_status);
   3654   1.1    bouyer 		goto done;
   3655   1.1    bouyer 	}
   3656   1.1    bouyer 
   3657   1.1    bouyer 
   3658   1.1    bouyer 	rv = mfii_mgmt(sc, MR_DCMD_PD_SET_STATE, &mbox, NULL, 0,
   3659   1.1    bouyer 	    MFII_DATA_NONE, false);
   3660   1.1    bouyer done:
   3661   1.1    bouyer 	free(pd, M_DEVBUF);
   3662   1.1    bouyer 	free(pl, M_DEVBUF);
   3663   1.1    bouyer 	return (rv);
   3664   1.1    bouyer }
   3665   1.1    bouyer 
   3666   1.1    bouyer #if 0
   3667   1.1    bouyer int
   3668   1.1    bouyer mfii_ioctl_patrol(struct mfii_softc *sc, struct bioc_patrol *bp)
   3669   1.1    bouyer {
   3670   1.1    bouyer 	uint32_t		opc;
   3671   1.1    bouyer 	int			rv = 0;
   3672   1.1    bouyer 	struct mfi_pr_properties prop;
   3673   1.1    bouyer 	struct mfi_pr_status	status;
   3674   1.1    bouyer 	uint32_t		time, exec_freq;
   3675   1.1    bouyer 
   3676   1.1    bouyer 	switch (bp->bp_opcode) {
   3677   1.1    bouyer 	case BIOC_SPSTOP:
   3678   1.1    bouyer 	case BIOC_SPSTART:
   3679   1.1    bouyer 		if (bp->bp_opcode == BIOC_SPSTART)
   3680   1.1    bouyer 			opc = MR_DCMD_PR_START;
   3681   1.1    bouyer 		else
   3682   1.1    bouyer 			opc = MR_DCMD_PR_STOP;
   3683   1.1    bouyer 		if (mfii_mgmt(sc, opc, NULL, NULL, 0, MFII_DATA_IN, false))
   3684   1.1    bouyer 			return (EINVAL);
   3685   1.1    bouyer 		break;
   3686   1.1    bouyer 
   3687   1.1    bouyer 	case BIOC_SPMANUAL:
   3688   1.1    bouyer 	case BIOC_SPDISABLE:
   3689   1.1    bouyer 	case BIOC_SPAUTO:
   3690   1.1    bouyer 		/* Get device's time. */
   3691   1.1    bouyer 		opc = MR_DCMD_TIME_SECS_GET;
   3692   1.1    bouyer 		if (mfii_mgmt(sc, opc, NULL, &time, sizeof(time),
   3693   1.1    bouyer 		    MFII_DATA_IN, false))
   3694   1.1    bouyer 			return (EINVAL);
   3695   1.1    bouyer 
   3696   1.1    bouyer 		opc = MR_DCMD_PR_GET_PROPERTIES;
   3697   1.1    bouyer 		if (mfii_mgmt(sc, opc, NULL, &prop, sizeof(prop),
   3698   1.1    bouyer 		    MFII_DATA_IN, false))
   3699   1.1    bouyer 			return (EINVAL);
   3700   1.1    bouyer 
   3701   1.1    bouyer 		switch (bp->bp_opcode) {
   3702   1.1    bouyer 		case BIOC_SPMANUAL:
   3703   1.1    bouyer 			prop.op_mode = MFI_PR_OPMODE_MANUAL;
   3704   1.1    bouyer 			break;
   3705   1.1    bouyer 		case BIOC_SPDISABLE:
   3706   1.1    bouyer 			prop.op_mode = MFI_PR_OPMODE_DISABLED;
   3707   1.1    bouyer 			break;
   3708   1.1    bouyer 		case BIOC_SPAUTO:
   3709   1.1    bouyer 			if (bp->bp_autoival != 0) {
   3710   1.1    bouyer 				if (bp->bp_autoival == -1)
   3711   1.1    bouyer 					/* continuously */
   3712   1.1    bouyer 					exec_freq = 0xffffffffU;
   3713   1.1    bouyer 				else if (bp->bp_autoival > 0)
   3714   1.1    bouyer 					exec_freq = bp->bp_autoival;
   3715   1.1    bouyer 				else
   3716   1.1    bouyer 					return (EINVAL);
   3717   1.1    bouyer 				prop.exec_freq = exec_freq;
   3718   1.1    bouyer 			}
   3719   1.1    bouyer 			if (bp->bp_autonext != 0) {
   3720   1.1    bouyer 				if (bp->bp_autonext < 0)
   3721   1.1    bouyer 					return (EINVAL);
   3722   1.1    bouyer 				else
   3723  1.19   msaitoh 					prop.next_exec =
   3724  1.19   msaitoh 					    time + bp->bp_autonext;
   3725   1.1    bouyer 			}
   3726   1.1    bouyer 			prop.op_mode = MFI_PR_OPMODE_AUTO;
   3727   1.1    bouyer 			break;
   3728   1.1    bouyer 		}
   3729   1.1    bouyer 
   3730   1.1    bouyer 		opc = MR_DCMD_PR_SET_PROPERTIES;
   3731   1.1    bouyer 		if (mfii_mgmt(sc, opc, NULL, &prop, sizeof(prop),
   3732   1.1    bouyer 		    MFII_DATA_OUT, false))
   3733   1.1    bouyer 			return (EINVAL);
   3734   1.1    bouyer 
   3735   1.1    bouyer 		break;
   3736   1.1    bouyer 
   3737   1.1    bouyer 	case BIOC_GPSTATUS:
   3738   1.1    bouyer 		opc = MR_DCMD_PR_GET_PROPERTIES;
   3739   1.1    bouyer 		if (mfii_mgmt(sc, opc, NULL, &prop, sizeof(prop),
   3740   1.1    bouyer 		    MFII_DATA_IN, false))
   3741   1.1    bouyer 			return (EINVAL);
   3742   1.1    bouyer 
   3743   1.1    bouyer 		opc = MR_DCMD_PR_GET_STATUS;
   3744   1.1    bouyer 		if (mfii_mgmt(sc, opc, NULL, &status, sizeof(status),
   3745   1.1    bouyer 		    MFII_DATA_IN, false))
   3746   1.1    bouyer 			return (EINVAL);
   3747   1.1    bouyer 
   3748   1.1    bouyer 		/* Get device's time. */
   3749   1.1    bouyer 		opc = MR_DCMD_TIME_SECS_GET;
   3750   1.1    bouyer 		if (mfii_mgmt(sc, opc, NULL, &time, sizeof(time),
   3751   1.1    bouyer 		    MFII_DATA_IN, false))
   3752   1.1    bouyer 			return (EINVAL);
   3753   1.1    bouyer 
   3754   1.1    bouyer 		switch (prop.op_mode) {
   3755   1.1    bouyer 		case MFI_PR_OPMODE_AUTO:
   3756   1.1    bouyer 			bp->bp_mode = BIOC_SPMAUTO;
   3757   1.1    bouyer 			bp->bp_autoival = prop.exec_freq;
   3758   1.1    bouyer 			bp->bp_autonext = prop.next_exec;
   3759   1.1    bouyer 			bp->bp_autonow = time;
   3760   1.1    bouyer 			break;
   3761   1.1    bouyer 		case MFI_PR_OPMODE_MANUAL:
   3762   1.1    bouyer 			bp->bp_mode = BIOC_SPMMANUAL;
   3763   1.1    bouyer 			break;
   3764   1.1    bouyer 		case MFI_PR_OPMODE_DISABLED:
   3765   1.1    bouyer 			bp->bp_mode = BIOC_SPMDISABLED;
   3766   1.1    bouyer 			break;
   3767   1.1    bouyer 		default:
   3768   1.1    bouyer 			printf("%s: unknown patrol mode %d\n",
   3769   1.1    bouyer 			    DEVNAME(sc), prop.op_mode);
   3770   1.1    bouyer 			break;
   3771   1.1    bouyer 		}
   3772   1.1    bouyer 
   3773   1.1    bouyer 		switch (status.state) {
   3774   1.1    bouyer 		case MFI_PR_STATE_STOPPED:
   3775   1.1    bouyer 			bp->bp_status = BIOC_SPSSTOPPED;
   3776   1.1    bouyer 			break;
   3777   1.1    bouyer 		case MFI_PR_STATE_READY:
   3778   1.1    bouyer 			bp->bp_status = BIOC_SPSREADY;
   3779   1.1    bouyer 			break;
   3780   1.1    bouyer 		case MFI_PR_STATE_ACTIVE:
   3781   1.1    bouyer 			bp->bp_status = BIOC_SPSACTIVE;
   3782   1.1    bouyer 			break;
   3783   1.1    bouyer 		case MFI_PR_STATE_ABORTED:
   3784   1.1    bouyer 			bp->bp_status = BIOC_SPSABORTED;
   3785   1.1    bouyer 			break;
   3786   1.1    bouyer 		default:
   3787   1.1    bouyer 			printf("%s: unknown patrol state %d\n",
   3788   1.1    bouyer 			    DEVNAME(sc), status.state);
   3789   1.1    bouyer 			break;
   3790   1.1    bouyer 		}
   3791   1.1    bouyer 
   3792   1.1    bouyer 		break;
   3793   1.1    bouyer 
   3794   1.1    bouyer 	default:
   3795  1.19   msaitoh 		DNPRINTF(MFII_D_IOCTL,
   3796  1.19   msaitoh 		    "%s: mfii_ioctl_patrol biocpatrol invalid opcode %x\n",
   3797  1.19   msaitoh 		    DEVNAME(sc), bp->bp_opcode);
   3798   1.1    bouyer 		return (EINVAL);
   3799   1.1    bouyer 	}
   3800   1.1    bouyer 
   3801   1.1    bouyer 	return (rv);
   3802   1.1    bouyer }
   3803   1.1    bouyer #endif
   3804   1.1    bouyer 
   3805   1.6      maxv static int
   3806   1.1    bouyer mfii_bio_hs(struct mfii_softc *sc, int volid, int type, void *bio_hs)
   3807   1.1    bouyer {
   3808   1.1    bouyer 	struct mfi_conf		*cfg;
   3809   1.1    bouyer 	struct mfi_hotspare	*hs;
   3810   1.1    bouyer 	struct mfi_pd_details	*pd;
   3811   1.1    bouyer 	struct bioc_disk	*sdhs;
   3812   1.1    bouyer 	struct bioc_vol		*vdhs;
   3813   1.1    bouyer 	struct scsipi_inquiry_data *inqbuf;
   3814   1.1    bouyer 	char			vend[8+16+4+1], *vendp;
   3815   1.1    bouyer 	int			i, rv = EINVAL;
   3816   1.1    bouyer 	uint32_t		size;
   3817   1.1    bouyer 	union mfi_mbox		mbox;
   3818   1.1    bouyer 
   3819   1.1    bouyer 	DNPRINTF(MFII_D_IOCTL, "%s: mfii_vol_hs %d\n", DEVNAME(sc), volid);
   3820   1.1    bouyer 
   3821   1.1    bouyer 	if (!bio_hs)
   3822   1.1    bouyer 		return (EINVAL);
   3823   1.1    bouyer 
   3824   1.1    bouyer 	pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
   3825   1.1    bouyer 
   3826   1.1    bouyer 	/* send single element command to retrieve size for full structure */
   3827   1.1    bouyer 	cfg = malloc(sizeof *cfg, M_DEVBUF, M_WAITOK);
   3828   1.1    bouyer 	if (mfii_mgmt(sc, MR_DCMD_CONF_GET, NULL, cfg, sizeof(*cfg),
   3829   1.1    bouyer 	    MFII_DATA_IN, false))
   3830   1.1    bouyer 		goto freeme;
   3831   1.1    bouyer 
   3832   1.1    bouyer 	size = cfg->mfc_size;
   3833   1.1    bouyer 	free(cfg, M_DEVBUF);
   3834   1.1    bouyer 
   3835   1.1    bouyer 	/* memory for read config */
   3836   1.1    bouyer 	cfg = malloc(size, M_DEVBUF, M_WAITOK|M_ZERO);
   3837   1.1    bouyer 	if (mfii_mgmt(sc, MR_DCMD_CONF_GET, NULL, cfg, size,
   3838   1.1    bouyer 	    MFII_DATA_IN, false))
   3839   1.1    bouyer 		goto freeme;
   3840   1.1    bouyer 
   3841   1.1    bouyer 	/* calculate offset to hs structure */
   3842   1.1    bouyer 	hs = (struct mfi_hotspare *)(
   3843   1.1    bouyer 	    ((uint8_t *)cfg) + offsetof(struct mfi_conf, mfc_array) +
   3844   1.1    bouyer 	    cfg->mfc_array_size * cfg->mfc_no_array +
   3845   1.1    bouyer 	    cfg->mfc_ld_size * cfg->mfc_no_ld);
   3846   1.1    bouyer 
   3847   1.1    bouyer 	if (volid < cfg->mfc_no_ld)
   3848   1.1    bouyer 		goto freeme; /* not a hotspare */
   3849   1.1    bouyer 
   3850   1.1    bouyer 	if (volid > (cfg->mfc_no_ld + cfg->mfc_no_hs))
   3851   1.1    bouyer 		goto freeme; /* not a hotspare */
   3852   1.1    bouyer 
   3853   1.1    bouyer 	/* offset into hotspare structure */
   3854   1.1    bouyer 	i = volid - cfg->mfc_no_ld;
   3855   1.1    bouyer 
   3856  1.19   msaitoh 	DNPRINTF(MFII_D_IOCTL,
   3857  1.19   msaitoh 	    "%s: mfii_vol_hs i %d volid %d no_ld %d no_hs %d "
   3858   1.1    bouyer 	    "hs %p cfg %p id %02x\n", DEVNAME(sc), i, volid, cfg->mfc_no_ld,
   3859   1.1    bouyer 	    cfg->mfc_no_hs, hs, cfg, hs[i].mhs_pd.mfp_id);
   3860   1.1    bouyer 
   3861   1.1    bouyer 	/* get pd fields */
   3862   1.1    bouyer 	memset(&mbox, 0, sizeof(mbox));
   3863   1.1    bouyer 	mbox.s[0] = hs[i].mhs_pd.mfp_id;
   3864   1.1    bouyer 	if (mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
   3865   1.1    bouyer 	    MFII_DATA_IN, false)) {
   3866   1.1    bouyer 		DNPRINTF(MFII_D_IOCTL, "%s: mfii_vol_hs illegal PD\n",
   3867   1.1    bouyer 		    DEVNAME(sc));
   3868   1.1    bouyer 		goto freeme;
   3869   1.1    bouyer 	}
   3870   1.1    bouyer 
   3871   1.1    bouyer 	switch (type) {
   3872   1.1    bouyer 	case MFI_MGMT_VD:
   3873   1.1    bouyer 		vdhs = bio_hs;
   3874   1.1    bouyer 		vdhs->bv_status = BIOC_SVONLINE;
   3875   1.1    bouyer 		vdhs->bv_size = pd->mpd_size / 2 * 1024; /* XXX why? */
   3876   1.1    bouyer 		vdhs->bv_level = -1; /* hotspare */
   3877   1.1    bouyer 		vdhs->bv_nodisk = 1;
   3878   1.1    bouyer 		break;
   3879   1.1    bouyer 
   3880   1.1    bouyer 	case MFI_MGMT_SD:
   3881   1.1    bouyer 		sdhs = bio_hs;
   3882   1.1    bouyer 		sdhs->bd_status = BIOC_SDHOTSPARE;
   3883   1.1    bouyer 		sdhs->bd_size = pd->mpd_size / 2 * 1024; /* XXX why? */
   3884   1.1    bouyer 		sdhs->bd_channel = pd->mpd_enc_idx;
   3885   1.1    bouyer 		sdhs->bd_target = pd->mpd_enc_slot;
   3886   1.1    bouyer 		inqbuf = (struct scsipi_inquiry_data *)&pd->mpd_inq_data;
   3887   1.1    bouyer 		vendp = inqbuf->vendor;
   3888   1.1    bouyer 		memcpy(vend, vendp, sizeof vend - 1);
   3889   1.1    bouyer 		vend[sizeof vend - 1] = '\0';
   3890   1.1    bouyer 		strlcpy(sdhs->bd_vendor, vend, sizeof(sdhs->bd_vendor));
   3891   1.1    bouyer 		break;
   3892   1.1    bouyer 
   3893   1.1    bouyer 	default:
   3894   1.1    bouyer 		goto freeme;
   3895   1.1    bouyer 	}
   3896   1.1    bouyer 
   3897   1.1    bouyer 	DNPRINTF(MFII_D_IOCTL, "%s: mfii_vol_hs 6\n", DEVNAME(sc));
   3898   1.1    bouyer 	rv = 0;
   3899   1.1    bouyer freeme:
   3900   1.1    bouyer 	free(pd, M_DEVBUF);
   3901   1.1    bouyer 	free(cfg, M_DEVBUF);
   3902   1.1    bouyer 
   3903   1.1    bouyer 	return (rv);
   3904   1.1    bouyer }
   3905   1.1    bouyer 
   3906   1.1    bouyer #endif /* NBIO > 0 */
   3907   1.1    bouyer 
   3908   1.6      maxv static void
   3909   1.1    bouyer mfii_bbu(struct mfii_softc *sc, envsys_data_t *edata)
   3910   1.1    bouyer {
   3911   1.1    bouyer 	struct mfi_bbu_status bbu;
   3912   1.1    bouyer 	u_int32_t status;
   3913   1.1    bouyer 	u_int32_t mask;
   3914   1.1    bouyer 	u_int32_t soh_bad;
   3915   1.1    bouyer 	int rv;
   3916   1.1    bouyer 
   3917   1.1    bouyer 	mutex_enter(&sc->sc_lock);
   3918   1.1    bouyer 	rv = mfii_mgmt(sc, MR_DCMD_BBU_GET_STATUS, NULL, &bbu,
   3919   1.1    bouyer 	    sizeof(bbu), MFII_DATA_IN, false);
   3920   1.1    bouyer 	mutex_exit(&sc->sc_lock);
   3921   1.1    bouyer 	if (rv != 0) {
   3922   1.1    bouyer 		edata->state = ENVSYS_SINVALID;
   3923   1.1    bouyer 		edata->value_cur = 0;
   3924   1.1    bouyer 		return;
   3925   1.1    bouyer 	}
   3926   1.1    bouyer 
   3927   1.1    bouyer 	switch (bbu.battery_type) {
   3928   1.1    bouyer 	case MFI_BBU_TYPE_IBBU:
   3929  1.14   msaitoh 	case MFI_BBU_TYPE_IBBU09:
   3930  1.20   msaitoh 	case MFI_BBU_TYPE_CVPM02:
   3931   1.1    bouyer 		mask = MFI_BBU_STATE_BAD_IBBU;
   3932   1.1    bouyer 		soh_bad = 0;
   3933   1.1    bouyer 		break;
   3934   1.1    bouyer 	case MFI_BBU_TYPE_BBU:
   3935   1.1    bouyer 		mask = MFI_BBU_STATE_BAD_BBU;
   3936   1.1    bouyer 		soh_bad = (bbu.detail.bbu.is_SOH_good == 0);
   3937   1.1    bouyer 		break;
   3938   1.1    bouyer 
   3939   1.1    bouyer 	case MFI_BBU_TYPE_NONE:
   3940   1.1    bouyer 	default:
   3941   1.1    bouyer 		edata->state = ENVSYS_SCRITICAL;
   3942   1.1    bouyer 		edata->value_cur = 0;
   3943   1.1    bouyer 		return;
   3944   1.1    bouyer 	}
   3945   1.1    bouyer 
   3946   1.1    bouyer 	status = le32toh(bbu.fw_status) & mask;
   3947  1.10   msaitoh 	switch (edata->sensor) {
   3948   1.1    bouyer 	case 0:
   3949   1.1    bouyer 		edata->value_cur = (status || soh_bad) ? 0 : 1;
   3950   1.1    bouyer 		edata->state =
   3951   1.1    bouyer 		    edata->value_cur ? ENVSYS_SVALID : ENVSYS_SCRITICAL;
   3952   1.1    bouyer 		return;
   3953   1.1    bouyer 	case 1:
   3954   1.1    bouyer 		edata->value_cur = le16toh(bbu.voltage) * 1000;
   3955   1.1    bouyer 		edata->state = ENVSYS_SVALID;
   3956   1.1    bouyer 		return;
   3957   1.1    bouyer 	case 2:
   3958   1.1    bouyer 		edata->value_cur = (int16_t)le16toh(bbu.current) * 1000;
   3959   1.1    bouyer 		edata->state = ENVSYS_SVALID;
   3960   1.1    bouyer 		return;
   3961   1.1    bouyer 	case 3:
   3962  1.19   msaitoh 		edata->value_cur =
   3963  1.19   msaitoh 		    le16toh(bbu.temperature) * 1000000 + 273150000;
   3964   1.1    bouyer 		edata->state = ENVSYS_SVALID;
   3965   1.1    bouyer 		return;
   3966   1.1    bouyer 	}
   3967   1.1    bouyer }
   3968   1.1    bouyer 
   3969   1.6      maxv static void
   3970   1.1    bouyer mfii_refresh_ld_sensor(struct mfii_softc *sc, envsys_data_t *edata)
   3971   1.1    bouyer {
   3972   1.1    bouyer 	struct bioc_vol bv;
   3973   1.1    bouyer 	int error;
   3974   1.1    bouyer 
   3975   1.1    bouyer 	memset(&bv, 0, sizeof(bv));
   3976   1.1    bouyer 	bv.bv_volid = edata->sensor - MFI_BBU_SENSORS;
   3977   1.1    bouyer 	mutex_enter(&sc->sc_lock);
   3978   1.1    bouyer 	error = mfii_ioctl_vol(sc, &bv);
   3979   1.1    bouyer 	mutex_exit(&sc->sc_lock);
   3980   1.1    bouyer 	if (error)
   3981   1.1    bouyer 		bv.bv_status = BIOC_SVINVALID;
   3982   1.1    bouyer 	bio_vol_to_envsys(edata, &bv);
   3983   1.1    bouyer }
   3984   1.1    bouyer 
   3985   1.6      maxv static void
   3986   1.1    bouyer mfii_init_ld_sensor(struct mfii_softc *sc, envsys_data_t *sensor, int i)
   3987   1.1    bouyer {
   3988   1.1    bouyer 	sensor->units = ENVSYS_DRIVE;
   3989   1.1    bouyer 	sensor->state = ENVSYS_SINVALID;
   3990   1.1    bouyer 	sensor->value_cur = ENVSYS_DRIVE_EMPTY;
   3991   1.1    bouyer 	/* Enable monitoring for drive state changes */
   3992   1.1    bouyer 	sensor->flags |= ENVSYS_FMONSTCHANGED;
   3993   1.1    bouyer 	snprintf(sensor->desc, sizeof(sensor->desc), "%s:%d", DEVNAME(sc), i);
   3994   1.1    bouyer }
   3995   1.1    bouyer 
   3996   1.1    bouyer static void
   3997   1.1    bouyer mfii_attach_sensor(struct mfii_softc *sc, envsys_data_t *s)
   3998   1.1    bouyer {
   3999   1.1    bouyer 	if (sysmon_envsys_sensor_attach(sc->sc_sme, s))
   4000   1.1    bouyer 		aprint_error_dev(sc->sc_dev,
   4001   1.1    bouyer 		    "failed to attach sensor %s\n", s->desc);
   4002   1.1    bouyer }
   4003   1.1    bouyer 
   4004   1.6      maxv static int
   4005   1.1    bouyer mfii_create_sensors(struct mfii_softc *sc)
   4006   1.1    bouyer {
   4007  1.31  christos 	int i, rv;
   4008  1.24   msaitoh 	const int nsensors = MFI_BBU_SENSORS + MFII_MAX_LD_EXT;
   4009   1.1    bouyer 
   4010   1.1    bouyer 	sc->sc_sme = sysmon_envsys_create();
   4011   1.1    bouyer 	sc->sc_sensors = malloc(sizeof(envsys_data_t) * nsensors,
   4012   1.5       chs 	    M_DEVBUF, M_WAITOK | M_ZERO);
   4013   1.1    bouyer 
   4014   1.1    bouyer 	/* BBU */
   4015   1.1    bouyer 	sc->sc_sensors[0].units = ENVSYS_INDICATOR;
   4016   1.1    bouyer 	sc->sc_sensors[0].state = ENVSYS_SINVALID;
   4017   1.1    bouyer 	sc->sc_sensors[0].value_cur = 0;
   4018   1.1    bouyer 	sc->sc_sensors[1].units = ENVSYS_SVOLTS_DC;
   4019   1.1    bouyer 	sc->sc_sensors[1].state = ENVSYS_SINVALID;
   4020   1.1    bouyer 	sc->sc_sensors[1].value_cur = 0;
   4021   1.1    bouyer 	sc->sc_sensors[2].units = ENVSYS_SAMPS;
   4022   1.1    bouyer 	sc->sc_sensors[2].state = ENVSYS_SINVALID;
   4023   1.1    bouyer 	sc->sc_sensors[2].value_cur = 0;
   4024   1.1    bouyer 	sc->sc_sensors[3].units = ENVSYS_STEMP;
   4025   1.1    bouyer 	sc->sc_sensors[3].state = ENVSYS_SINVALID;
   4026   1.1    bouyer 	sc->sc_sensors[3].value_cur = 0;
   4027  1.31  christos 	sc->sc_ld_sensors = sc->sc_sensors + MFI_BBU_SENSORS;
   4028   1.1    bouyer 
   4029   1.1    bouyer 	if (ISSET(le32toh(sc->sc_info.mci_hw_present), MFI_INFO_HW_BBU)) {
   4030   1.1    bouyer 		sc->sc_bbuok = true;
   4031   1.1    bouyer 		sc->sc_sensors[0].flags |= ENVSYS_FMONCRITICAL;
   4032   1.1    bouyer 		snprintf(sc->sc_sensors[0].desc, sizeof(sc->sc_sensors[0].desc),
   4033   1.1    bouyer 		    "%s BBU state", DEVNAME(sc));
   4034   1.1    bouyer 		snprintf(sc->sc_sensors[1].desc, sizeof(sc->sc_sensors[1].desc),
   4035   1.1    bouyer 		    "%s BBU voltage", DEVNAME(sc));
   4036   1.1    bouyer 		snprintf(sc->sc_sensors[2].desc, sizeof(sc->sc_sensors[2].desc),
   4037   1.1    bouyer 		    "%s BBU current", DEVNAME(sc));
   4038   1.1    bouyer 		snprintf(sc->sc_sensors[3].desc, sizeof(sc->sc_sensors[3].desc),
   4039   1.1    bouyer 		    "%s BBU temperature", DEVNAME(sc));
   4040   1.1    bouyer 		for (i = 0; i < MFI_BBU_SENSORS; i++) {
   4041   1.1    bouyer 			mfii_attach_sensor(sc, &sc->sc_sensors[i]);
   4042   1.1    bouyer 		}
   4043   1.1    bouyer 	}
   4044   1.1    bouyer 
   4045   1.1    bouyer 	for (i = 0; i < sc->sc_ld_list.mll_no_ld; i++) {
   4046  1.31  christos 		mfii_init_ld_sensor(sc, &sc->sc_ld_sensors[i], i);
   4047  1.31  christos 		mfii_attach_sensor(sc, &sc->sc_ld_sensors[i]);
   4048   1.1    bouyer 	}
   4049   1.1    bouyer 
   4050   1.1    bouyer 	sc->sc_sme->sme_name = DEVNAME(sc);
   4051   1.1    bouyer 	sc->sc_sme->sme_cookie = sc;
   4052   1.1    bouyer 	sc->sc_sme->sme_refresh = mfii_refresh_sensor;
   4053   1.1    bouyer 	rv = sysmon_envsys_register(sc->sc_sme);
   4054   1.1    bouyer 	if (rv) {
   4055   1.1    bouyer 		aprint_error_dev(sc->sc_dev,
   4056   1.1    bouyer 		    "unable to register with sysmon (rv = %d)\n", rv);
   4057  1.27   msaitoh 		sysmon_envsys_destroy(sc->sc_sme);
   4058  1.27   msaitoh 		sc->sc_sme = NULL;
   4059   1.1    bouyer 	}
   4060   1.1    bouyer 	return rv;
   4061   1.1    bouyer 
   4062   1.1    bouyer }
   4063   1.1    bouyer 
   4064   1.1    bouyer static int
   4065   1.1    bouyer mfii_destroy_sensors(struct mfii_softc *sc)
   4066   1.1    bouyer {
   4067   1.1    bouyer 	if (sc->sc_sme == NULL)
   4068   1.1    bouyer 		return 0;
   4069   1.1    bouyer 	sysmon_envsys_unregister(sc->sc_sme);
   4070   1.1    bouyer 	sc->sc_sme = NULL;
   4071   1.1    bouyer 	free(sc->sc_sensors, M_DEVBUF);
   4072  1.10   msaitoh 	return 0;
   4073  1.10   msaitoh }
   4074   1.1    bouyer 
   4075   1.6      maxv static void
   4076   1.1    bouyer mfii_refresh_sensor(struct sysmon_envsys *sme, envsys_data_t *edata)
   4077   1.1    bouyer {
   4078   1.1    bouyer 	struct mfii_softc	*sc = sme->sme_cookie;
   4079   1.1    bouyer 
   4080  1.24   msaitoh 	if (edata->sensor >= MFI_BBU_SENSORS + MFII_MAX_LD_EXT)
   4081   1.1    bouyer 		return;
   4082   1.1    bouyer 
   4083   1.1    bouyer 	if (edata->sensor < MFI_BBU_SENSORS) {
   4084   1.1    bouyer 		if (sc->sc_bbuok)
   4085   1.1    bouyer 			mfii_bbu(sc, edata);
   4086   1.1    bouyer 	} else {
   4087   1.1    bouyer 		mfii_refresh_ld_sensor(sc, edata);
   4088   1.1    bouyer 	}
   4089   1.1    bouyer }
   4090