Home | History | Annotate | Line # | Download | only in pci
mpii.c revision 1.15
      1  1.15    bouyer /* $NetBSD: mpii.c,v 1.15 2018/12/03 22:34:36 bouyer Exp $ */
      2  1.15    bouyer /*	$OpenBSD: mpii.c,v 1.115 2018/08/14 05:22:21 jmatthew Exp $	*/
      3   1.1    bouyer /*
      4  1.15    bouyer  * Copyright (c) 2010, 2012 Mike Belopuhov
      5   1.1    bouyer  * Copyright (c) 2009 James Giannoules
      6   1.1    bouyer  * Copyright (c) 2005 - 2010 David Gwynne <dlg (at) openbsd.org>
      7   1.1    bouyer  * Copyright (c) 2005 - 2010 Marco Peereboom <marco (at) openbsd.org>
      8   1.1    bouyer  *
      9   1.1    bouyer  * Permission to use, copy, modify, and distribute this software for any
     10   1.1    bouyer  * purpose with or without fee is hereby granted, provided that the above
     11   1.1    bouyer  * copyright notice and this permission notice appear in all copies.
     12   1.1    bouyer  *
     13   1.1    bouyer  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     14   1.1    bouyer  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     15   1.1    bouyer  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     16   1.1    bouyer  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     17   1.1    bouyer  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     18   1.1    bouyer  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     19   1.1    bouyer  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     20   1.1    bouyer  */
     21   1.1    bouyer 
     22   1.1    bouyer #include <sys/cdefs.h>
     23  1.15    bouyer __KERNEL_RCSID(0, "$NetBSD: mpii.c,v 1.15 2018/12/03 22:34:36 bouyer Exp $");
     24   1.1    bouyer 
     25   1.1    bouyer #include "bio.h"
     26   1.1    bouyer 
     27   1.1    bouyer #include <sys/param.h>
     28   1.1    bouyer #include <sys/systm.h>
     29   1.1    bouyer #include <sys/buf.h>
     30   1.1    bouyer #include <sys/device.h>
     31   1.1    bouyer #include <sys/ioctl.h>
     32   1.1    bouyer #include <sys/malloc.h>
     33   1.1    bouyer #include <sys/kernel.h>
     34   1.1    bouyer #include <sys/mutex.h>
     35   1.1    bouyer #include <sys/condvar.h>
     36   1.1    bouyer #include <sys/dkio.h>
     37   1.1    bouyer #include <sys/tree.h>
     38   1.1    bouyer 
     39   1.1    bouyer #include <dev/pci/pcireg.h>
     40   1.1    bouyer #include <dev/pci/pcivar.h>
     41   1.1    bouyer #include <dev/pci/pcidevs.h>
     42   1.1    bouyer 
     43   1.1    bouyer #include <dev/scsipi/scsipi_all.h>
     44   1.1    bouyer #include <dev/scsipi/scsi_all.h>
     45   1.1    bouyer #include <dev/scsipi/scsiconf.h>
     46   1.1    bouyer 
     47  1.13    bouyer #if NBIO > 0
     48   1.1    bouyer #include <dev/biovar.h>
     49  1.15    bouyer #include <dev/sysmon/sysmonvar.h>
     50   1.1    bouyer #include <sys/envsys.h>
     51  1.13    bouyer #endif
     52   1.1    bouyer 
     53  1.15    bouyer #include <dev/pci/mpiireg.h>
     54  1.15    bouyer 
     55  1.15    bouyer // #define MPII_DEBUG
     56   1.1    bouyer #ifdef MPII_DEBUG
     57   1.1    bouyer #define DPRINTF(x...)		do { if (mpii_debug) printf(x); } while(0)
     58   1.1    bouyer #define DNPRINTF(n,x...)	do { if (mpii_debug & (n)) printf(x); } while(0)
     59   1.1    bouyer #define	MPII_D_CMD		(0x0001)
     60   1.1    bouyer #define	MPII_D_INTR		(0x0002)
     61   1.1    bouyer #define	MPII_D_MISC		(0x0004)
     62   1.1    bouyer #define	MPII_D_DMA		(0x0008)
     63   1.1    bouyer #define	MPII_D_IOCTL		(0x0010)
     64   1.1    bouyer #define	MPII_D_RW		(0x0020)
     65   1.1    bouyer #define	MPII_D_MEM		(0x0040)
     66   1.1    bouyer #define	MPII_D_CCB		(0x0080)
     67   1.1    bouyer #define	MPII_D_PPR		(0x0100)
     68   1.1    bouyer #define	MPII_D_RAID		(0x0200)
     69   1.1    bouyer #define	MPII_D_EVT		(0x0400)
     70   1.1    bouyer #define MPII_D_CFG		(0x0800)
     71   1.1    bouyer #define MPII_D_MAP		(0x1000)
     72  1.15    bouyer 
     73   1.1    bouyer u_int32_t  mpii_debug = 0
     74  1.15    bouyer //		| MPII_D_CMD
     75  1.15    bouyer //		| MPII_D_INTR
     76  1.15    bouyer //		| MPII_D_MISC
     77  1.15    bouyer //		| MPII_D_DMA
     78  1.15    bouyer //		| MPII_D_IOCTL
     79  1.15    bouyer //		| MPII_D_RW
     80  1.15    bouyer //		| MPII_D_MEM
     81  1.15    bouyer //		| MPII_D_CCB
     82  1.15    bouyer //		| MPII_D_PPR
     83  1.15    bouyer //		| MPII_D_RAID
     84  1.15    bouyer //		| MPII_D_EVT
     85  1.15    bouyer //		| MPII_D_CFG
     86  1.15    bouyer //		| MPII_D_MAP
     87   1.1    bouyer 	;
     88   1.1    bouyer #else
     89   1.1    bouyer #define DPRINTF(x...)
     90   1.1    bouyer #define DNPRINTF(n,x...)
     91   1.1    bouyer #endif
     92   1.1    bouyer 
     93  1.15    bouyer #define MPII_REQUEST_SIZE		(512)
     94  1.15    bouyer #define MPII_REQUEST_CREDIT		(128)
     95   1.1    bouyer 
     96   1.1    bouyer struct mpii_dmamem {
     97   1.1    bouyer 	bus_dmamap_t		mdm_map;
     98   1.1    bouyer 	bus_dma_segment_t	mdm_seg;
     99   1.1    bouyer 	size_t			mdm_size;
    100   1.1    bouyer 	void 			*mdm_kva;
    101   1.1    bouyer };
    102  1.15    bouyer #define MPII_DMA_MAP(_mdm) ((_mdm)->mdm_map)
    103  1.15    bouyer #define MPII_DMA_DVA(_mdm) ((uint64_t)(_mdm)->mdm_map->dm_segs[0].ds_addr)
    104  1.15    bouyer #define MPII_DMA_KVA(_mdm) ((_mdm)->mdm_kva)
    105   1.1    bouyer 
    106   1.1    bouyer struct mpii_softc;
    107   1.1    bouyer 
    108   1.1    bouyer struct mpii_rcb {
    109  1.15    bouyer 	SIMPLEQ_ENTRY(mpii_rcb)	rcb_link;
    110   1.1    bouyer 	void			*rcb_reply;
    111   1.1    bouyer 	u_int32_t		rcb_reply_dva;
    112   1.1    bouyer };
    113   1.1    bouyer 
    114   1.1    bouyer SIMPLEQ_HEAD(mpii_rcb_list, mpii_rcb);
    115   1.1    bouyer 
    116   1.1    bouyer struct mpii_device {
    117   1.1    bouyer 	int			flags;
    118   1.1    bouyer #define MPII_DF_ATTACH		(0x0001)
    119   1.1    bouyer #define MPII_DF_DETACH		(0x0002)
    120   1.1    bouyer #define MPII_DF_HIDDEN		(0x0004)
    121   1.1    bouyer #define MPII_DF_UNUSED		(0x0008)
    122   1.1    bouyer #define MPII_DF_VOLUME		(0x0010)
    123   1.1    bouyer #define MPII_DF_VOLUME_DISK	(0x0020)
    124   1.1    bouyer #define MPII_DF_HOT_SPARE	(0x0040)
    125   1.1    bouyer 	short			slot;
    126   1.1    bouyer 	short			percent;
    127   1.1    bouyer 	u_int16_t		dev_handle;
    128   1.1    bouyer 	u_int16_t		enclosure;
    129   1.1    bouyer 	u_int16_t		expander;
    130   1.1    bouyer 	u_int8_t		phy_num;
    131   1.1    bouyer 	u_int8_t		physical_port;
    132   1.1    bouyer };
    133   1.1    bouyer 
    134   1.1    bouyer struct mpii_ccb {
    135   1.1    bouyer 	struct mpii_softc	*ccb_sc;
    136   1.1    bouyer 
    137   1.1    bouyer 	void *			ccb_cookie;
    138  1.15    bouyer 	kmutex_t		ccb_mtx;
    139  1.15    bouyer 	kcondvar_t		ccb_cv;
    140  1.15    bouyer 
    141   1.1    bouyer 	bus_dmamap_t		ccb_dmamap;
    142   1.1    bouyer 
    143   1.1    bouyer 	bus_addr_t		ccb_offset;
    144   1.1    bouyer 	void			*ccb_cmd;
    145   1.1    bouyer 	bus_addr_t		ccb_cmd_dva;
    146   1.1    bouyer 	u_int16_t		ccb_dev_handle;
    147  1.15    bouyer 	u_int16_t		ccb_smid;
    148   1.1    bouyer 
    149   1.1    bouyer 	volatile enum {
    150   1.1    bouyer 		MPII_CCB_FREE,
    151   1.1    bouyer 		MPII_CCB_READY,
    152   1.1    bouyer 		MPII_CCB_QUEUED,
    153   1.1    bouyer 		MPII_CCB_TIMEOUT
    154   1.1    bouyer 	}			ccb_state;
    155   1.1    bouyer 
    156   1.1    bouyer 	void			(*ccb_done)(struct mpii_ccb *);
    157   1.1    bouyer 	struct mpii_rcb		*ccb_rcb;
    158   1.1    bouyer 
    159  1.15    bouyer 	SIMPLEQ_ENTRY(mpii_ccb)	ccb_link;
    160   1.1    bouyer };
    161   1.1    bouyer 
    162   1.1    bouyer SIMPLEQ_HEAD(mpii_ccb_list, mpii_ccb);
    163   1.1    bouyer 
    164   1.1    bouyer struct mpii_softc {
    165   1.1    bouyer 	device_t		sc_dev;
    166   1.1    bouyer 
    167   1.1    bouyer 	pci_chipset_tag_t	sc_pc;
    168   1.1    bouyer 	pcitag_t		sc_tag;
    169   1.1    bouyer 
    170   1.1    bouyer 	void			*sc_ih;
    171  1.15    bouyer 	pci_intr_handle_t	*sc_pihp;
    172   1.1    bouyer 
    173   1.1    bouyer 	struct scsipi_adapter	sc_adapt;
    174   1.1    bouyer 	struct scsipi_channel	sc_chan;
    175   1.1    bouyer 	device_t		sc_child; /* our scsibus */
    176   1.1    bouyer 
    177  1.15    bouyer 	int			sc_flags;
    178  1.15    bouyer #define MPII_F_RAID		(1<<1)
    179  1.15    bouyer #define MPII_F_SAS3		(1<<2)
    180  1.15    bouyer 
    181   1.1    bouyer 	struct mpii_device	**sc_devs;
    182  1.15    bouyer 	kmutex_t		sc_devs_mtx;
    183   1.1    bouyer 
    184   1.1    bouyer 	bus_space_tag_t		sc_iot;
    185   1.1    bouyer 	bus_space_handle_t	sc_ioh;
    186   1.1    bouyer 	bus_size_t		sc_ios;
    187   1.1    bouyer 	bus_dma_tag_t		sc_dmat;
    188   1.1    bouyer 
    189   1.1    bouyer 	kmutex_t		sc_req_mtx;
    190   1.1    bouyer 	kmutex_t		sc_rep_mtx;
    191   1.1    bouyer 
    192  1.15    bouyer 	ushort			sc_reply_size;
    193  1.15    bouyer 	ushort			sc_request_size;
    194  1.15    bouyer 
    195  1.15    bouyer 	ushort			sc_max_cmds;
    196  1.15    bouyer 	ushort			sc_num_reply_frames;
    197  1.15    bouyer 	u_int			sc_reply_free_qdepth;
    198  1.15    bouyer 	u_int			sc_reply_post_qdepth;
    199  1.15    bouyer 
    200  1.15    bouyer 	ushort			sc_chain_sge;
    201  1.15    bouyer 	ushort			sc_max_sgl;
    202   1.1    bouyer 
    203   1.1    bouyer 	u_int8_t		sc_ioc_event_replay;
    204  1.15    bouyer 
    205  1.15    bouyer 	u_int8_t		sc_porttype;
    206   1.1    bouyer 	u_int8_t		sc_max_volumes;
    207   1.1    bouyer 	u_int16_t		sc_max_devices;
    208   1.1    bouyer 	u_int16_t		sc_vd_count;
    209   1.1    bouyer 	u_int16_t		sc_vd_id_low;
    210   1.1    bouyer 	u_int16_t		sc_pd_id_start;
    211   1.1    bouyer 	int			sc_ioc_number;
    212   1.1    bouyer 	u_int8_t		sc_vf_id;
    213   1.1    bouyer 
    214   1.1    bouyer 	struct mpii_ccb		*sc_ccbs;
    215   1.1    bouyer 	struct mpii_ccb_list	sc_ccb_free;
    216   1.1    bouyer 	kmutex_t		sc_ccb_free_mtx;
    217   1.1    bouyer 	kcondvar_t		sc_ccb_free_cv;
    218   1.1    bouyer 
    219  1.15    bouyer 	struct mpii_ccb_list	sc_ccb_tmos;
    220  1.15    bouyer 	kmutex_t		sc_ssb_tmomtx;
    221   1.1    bouyer 	struct workqueue	*sc_ssb_tmowk;
    222  1.15    bouyer 	struct work		sc_ssb_tmowork;
    223   1.1    bouyer 
    224   1.1    bouyer 	struct mpii_dmamem	*sc_requests;
    225   1.1    bouyer 
    226   1.1    bouyer 	struct mpii_dmamem	*sc_replies;
    227   1.1    bouyer 	struct mpii_rcb		*sc_rcbs;
    228   1.1    bouyer 
    229   1.1    bouyer 	struct mpii_dmamem	*sc_reply_postq;
    230   1.1    bouyer 	struct mpii_reply_descr	*sc_reply_postq_kva;
    231  1.15    bouyer 	u_int			sc_reply_post_host_index;
    232   1.1    bouyer 
    233   1.1    bouyer 	struct mpii_dmamem	*sc_reply_freeq;
    234  1.15    bouyer 	u_int			sc_reply_free_host_index;
    235  1.15    bouyer 	kmutex_t		sc_reply_free_mtx;
    236   1.1    bouyer 
    237  1.15    bouyer 	struct mpii_rcb_list	sc_evt_sas_queue;
    238  1.15    bouyer 	kmutex_t		sc_evt_sas_mtx;
    239  1.15    bouyer 	struct workqueue	*sc_evt_sas_wq;
    240  1.15    bouyer 	struct work		sc_evt_sas_work;
    241  1.15    bouyer 
    242  1.15    bouyer 	struct mpii_rcb_list	sc_evt_ack_queue;
    243  1.15    bouyer 	kmutex_t		sc_evt_ack_mtx;
    244  1.15    bouyer 	struct workqueue	*sc_evt_ack_wq;
    245  1.15    bouyer 	struct work		sc_evt_ack_work;
    246   1.1    bouyer 
    247   1.1    bouyer 	struct sysmon_envsys	*sc_sme;
    248   1.1    bouyer 	envsys_data_t		*sc_sensors;
    249   1.1    bouyer };
    250   1.1    bouyer 
    251  1.15    bouyer int	mpii_match(device_t, cfdata_t, void *);
    252  1.15    bouyer void	mpii_attach(device_t, device_t, void *);
    253  1.15    bouyer int	mpii_detach(device_t, int);
    254  1.15    bouyer void	mpii_childdetached(device_t, device_t);
    255  1.15    bouyer int	mpii_rescan(device_t, const char *, const int *);
    256   1.1    bouyer 
    257  1.15    bouyer int	mpii_intr(void *);
    258   1.1    bouyer 
    259   1.1    bouyer CFATTACH_DECL3_NEW(mpii, sizeof(struct mpii_softc),
    260   1.1    bouyer     mpii_match, mpii_attach, mpii_detach, NULL, mpii_rescan,
    261   1.1    bouyer     mpii_childdetached, DVF_DETACH_SHUTDOWN);
    262   1.1    bouyer 
    263  1.15    bouyer void		mpii_scsipi_request(struct scsipi_channel *,
    264  1.15    bouyer 			scsipi_adapter_req_t, void *);
    265  1.15    bouyer void		mpii_scsi_cmd_done(struct mpii_ccb *);
    266  1.15    bouyer 
    267  1.15    bouyer struct mpii_dmamem *
    268  1.15    bouyer 		mpii_dmamem_alloc(struct mpii_softc *, size_t);
    269  1.15    bouyer void		mpii_dmamem_free(struct mpii_softc *,
    270  1.15    bouyer 		    struct mpii_dmamem *);
    271  1.15    bouyer int		mpii_alloc_ccbs(struct mpii_softc *);
    272  1.15    bouyer struct mpii_ccb *mpii_get_ccb(struct mpii_softc *);
    273  1.15    bouyer void		mpii_put_ccb(struct mpii_softc *, struct mpii_ccb *);
    274  1.15    bouyer int		mpii_alloc_replies(struct mpii_softc *);
    275  1.15    bouyer int		mpii_alloc_queues(struct mpii_softc *);
    276  1.15    bouyer void		mpii_push_reply(struct mpii_softc *, struct mpii_rcb *);
    277  1.15    bouyer void		mpii_push_replies(struct mpii_softc *);
    278  1.15    bouyer 
    279  1.15    bouyer void		mpii_scsi_cmd_tmo(void *);
    280  1.15    bouyer void		mpii_scsi_cmd_tmo_handler(struct work *, void *);
    281  1.15    bouyer void		mpii_scsi_cmd_tmo_done(struct mpii_ccb *);
    282  1.15    bouyer 
    283  1.15    bouyer int		mpii_insert_dev(struct mpii_softc *, struct mpii_device *);
    284  1.15    bouyer int		mpii_remove_dev(struct mpii_softc *, struct mpii_device *);
    285  1.15    bouyer struct mpii_device *
    286  1.15    bouyer 		mpii_find_dev(struct mpii_softc *, u_int16_t);
    287  1.15    bouyer 
    288  1.15    bouyer void		mpii_start(struct mpii_softc *, struct mpii_ccb *);
    289  1.15    bouyer int		mpii_poll(struct mpii_softc *, struct mpii_ccb *);
    290  1.15    bouyer void		mpii_poll_done(struct mpii_ccb *);
    291  1.15    bouyer struct mpii_rcb *
    292  1.15    bouyer 		mpii_reply(struct mpii_softc *, struct mpii_reply_descr *);
    293  1.15    bouyer 
    294  1.15    bouyer void		mpii_wait(struct mpii_softc *, struct mpii_ccb *);
    295  1.15    bouyer void		mpii_wait_done(struct mpii_ccb *);
    296  1.15    bouyer 
    297  1.15    bouyer void		mpii_init_queues(struct mpii_softc *);
    298  1.15    bouyer 
    299  1.15    bouyer int		mpii_load_xs(struct mpii_ccb *);
    300  1.15    bouyer int		mpii_load_xs_sas3(struct mpii_ccb *);
    301  1.15    bouyer 
    302  1.15    bouyer u_int32_t	mpii_read(struct mpii_softc *, bus_size_t);
    303  1.15    bouyer void		mpii_write(struct mpii_softc *, bus_size_t, u_int32_t);
    304  1.15    bouyer int		mpii_wait_eq(struct mpii_softc *, bus_size_t, u_int32_t,
    305   1.1    bouyer 		    u_int32_t);
    306  1.15    bouyer int		mpii_wait_ne(struct mpii_softc *, bus_size_t, u_int32_t,
    307   1.1    bouyer 		    u_int32_t);
    308   1.1    bouyer 
    309  1.15    bouyer int		mpii_init(struct mpii_softc *);
    310  1.15    bouyer int		mpii_reset_soft(struct mpii_softc *);
    311  1.15    bouyer int		mpii_reset_hard(struct mpii_softc *);
    312   1.1    bouyer 
    313  1.15    bouyer int		mpii_handshake_send(struct mpii_softc *, void *, size_t);
    314  1.15    bouyer int		mpii_handshake_recv_dword(struct mpii_softc *,
    315   1.1    bouyer 		    u_int32_t *);
    316  1.15    bouyer int		mpii_handshake_recv(struct mpii_softc *, void *, size_t);
    317   1.1    bouyer 
    318  1.15    bouyer void		mpii_empty_done(struct mpii_ccb *);
    319   1.1    bouyer 
    320  1.15    bouyer int		mpii_iocinit(struct mpii_softc *);
    321  1.15    bouyer int		mpii_iocfacts(struct mpii_softc *);
    322  1.15    bouyer int		mpii_portfacts(struct mpii_softc *);
    323  1.15    bouyer int		mpii_portenable(struct mpii_softc *);
    324  1.15    bouyer int		mpii_cfg_coalescing(struct mpii_softc *);
    325  1.15    bouyer int		mpii_board_info(struct mpii_softc *);
    326  1.15    bouyer int		mpii_target_map(struct mpii_softc *);
    327  1.15    bouyer 
    328  1.15    bouyer int		mpii_eventnotify(struct mpii_softc *);
    329  1.15    bouyer void		mpii_eventnotify_done(struct mpii_ccb *);
    330  1.15    bouyer void		mpii_eventack(struct work *, void *);
    331  1.15    bouyer void		mpii_eventack_done(struct mpii_ccb *);
    332  1.15    bouyer void		mpii_event_process(struct mpii_softc *, struct mpii_rcb *);
    333  1.15    bouyer void		mpii_event_done(struct mpii_softc *, struct mpii_rcb *);
    334  1.15    bouyer void		mpii_event_sas(struct mpii_softc *, struct mpii_rcb *);
    335  1.15    bouyer void		mpii_event_sas_work(struct work *, void *);
    336  1.15    bouyer void		mpii_event_raid(struct mpii_softc *,
    337   1.1    bouyer 		    struct mpii_msg_event_reply *);
    338  1.15    bouyer void		mpii_event_discovery(struct mpii_softc *,
    339   1.1    bouyer 		    struct mpii_msg_event_reply *);
    340   1.1    bouyer 
    341  1.15    bouyer void		mpii_sas_remove_device(struct mpii_softc *, u_int16_t);
    342   1.1    bouyer 
    343  1.15    bouyer int		mpii_req_cfg_header(struct mpii_softc *, u_int8_t,
    344   1.1    bouyer 		    u_int8_t, u_int32_t, int, void *);
    345  1.15    bouyer int		mpii_req_cfg_page(struct mpii_softc *, u_int32_t, int,
    346   1.1    bouyer 		    void *, int, void *, size_t);
    347   1.1    bouyer 
    348   1.1    bouyer #if 0
    349  1.15    bouyer int		mpii_ioctl_cache(struct scsi_link *, u_long, struct dk_cache *);
    350   1.1    bouyer #endif
    351   1.1    bouyer 
    352   1.1    bouyer #if NBIO > 0
    353  1.15    bouyer int		mpii_ioctl(device_t, u_long, void *);
    354  1.15    bouyer int		mpii_ioctl_inq(struct mpii_softc *, struct bioc_inq *);
    355  1.15    bouyer int		mpii_ioctl_vol(struct mpii_softc *, struct bioc_vol *);
    356  1.15    bouyer int		mpii_ioctl_disk(struct mpii_softc *, struct bioc_disk *);
    357  1.15    bouyer int		mpii_bio_hs(struct mpii_softc *, struct bioc_disk *, int,
    358   1.1    bouyer 		    int, int *);
    359  1.15    bouyer int		mpii_bio_disk(struct mpii_softc *, struct bioc_disk *,
    360   1.1    bouyer 		    u_int8_t);
    361  1.15    bouyer struct mpii_device *
    362  1.15    bouyer 		mpii_find_vol(struct mpii_softc *, int);
    363  1.15    bouyer #ifndef SMALL_KERNEL
    364  1.15    bouyer  int		mpii_bio_volstate(struct mpii_softc *, struct bioc_vol *);
    365  1.15    bouyer int		mpii_create_sensors(struct mpii_softc *);
    366  1.15    bouyer void		mpii_refresh_sensors(struct sysmon_envsys *, envsys_data_t *);
    367  1.15    bouyer int		mpii_destroy_sensors(struct mpii_softc *);
    368  1.15    bouyer #endif /* SMALL_KERNEL */
    369   1.1    bouyer #endif /* NBIO > 0 */
    370   1.1    bouyer 
    371  1.15    bouyer #define DEVNAME(s)		(device_xname((s)->sc_dev))
    372   1.1    bouyer 
    373   1.1    bouyer #define dwordsof(s)		(sizeof(s) / sizeof(u_int32_t))
    374   1.1    bouyer 
    375   1.1    bouyer #define mpii_read_db(s)		mpii_read((s), MPII_DOORBELL)
    376   1.1    bouyer #define mpii_write_db(s, v)	mpii_write((s), MPII_DOORBELL, (v))
    377   1.1    bouyer #define mpii_read_intr(s)	mpii_read((s), MPII_INTR_STATUS)
    378   1.1    bouyer #define mpii_write_intr(s, v)	mpii_write((s), MPII_INTR_STATUS, (v))
    379   1.1    bouyer #define mpii_reply_waiting(s)	((mpii_read_intr((s)) & MPII_INTR_STATUS_REPLY)\
    380   1.1    bouyer 				    == MPII_INTR_STATUS_REPLY)
    381   1.1    bouyer 
    382  1.15    bouyer #define mpii_write_reply_free(s, v) \
    383  1.15    bouyer     bus_space_write_4((s)->sc_iot, (s)->sc_ioh, \
    384  1.15    bouyer     MPII_REPLY_FREE_HOST_INDEX, (v))
    385  1.15    bouyer #define mpii_write_reply_post(s, v) \
    386  1.15    bouyer     bus_space_write_4((s)->sc_iot, (s)->sc_ioh, \
    387  1.15    bouyer     MPII_REPLY_POST_HOST_INDEX, (v))
    388   1.1    bouyer 
    389   1.1    bouyer #define mpii_wait_db_int(s)	mpii_wait_ne((s), MPII_INTR_STATUS, \
    390   1.1    bouyer 				    MPII_INTR_STATUS_IOC2SYSDB, 0)
    391   1.1    bouyer #define mpii_wait_db_ack(s)	mpii_wait_eq((s), MPII_INTR_STATUS, \
    392   1.1    bouyer 				    MPII_INTR_STATUS_SYS2IOCDB, 0)
    393   1.1    bouyer 
    394  1.15    bouyer static inline void
    395  1.15    bouyer mpii_dvatosge(struct mpii_sge *sge, u_int64_t dva)
    396  1.15    bouyer {
    397  1.15    bouyer 	sge->sg_addr_lo = htole32(dva);
    398  1.15    bouyer 	sge->sg_addr_hi = htole32(dva >> 32);
    399  1.15    bouyer }
    400  1.15    bouyer 
    401   1.1    bouyer #define MPII_PG_EXTENDED	(1<<0)
    402   1.1    bouyer #define MPII_PG_POLL		(1<<1)
    403   1.1    bouyer #define MPII_PG_FMT		"\020" "\002POLL" "\001EXTENDED"
    404   1.1    bouyer 
    405   1.1    bouyer static const struct mpii_pci_product {
    406   1.1    bouyer 	pci_vendor_id_t         mpii_vendor;
    407   1.1    bouyer 	pci_product_id_t        mpii_product;
    408   1.1    bouyer } mpii_devices[] = {
    409   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2004 },
    410   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2008 },
    411   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2108_3 },
    412   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2108_4 },
    413   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2108_5 },
    414   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2116_1 },
    415   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2116_2 },
    416   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2208_1 },
    417   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2208_2 },
    418   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2208_3 },
    419   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2208_4 },
    420   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2208_5 },
    421   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2208_6 },
    422   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2308_1 },
    423   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2308_2 },
    424   1.1    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2308_3 },
    425  1.15    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS3004 },
    426  1.15    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS3008 },
    427  1.15    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS3108_1 },
    428  1.15    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS3108_2 },
    429  1.15    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS3108_3 },
    430  1.15    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS3108_4 },
    431  1.15    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS3408 },
    432  1.15    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS3416 },
    433  1.15    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS3508 },
    434  1.15    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS3508_1 },
    435  1.15    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS3516 },
    436  1.15    bouyer 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS3516_1 }
    437   1.1    bouyer };
    438   1.1    bouyer 
    439  1.15    bouyer int
    440   1.1    bouyer mpii_match(device_t parent, cfdata_t match, void *aux)
    441   1.1    bouyer {
    442   1.1    bouyer 	struct pci_attach_args *pa = aux;
    443   1.1    bouyer 	const struct mpii_pci_product *mpii;
    444   1.1    bouyer 
    445  1.15    bouyer 	for (mpii = mpii_devices; mpii->mpii_vendor != 0; mpii++) {
    446  1.15    bouyer 		if (PCI_VENDOR(pa->pa_id) == mpii->mpii_vendor &&
    447  1.15    bouyer 		    PCI_PRODUCT(pa->pa_id) == mpii->mpii_product)
    448  1.15    bouyer 			return (1);
    449   1.1    bouyer 	}
    450   1.1    bouyer 	return (0);
    451   1.1    bouyer }
    452   1.1    bouyer 
    453  1.15    bouyer void
    454   1.1    bouyer mpii_attach(device_t parent, device_t self, void *aux)
    455   1.1    bouyer {
    456   1.1    bouyer 	struct mpii_softc		*sc = device_private(self);
    457   1.1    bouyer 	struct pci_attach_args		*pa = aux;
    458   1.1    bouyer 	pcireg_t			memtype;
    459   1.1    bouyer 	int				r;
    460   1.1    bouyer 	struct mpii_ccb			*ccb;
    461   1.1    bouyer 	struct scsipi_adapter *adapt = &sc->sc_adapt;
    462   1.1    bouyer 	struct scsipi_channel *chan = &sc->sc_chan;
    463   1.5  christos 	char intrbuf[PCI_INTRSTR_LEN];
    464  1.15    bouyer 	const char *intrstr;
    465   1.1    bouyer 
    466   1.1    bouyer 	pci_aprint_devinfo(pa, NULL);
    467   1.1    bouyer 
    468   1.1    bouyer 	sc->sc_pc = pa->pa_pc;
    469   1.1    bouyer 	sc->sc_tag = pa->pa_tag;
    470   1.1    bouyer 	sc->sc_dmat = pa->pa_dmat;
    471   1.1    bouyer 	sc->sc_dev = self;
    472  1.15    bouyer 
    473   1.1    bouyer 	mutex_init(&sc->sc_req_mtx, MUTEX_DEFAULT, IPL_BIO);
    474   1.1    bouyer 	mutex_init(&sc->sc_rep_mtx, MUTEX_DEFAULT, IPL_BIO);
    475   1.1    bouyer 
    476   1.1    bouyer 	/* find the appropriate memory base */
    477   1.1    bouyer 	for (r = PCI_MAPREG_START; r < PCI_MAPREG_END; r += sizeof(memtype)) {
    478   1.1    bouyer 		memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, r);
    479   1.1    bouyer 		if ((memtype & PCI_MAPREG_TYPE_MASK) == PCI_MAPREG_TYPE_MEM)
    480   1.1    bouyer 			break;
    481   1.1    bouyer 	}
    482   1.1    bouyer 	if (r >= PCI_MAPREG_END) {
    483   1.1    bouyer 		aprint_error_dev(self,
    484   1.1    bouyer 		    "unable to locate system interface registers\n");
    485   1.1    bouyer 		return;
    486   1.1    bouyer 	}
    487   1.1    bouyer 
    488   1.1    bouyer 	if (pci_mapreg_map(pa, r, memtype, 0, &sc->sc_iot, &sc->sc_ioh,
    489   1.1    bouyer 	    NULL, &sc->sc_ios) != 0) {
    490   1.1    bouyer 		aprint_error_dev(self,
    491   1.1    bouyer 		    "unable to map system interface registers\n");
    492   1.1    bouyer 		return;
    493   1.1    bouyer 	}
    494   1.1    bouyer 
    495   1.1    bouyer 	/* disable the expansion rom */
    496  1.15    bouyer 	pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_MAPREG_ROM,
    497  1.15    bouyer 	    pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_MAPREG_ROM) &
    498  1.15    bouyer 	    ~PCI_MAPREG_ROM_ENABLE);
    499   1.1    bouyer 
    500   1.1    bouyer 	/* disable interrupts */
    501   1.1    bouyer 	mpii_write(sc, MPII_INTR_MASK,
    502   1.1    bouyer 	    MPII_INTR_MASK_RESET | MPII_INTR_MASK_REPLY |
    503   1.1    bouyer 	    MPII_INTR_MASK_DOORBELL);
    504   1.1    bouyer 
    505   1.1    bouyer 	/* hook up the interrupt */
    506  1.15    bouyer 	if (pci_intr_alloc(pa, &sc->sc_pihp, NULL, 0)) {
    507   1.1    bouyer 		aprint_error_dev(self, "unable to map interrupt\n");
    508   1.1    bouyer 		goto unmap;
    509   1.1    bouyer 	}
    510  1.15    bouyer 	intrstr = pci_intr_string(pa->pa_pc, sc->sc_pihp[0],
    511  1.15    bouyer 	    intrbuf, sizeof(intrbuf));
    512  1.15    bouyer 	pci_intr_setattr(pa->pa_pc, &sc->sc_pihp[0], PCI_INTR_MPSAFE, true);
    513  1.15    bouyer 	sc->sc_ih = pci_intr_establish_xname(pa->pa_pc, sc->sc_pihp[0], IPL_BIO,
    514  1.15    bouyer 	    mpii_intr, sc, device_xname(self));
    515  1.15    bouyer 	if (sc->sc_ih == NULL) {
    516  1.15    bouyer 		aprint_error_dev(self, "couldn't establish interrupt");
    517  1.15    bouyer 		if (intrstr != NULL)
    518  1.15    bouyer 			aprint_error(" at %s", intrstr);
    519  1.15    bouyer 		aprint_error("\n");
    520  1.15    bouyer 		return;
    521  1.15    bouyer 	}
    522  1.15    bouyer 	aprint_normal_dev(self, "interrupting at %s\n", intrstr);
    523  1.15    bouyer 	aprint_naive("\n");
    524   1.1    bouyer 
    525  1.15    bouyer 	if (mpii_iocfacts(sc) != 0) {
    526  1.15    bouyer 		aprint_error_dev(self,  "unable to get iocfacts\n");
    527   1.1    bouyer 		goto unmap;
    528   1.1    bouyer 	}
    529   1.1    bouyer 
    530  1.15    bouyer 	if (mpii_init(sc) != 0) {
    531  1.15    bouyer 		aprint_error_dev(self, "unable to initialize ioc\n");
    532   1.1    bouyer 		goto unmap;
    533   1.1    bouyer 	}
    534   1.1    bouyer 
    535   1.1    bouyer 	if (mpii_alloc_ccbs(sc) != 0) {
    536   1.1    bouyer 		/* error already printed */
    537   1.1    bouyer 		goto unmap;
    538   1.1    bouyer 	}
    539   1.1    bouyer 
    540   1.1    bouyer 	if (mpii_alloc_replies(sc) != 0) {
    541   1.1    bouyer 		aprint_error_dev(self, "unable to allocated reply space\n");
    542   1.1    bouyer 		goto free_ccbs;
    543   1.1    bouyer 	}
    544   1.1    bouyer 
    545   1.1    bouyer 	if (mpii_alloc_queues(sc) != 0) {
    546   1.1    bouyer 		aprint_error_dev(self, "unable to allocate reply queues\n");
    547   1.1    bouyer 		goto free_replies;
    548   1.1    bouyer 	}
    549   1.1    bouyer 
    550   1.1    bouyer 	if (mpii_iocinit(sc) != 0) {
    551   1.1    bouyer 		aprint_error_dev(self, "unable to send iocinit\n");
    552   1.1    bouyer 		goto free_queues;
    553   1.1    bouyer 	}
    554   1.1    bouyer 
    555   1.1    bouyer 	if (mpii_wait_eq(sc, MPII_DOORBELL, MPII_DOORBELL_STATE,
    556   1.1    bouyer 	    MPII_DOORBELL_STATE_OPER) != 0) {
    557   1.1    bouyer 		aprint_error_dev(self, "state: 0x%08x\n",
    558   1.1    bouyer 			mpii_read_db(sc) & MPII_DOORBELL_STATE);
    559   1.1    bouyer 		aprint_error_dev(self, "operational state timeout\n");
    560   1.1    bouyer 		goto free_queues;
    561   1.1    bouyer 	}
    562   1.1    bouyer 
    563   1.1    bouyer 	mpii_push_replies(sc);
    564   1.1    bouyer 	mpii_init_queues(sc);
    565   1.1    bouyer 
    566  1.15    bouyer 	if (mpii_board_info(sc) != 0) {
    567  1.15    bouyer 		aprint_error_dev(self, "unable to get manufacturing page 0\n");
    568  1.15    bouyer 		goto free_queues;
    569  1.15    bouyer 	}
    570  1.15    bouyer 
    571   1.1    bouyer 	if (mpii_portfacts(sc) != 0) {
    572   1.1    bouyer 		aprint_error_dev(self, "unable to get portfacts\n");
    573   1.1    bouyer 		goto free_queues;
    574   1.1    bouyer 	}
    575   1.1    bouyer 
    576  1.15    bouyer 	if (mpii_target_map(sc) != 0) {
    577  1.15    bouyer 		aprint_error_dev(self, "unable to setup target mappings\n");
    578   1.1    bouyer 		goto free_queues;
    579   1.1    bouyer 	}
    580   1.1    bouyer 
    581   1.1    bouyer 	if (mpii_cfg_coalescing(sc) != 0) {
    582   1.1    bouyer 		aprint_error_dev(self, "unable to configure coalescing\n");
    583   1.1    bouyer 		goto free_queues;
    584   1.1    bouyer 	}
    585   1.1    bouyer 
    586   1.1    bouyer 	/* XXX bail on unsupported porttype? */
    587   1.1    bouyer 	if ((sc->sc_porttype == MPII_PORTFACTS_PORTTYPE_SAS_PHYSICAL) ||
    588  1.15    bouyer 	    (sc->sc_porttype == MPII_PORTFACTS_PORTTYPE_SAS_VIRTUAL) ||
    589  1.15    bouyer 	    (sc->sc_porttype == MPII_PORTFACTS_PORTTYPE_TRI_MODE)) {
    590   1.1    bouyer 		if (mpii_eventnotify(sc) != 0) {
    591   1.1    bouyer 			aprint_error_dev(self, "unable to enable events\n");
    592   1.1    bouyer 			goto free_queues;
    593   1.1    bouyer 		}
    594   1.1    bouyer 	}
    595   1.1    bouyer 
    596  1.15    bouyer 	mutex_init(&sc->sc_devs_mtx, MUTEX_DEFAULT, IPL_BIO);
    597  1.15    bouyer 	sc->sc_devs = malloc(sc->sc_max_devices * sizeof(struct mpii_device *),
    598  1.15    bouyer 	    M_DEVBUF, M_NOWAIT | M_ZERO);
    599  1.15    bouyer 	if (sc->sc_devs == NULL) {
    600   1.1    bouyer 		aprint_error_dev(self,
    601   1.1    bouyer 		    "unable to allocate memory for mpii_device\n");
    602   1.1    bouyer 		goto free_queues;
    603   1.1    bouyer 	}
    604   1.1    bouyer 
    605   1.1    bouyer 	if (mpii_portenable(sc) != 0) {
    606   1.1    bouyer 		aprint_error_dev(self, "unable to enable port\n");
    607  1.15    bouyer 		goto free_devs;
    608   1.1    bouyer 	}
    609   1.1    bouyer 
    610  1.15    bouyer 	/* we should be good to go now, attach scsibus */
    611   1.1    bouyer 	memset(adapt, 0, sizeof(*adapt));
    612   1.1    bouyer 	adapt->adapt_dev = sc->sc_dev;
    613   1.1    bouyer 	adapt->adapt_nchannels = 1;
    614  1.15    bouyer 	adapt->adapt_openings = sc->sc_max_cmds - 4;
    615   1.1    bouyer 	adapt->adapt_max_periph = adapt->adapt_openings;
    616   1.1    bouyer 	adapt->adapt_request = mpii_scsipi_request;
    617  1.15    bouyer 	adapt->adapt_minphys = minphys;
    618   1.1    bouyer 
    619   1.1    bouyer 	memset(chan, 0, sizeof(*chan));
    620   1.1    bouyer 	chan->chan_adapter = adapt;
    621   1.1    bouyer 	chan->chan_bustype = &scsi_sas_bustype;
    622  1.15    bouyer 	chan->chan_channel = 0;
    623   1.1    bouyer 	chan->chan_flags = 0;
    624   1.2    kardel 	chan->chan_nluns = 8;
    625   1.1    bouyer 	chan->chan_ntargets = sc->sc_max_devices;
    626   1.1    bouyer 	chan->chan_id = -1;
    627   1.1    bouyer 
    628   1.1    bouyer 	mpii_rescan(self, "scsi", NULL);
    629   1.1    bouyer 
    630   1.1    bouyer 	/* enable interrupts */
    631   1.1    bouyer 	mpii_write(sc, MPII_INTR_MASK, MPII_INTR_MASK_DOORBELL
    632   1.1    bouyer 	    | MPII_INTR_MASK_RESET);
    633   1.1    bouyer 
    634   1.1    bouyer #if NBIO > 0
    635   1.1    bouyer 	if (ISSET(sc->sc_flags, MPII_F_RAID)) {
    636   1.1    bouyer 		if (bio_register(sc->sc_dev, mpii_ioctl) != 0)
    637   1.1    bouyer 			panic("%s: controller registration failed",
    638   1.1    bouyer 			    DEVNAME(sc));
    639   1.1    bouyer 		if (mpii_create_sensors(sc) != 0)
    640   1.1    bouyer 			aprint_error_dev(self, "unable to create sensors\n");
    641   1.1    bouyer 	}
    642   1.1    bouyer #endif
    643   1.1    bouyer 
    644   1.1    bouyer 	return;
    645   1.1    bouyer 
    646  1.15    bouyer free_devs:
    647  1.15    bouyer 	free(sc->sc_devs, M_DEVBUF);
    648  1.15    bouyer 	sc->sc_devs = NULL;
    649   1.1    bouyer 
    650   1.1    bouyer free_queues:
    651   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_freeq),
    652  1.15    bouyer 	    0, sc->sc_reply_free_qdepth * 4, BUS_DMASYNC_POSTREAD);
    653   1.1    bouyer 	mpii_dmamem_free(sc, sc->sc_reply_freeq);
    654   1.1    bouyer 
    655   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq),
    656   1.1    bouyer 	    0, sc->sc_reply_post_qdepth * 8, BUS_DMASYNC_POSTREAD);
    657   1.1    bouyer 	mpii_dmamem_free(sc, sc->sc_reply_postq);
    658   1.1    bouyer 
    659   1.1    bouyer free_replies:
    660   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_replies),
    661   1.1    bouyer 		0, PAGE_SIZE, BUS_DMASYNC_POSTREAD);
    662   1.1    bouyer 	mpii_dmamem_free(sc, sc->sc_replies);
    663   1.1    bouyer 
    664   1.1    bouyer free_ccbs:
    665  1.15    bouyer 	while ((ccb = mpii_get_ccb(sc)) != NULL)
    666   1.1    bouyer 		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
    667   1.1    bouyer 	mpii_dmamem_free(sc, sc->sc_requests);
    668   1.1    bouyer 	free(sc->sc_ccbs, M_DEVBUF);
    669   1.1    bouyer 
    670   1.1    bouyer unmap:
    671   1.1    bouyer 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    672   1.1    bouyer 	sc->sc_ios = 0;
    673   1.1    bouyer }
    674   1.1    bouyer 
    675  1.15    bouyer int
    676   1.1    bouyer mpii_detach(device_t self, int flags)
    677   1.1    bouyer {
    678  1.15    bouyer 	struct mpii_softc	*sc = device_private(self);
    679   1.1    bouyer 	int error;
    680   1.1    bouyer 	struct mpii_ccb *ccb;
    681   1.1    bouyer 
    682   1.1    bouyer 	if ((error = config_detach_children(sc->sc_dev, flags)) != 0)
    683   1.1    bouyer 		return error;
    684   1.1    bouyer 
    685   1.1    bouyer #if NBIO > 0
    686   1.1    bouyer 	mpii_destroy_sensors(sc);
    687   1.1    bouyer 	bio_unregister(sc->sc_dev);
    688   1.1    bouyer #endif /* NBIO > 0 */
    689   1.1    bouyer 
    690   1.1    bouyer 	if (sc->sc_ih != NULL) {
    691  1.15    bouyer 		pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
    692  1.15    bouyer 		sc->sc_ih = NULL;
    693  1.15    bouyer 	}
    694  1.15    bouyer 	if (sc->sc_ios != 0) {
    695  1.15    bouyer 		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
    696  1.15    bouyer 		free(sc->sc_devs, M_DEVBUF);
    697  1.15    bouyer 		sc->sc_devs = NULL;
    698   1.1    bouyer 
    699   1.1    bouyer 		bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_freeq),
    700   1.1    bouyer 		    0, sc->sc_reply_free_qdepth * 4, BUS_DMASYNC_POSTREAD);
    701   1.1    bouyer 		mpii_dmamem_free(sc, sc->sc_reply_freeq);
    702   1.1    bouyer 
    703   1.1    bouyer 		bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq),
    704   1.1    bouyer 		    0, sc->sc_reply_post_qdepth * 8, BUS_DMASYNC_POSTREAD);
    705   1.1    bouyer 		mpii_dmamem_free(sc, sc->sc_reply_postq);
    706   1.1    bouyer 
    707   1.1    bouyer 		bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_replies),
    708   1.1    bouyer 			0, PAGE_SIZE, BUS_DMASYNC_POSTREAD);
    709   1.1    bouyer 		mpii_dmamem_free(sc, sc->sc_replies);
    710   1.1    bouyer 
    711  1.15    bouyer 		while ((ccb = mpii_get_ccb(sc)) != NULL)
    712   1.1    bouyer 			bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
    713   1.1    bouyer 		mpii_dmamem_free(sc, sc->sc_requests);
    714   1.1    bouyer 		free(sc->sc_ccbs, M_DEVBUF);
    715   1.1    bouyer 
    716   1.1    bouyer 		sc->sc_ios = 0;
    717   1.1    bouyer 	}
    718   1.1    bouyer 
    719   1.1    bouyer 	return (0);
    720   1.1    bouyer }
    721   1.1    bouyer 
    722  1.15    bouyer int
    723  1.15    bouyer mpii_rescan(device_t self, const char *ifattr, const int *locators)
    724   1.1    bouyer {
    725   1.1    bouyer 	struct mpii_softc *sc = device_private(self);
    726   1.1    bouyer 
    727   1.1    bouyer 	if (sc->sc_child != NULL)
    728   1.1    bouyer 		return 0;
    729   1.1    bouyer 
    730   1.1    bouyer 	sc->sc_child = config_found_sm_loc(self, ifattr, locators, &sc->sc_chan,
    731   1.1    bouyer 	    scsiprint, NULL);
    732   1.1    bouyer 
    733   1.1    bouyer 	return 0;
    734   1.1    bouyer }
    735   1.1    bouyer 
    736  1.15    bouyer void
    737   1.1    bouyer mpii_childdetached(device_t self, device_t child)
    738   1.1    bouyer {
    739  1.15    bouyer 	struct mpii_softc *sc = device_private(self);
    740   1.1    bouyer 
    741  1.15    bouyer 	KASSERT(self == sc->sc_dev);
    742  1.15    bouyer 	KASSERT(child == sc->sc_child);
    743   1.1    bouyer 
    744  1.15    bouyer 	if (child == sc->sc_child)
    745  1.15    bouyer 		sc->sc_child = NULL;
    746   1.1    bouyer }
    747   1.1    bouyer 
    748  1.15    bouyer 
    749  1.15    bouyer int
    750   1.1    bouyer mpii_intr(void *arg)
    751   1.1    bouyer {
    752   1.1    bouyer 	struct mpii_rcb_list		evts = SIMPLEQ_HEAD_INITIALIZER(evts);
    753   1.1    bouyer 	struct mpii_ccb_list		ccbs = SIMPLEQ_HEAD_INITIALIZER(ccbs);
    754   1.1    bouyer 	struct mpii_softc		*sc = arg;
    755   1.1    bouyer 	struct mpii_reply_descr		*postq = sc->sc_reply_postq_kva, *rdp;
    756   1.1    bouyer 	struct mpii_ccb			*ccb;
    757   1.1    bouyer 	struct mpii_rcb			*rcb;
    758   1.1    bouyer 	int				smid;
    759  1.15    bouyer 	u_int				idx;
    760   1.1    bouyer 	int				rv = 0;
    761   1.1    bouyer 
    762   1.1    bouyer 	mutex_enter(&sc->sc_rep_mtx);
    763   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat,
    764   1.1    bouyer 	    MPII_DMA_MAP(sc->sc_reply_postq),
    765  1.15    bouyer 	    0, sc->sc_reply_post_qdepth * sizeof(*rdp),
    766   1.1    bouyer 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
    767   1.1    bouyer 
    768  1.15    bouyer 	idx = sc->sc_reply_post_host_index;
    769   1.1    bouyer 	for (;;) {
    770  1.15    bouyer 		rdp = &postq[idx];
    771   1.1    bouyer 		if ((rdp->reply_flags & MPII_REPLY_DESCR_TYPE_MASK) ==
    772   1.1    bouyer 		    MPII_REPLY_DESCR_UNUSED)
    773   1.1    bouyer 			break;
    774   1.1    bouyer 		if (rdp->data == 0xffffffff) {
    775   1.1    bouyer 			/*
    776   1.1    bouyer 			 * ioc is still writing to the reply post queue
    777   1.1    bouyer 			 * race condition - bail!
    778   1.1    bouyer 			 */
    779   1.1    bouyer 			break;
    780   1.1    bouyer 		}
    781   1.1    bouyer 
    782   1.1    bouyer 		smid = le16toh(rdp->smid);
    783   1.1    bouyer 		rcb = mpii_reply(sc, rdp);
    784   1.1    bouyer 
    785   1.1    bouyer 		if (smid) {
    786   1.1    bouyer 			ccb = &sc->sc_ccbs[smid - 1];
    787   1.1    bouyer 			ccb->ccb_state = MPII_CCB_READY;
    788   1.1    bouyer 			ccb->ccb_rcb = rcb;
    789  1.15    bouyer 			SIMPLEQ_INSERT_TAIL(&ccbs, ccb, ccb_link);
    790   1.1    bouyer 		} else
    791  1.15    bouyer 			SIMPLEQ_INSERT_TAIL(&evts, rcb, rcb_link);
    792  1.15    bouyer 
    793  1.15    bouyer 		if (++idx >= sc->sc_reply_post_qdepth)
    794  1.15    bouyer 			idx = 0;
    795   1.1    bouyer 
    796   1.1    bouyer 		rv = 1;
    797   1.1    bouyer 	}
    798   1.1    bouyer 
    799   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat,
    800   1.1    bouyer 	    MPII_DMA_MAP(sc->sc_reply_postq),
    801  1.15    bouyer 	    0, sc->sc_reply_post_qdepth * sizeof(*rdp),
    802   1.1    bouyer 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    803   1.1    bouyer 
    804   1.1    bouyer 	if (rv)
    805  1.15    bouyer 		mpii_write_reply_post(sc, sc->sc_reply_post_host_index = idx);
    806   1.1    bouyer 
    807   1.1    bouyer 	mutex_exit(&sc->sc_rep_mtx);
    808   1.1    bouyer 
    809   1.1    bouyer 	if (rv == 0)
    810   1.1    bouyer 		return (0);
    811   1.1    bouyer 
    812   1.1    bouyer 	while ((ccb = SIMPLEQ_FIRST(&ccbs)) != NULL) {
    813  1.15    bouyer 		SIMPLEQ_REMOVE_HEAD(&ccbs, ccb_link);
    814   1.1    bouyer 		ccb->ccb_done(ccb);
    815   1.1    bouyer 	}
    816   1.1    bouyer 	while ((rcb = SIMPLEQ_FIRST(&evts)) != NULL) {
    817  1.15    bouyer 		SIMPLEQ_REMOVE_HEAD(&evts, rcb_link);
    818   1.1    bouyer 		mpii_event_process(sc, rcb);
    819   1.1    bouyer 	}
    820   1.1    bouyer 
    821   1.1    bouyer 	return (1);
    822   1.1    bouyer }
    823   1.1    bouyer 
    824  1.15    bouyer int
    825  1.15    bouyer mpii_load_xs_sas3(struct mpii_ccb *ccb)
    826   1.1    bouyer {
    827   1.1    bouyer 	struct mpii_softc	*sc = ccb->ccb_sc;
    828   1.1    bouyer 	struct scsipi_xfer	*xs = ccb->ccb_cookie;
    829  1.15    bouyer 	struct mpii_msg_scsi_io	*io = ccb->ccb_cmd;
    830  1.15    bouyer 	struct mpii_ieee_sge	*csge, *nsge, *sge;
    831   1.1    bouyer 	bus_dmamap_t		dmap = ccb->ccb_dmamap;
    832   1.1    bouyer 	int			i, error;
    833   1.1    bouyer 
    834  1.15    bouyer 	/* Request frame structure is described in the mpii_iocfacts */
    835  1.15    bouyer 	nsge = (struct mpii_ieee_sge *)(io + 1);
    836  1.15    bouyer 	csge = nsge + sc->sc_chain_sge;
    837  1.15    bouyer 
    838   1.1    bouyer 	/* zero length transfer still requires an SGE */
    839   1.1    bouyer 	if (xs->datalen == 0) {
    840  1.15    bouyer 		nsge->sg_flags = MPII_IEEE_SGE_END_OF_LIST;
    841   1.1    bouyer 		return (0);
    842   1.1    bouyer 	}
    843   1.1    bouyer 
    844  1.15    bouyer 	error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data, xs->datalen, NULL,
    845  1.15    bouyer 	    (xs->xs_control & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
    846   1.1    bouyer 	if (error) {
    847  1.15    bouyer 		printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
    848   1.1    bouyer 		return (1);
    849   1.1    bouyer 	}
    850   1.1    bouyer 
    851  1.15    bouyer 	sge = nsge;
    852  1.15    bouyer 	for (i = 0; i < dmap->dm_nsegs; i++, nsge++) {
    853  1.15    bouyer 		if (nsge == csge) {
    854  1.15    bouyer 			nsge++;
    855  1.15    bouyer 			/* offset to the chain sge from the beginning */
    856  1.15    bouyer 			io->chain_offset = ((uintptr_t)csge - (uintptr_t)io) / 4;
    857  1.15    bouyer 			csge->sg_flags = MPII_IEEE_SGE_CHAIN_ELEMENT |
    858  1.15    bouyer 			    MPII_IEEE_SGE_ADDR_SYSTEM;
    859  1.15    bouyer 			/* address of the next sge */
    860  1.15    bouyer 			csge->sg_addr = htole64(ccb->ccb_cmd_dva +
    861  1.15    bouyer 			    ((uintptr_t)nsge - (uintptr_t)io));
    862  1.15    bouyer 			csge->sg_len = htole32((dmap->dm_nsegs - i) *
    863  1.15    bouyer 			    sizeof(*sge));
    864  1.15    bouyer 		}
    865   1.1    bouyer 
    866  1.15    bouyer 		sge = nsge;
    867  1.15    bouyer 		sge->sg_flags = MPII_IEEE_SGE_ADDR_SYSTEM;
    868  1.15    bouyer 		sge->sg_len = htole32(dmap->dm_segs[i].ds_len);
    869  1.15    bouyer 		sge->sg_addr = htole64(dmap->dm_segs[i].ds_addr);
    870   1.1    bouyer 	}
    871   1.1    bouyer 
    872  1.15    bouyer 	/* terminate list */
    873  1.15    bouyer 	sge->sg_flags |= MPII_IEEE_SGE_END_OF_LIST;
    874   1.1    bouyer 
    875  1.15    bouyer 	bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
    876  1.15    bouyer 	    (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD :
    877  1.15    bouyer 	    BUS_DMASYNC_PREWRITE);
    878   1.1    bouyer 
    879  1.15    bouyer 	return (0);
    880  1.15    bouyer }
    881   1.1    bouyer 
    882  1.15    bouyer int
    883  1.15    bouyer mpii_load_xs(struct mpii_ccb *ccb)
    884  1.15    bouyer {
    885  1.15    bouyer 	struct mpii_softc	*sc = ccb->ccb_sc;
    886  1.15    bouyer 	struct scsipi_xfer	*xs = ccb->ccb_cookie;
    887  1.15    bouyer 	struct mpii_msg_scsi_io	*io = ccb->ccb_cmd;
    888  1.15    bouyer 	struct mpii_sge		*csge, *nsge, *sge;
    889  1.15    bouyer 	bus_dmamap_t		dmap = ccb->ccb_dmamap;
    890  1.15    bouyer 	u_int32_t		flags;
    891  1.15    bouyer 	u_int16_t		len;
    892  1.15    bouyer 	int			i, error;
    893   1.1    bouyer 
    894  1.15    bouyer 	/* Request frame structure is described in the mpii_iocfacts */
    895  1.15    bouyer 	nsge = (struct mpii_sge *)(io + 1);
    896  1.15    bouyer 	csge = nsge + sc->sc_chain_sge;
    897   1.1    bouyer 
    898  1.15    bouyer 	/* zero length transfer still requires an SGE */
    899  1.15    bouyer 	if (xs->datalen == 0) {
    900  1.15    bouyer 		nsge->sg_hdr = htole32(MPII_SGE_FL_TYPE_SIMPLE |
    901  1.15    bouyer 		    MPII_SGE_FL_LAST | MPII_SGE_FL_EOB | MPII_SGE_FL_EOL);
    902  1.15    bouyer 		return (0);
    903  1.15    bouyer 	}
    904  1.15    bouyer 
    905  1.15    bouyer 	error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data, xs->datalen, NULL,
    906  1.15    bouyer 	    (xs->xs_control & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
    907  1.15    bouyer 	if (error) {
    908  1.15    bouyer 		printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
    909  1.15    bouyer 		return (1);
    910  1.15    bouyer 	}
    911   1.1    bouyer 
    912  1.15    bouyer 	/* safe default starting flags */
    913  1.15    bouyer 	flags = MPII_SGE_FL_TYPE_SIMPLE | MPII_SGE_FL_SIZE_64;
    914  1.15    bouyer 	if (xs->xs_control & XS_CTL_DATA_OUT)
    915  1.15    bouyer 		flags |= MPII_SGE_FL_DIR_OUT;
    916  1.15    bouyer 
    917  1.15    bouyer 	sge = nsge;
    918  1.15    bouyer 	for (i = 0; i < dmap->dm_nsegs; i++, nsge++) {
    919  1.15    bouyer 		if (nsge == csge) {
    920  1.15    bouyer 			nsge++;
    921  1.15    bouyer 			/* offset to the chain sge from the beginning */
    922  1.15    bouyer 			io->chain_offset = ((uintptr_t)csge - (uintptr_t)io) / 4;
    923  1.15    bouyer 			/* length of the sgl segment we're pointing to */
    924  1.15    bouyer 			len = (dmap->dm_nsegs - i) * sizeof(*sge);
    925  1.15    bouyer 			csge->sg_hdr = htole32(MPII_SGE_FL_TYPE_CHAIN |
    926  1.15    bouyer 			    MPII_SGE_FL_SIZE_64 | len);
    927  1.15    bouyer 			/* address of the next sge */
    928  1.15    bouyer 			mpii_dvatosge(csge, ccb->ccb_cmd_dva +
    929  1.15    bouyer 			    ((uintptr_t)nsge - (uintptr_t)io));
    930   1.1    bouyer 		}
    931   1.1    bouyer 
    932   1.1    bouyer 		sge = nsge;
    933   1.1    bouyer 		sge->sg_hdr = htole32(flags | dmap->dm_segs[i].ds_len);
    934  1.15    bouyer 		mpii_dvatosge(sge, dmap->dm_segs[i].ds_addr);
    935   1.1    bouyer 	}
    936   1.1    bouyer 
    937   1.1    bouyer 	/* terminate list */
    938   1.1    bouyer 	sge->sg_hdr |= htole32(MPII_SGE_FL_LAST | MPII_SGE_FL_EOB |
    939   1.1    bouyer 	    MPII_SGE_FL_EOL);
    940   1.1    bouyer 
    941   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
    942   1.1    bouyer 	    (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD :
    943   1.1    bouyer 	    BUS_DMASYNC_PREWRITE);
    944   1.1    bouyer 
    945   1.1    bouyer 	return (0);
    946   1.1    bouyer }
    947   1.1    bouyer 
    948  1.15    bouyer u_int32_t
    949   1.1    bouyer mpii_read(struct mpii_softc *sc, bus_size_t r)
    950   1.1    bouyer {
    951   1.1    bouyer 	u_int32_t			rv;
    952   1.1    bouyer 
    953   1.1    bouyer 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
    954   1.1    bouyer 	    BUS_SPACE_BARRIER_READ);
    955   1.1    bouyer 	rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
    956   1.1    bouyer 
    957  1.15    bouyer 	DNPRINTF(MPII_D_RW, "%s: mpii_read %#lx %#x\n", DEVNAME(sc), r, rv);
    958   1.1    bouyer 
    959   1.1    bouyer 	return (rv);
    960   1.1    bouyer }
    961   1.1    bouyer 
    962  1.15    bouyer void
    963   1.1    bouyer mpii_write(struct mpii_softc *sc, bus_size_t r, u_int32_t v)
    964   1.1    bouyer {
    965  1.15    bouyer 	DNPRINTF(MPII_D_RW, "%s: mpii_write %#lx %#x\n", DEVNAME(sc), r, v);
    966   1.1    bouyer 
    967   1.1    bouyer 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
    968   1.1    bouyer 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
    969   1.1    bouyer 	    BUS_SPACE_BARRIER_WRITE);
    970   1.1    bouyer }
    971   1.1    bouyer 
    972   1.1    bouyer 
    973  1.15    bouyer int
    974   1.1    bouyer mpii_wait_eq(struct mpii_softc *sc, bus_size_t r, u_int32_t mask,
    975   1.1    bouyer     u_int32_t target)
    976   1.1    bouyer {
    977   1.1    bouyer 	int			i;
    978   1.1    bouyer 
    979  1.15    bouyer 	DNPRINTF(MPII_D_RW, "%s: mpii_wait_eq %#lx %#x %#x\n", DEVNAME(sc), r,
    980  1.15    bouyer 	    mask, target);
    981   1.1    bouyer 
    982   1.1    bouyer 	for (i = 0; i < 15000; i++) {
    983   1.1    bouyer 		if ((mpii_read(sc, r) & mask) == target)
    984   1.1    bouyer 			return (0);
    985   1.1    bouyer 		delay(1000);
    986   1.1    bouyer 	}
    987   1.1    bouyer 
    988   1.1    bouyer 	return (1);
    989   1.1    bouyer }
    990   1.1    bouyer 
    991  1.15    bouyer int
    992   1.1    bouyer mpii_wait_ne(struct mpii_softc *sc, bus_size_t r, u_int32_t mask,
    993   1.1    bouyer     u_int32_t target)
    994   1.1    bouyer {
    995   1.1    bouyer 	int			i;
    996   1.1    bouyer 
    997  1.15    bouyer 	DNPRINTF(MPII_D_RW, "%s: mpii_wait_ne %#lx %#x %#x\n", DEVNAME(sc), r,
    998  1.15    bouyer 	    mask, target);
    999   1.1    bouyer 
   1000   1.1    bouyer 	for (i = 0; i < 15000; i++) {
   1001   1.1    bouyer 		if ((mpii_read(sc, r) & mask) != target)
   1002   1.1    bouyer 			return (0);
   1003   1.1    bouyer 		delay(1000);
   1004   1.1    bouyer 	}
   1005   1.1    bouyer 
   1006   1.1    bouyer 	return (1);
   1007   1.1    bouyer }
   1008   1.1    bouyer 
   1009  1.15    bouyer int
   1010   1.1    bouyer mpii_init(struct mpii_softc *sc)
   1011   1.1    bouyer {
   1012   1.1    bouyer 	u_int32_t		db;
   1013   1.1    bouyer 	int			i;
   1014   1.1    bouyer 
   1015   1.1    bouyer 	/* spin until the ioc leaves the reset state */
   1016   1.1    bouyer 	if (mpii_wait_ne(sc, MPII_DOORBELL, MPII_DOORBELL_STATE,
   1017   1.1    bouyer 	    MPII_DOORBELL_STATE_RESET) != 0) {
   1018   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_init timeout waiting to leave "
   1019   1.1    bouyer 		    "reset state\n", DEVNAME(sc));
   1020   1.1    bouyer 		return (1);
   1021   1.1    bouyer 	}
   1022   1.1    bouyer 
   1023   1.1    bouyer 	/* check current ownership */
   1024   1.1    bouyer 	db = mpii_read_db(sc);
   1025   1.1    bouyer 	if ((db & MPII_DOORBELL_WHOINIT) == MPII_DOORBELL_WHOINIT_PCIPEER) {
   1026   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_init initialised by pci peer\n",
   1027   1.1    bouyer 		    DEVNAME(sc));
   1028   1.1    bouyer 		return (0);
   1029   1.1    bouyer 	}
   1030   1.1    bouyer 
   1031   1.1    bouyer 	for (i = 0; i < 5; i++) {
   1032   1.1    bouyer 		switch (db & MPII_DOORBELL_STATE) {
   1033   1.1    bouyer 		case MPII_DOORBELL_STATE_READY:
   1034   1.1    bouyer 			DNPRINTF(MPII_D_MISC, "%s: mpii_init ioc is ready\n",
   1035   1.1    bouyer 			    DEVNAME(sc));
   1036   1.1    bouyer 			return (0);
   1037   1.1    bouyer 
   1038   1.1    bouyer 		case MPII_DOORBELL_STATE_OPER:
   1039   1.1    bouyer 			DNPRINTF(MPII_D_MISC, "%s: mpii_init ioc is oper\n",
   1040   1.1    bouyer 			    DEVNAME(sc));
   1041   1.1    bouyer 			if (sc->sc_ioc_event_replay)
   1042   1.1    bouyer 				mpii_reset_soft(sc);
   1043   1.1    bouyer 			else
   1044   1.1    bouyer 				mpii_reset_hard(sc);
   1045   1.1    bouyer 			break;
   1046   1.1    bouyer 
   1047   1.1    bouyer 		case MPII_DOORBELL_STATE_FAULT:
   1048   1.1    bouyer 			DNPRINTF(MPII_D_MISC, "%s: mpii_init ioc is being "
   1049   1.1    bouyer 			    "reset hard\n" , DEVNAME(sc));
   1050   1.1    bouyer 			mpii_reset_hard(sc);
   1051   1.1    bouyer 			break;
   1052   1.1    bouyer 
   1053   1.1    bouyer 		case MPII_DOORBELL_STATE_RESET:
   1054   1.1    bouyer 			DNPRINTF(MPII_D_MISC, "%s: mpii_init waiting to come "
   1055   1.1    bouyer 			    "out of reset\n", DEVNAME(sc));
   1056   1.1    bouyer 			if (mpii_wait_ne(sc, MPII_DOORBELL, MPII_DOORBELL_STATE,
   1057   1.1    bouyer 			    MPII_DOORBELL_STATE_RESET) != 0)
   1058   1.1    bouyer 				return (1);
   1059   1.1    bouyer 			break;
   1060   1.1    bouyer 		}
   1061   1.1    bouyer 		db = mpii_read_db(sc);
   1062   1.1    bouyer 	}
   1063   1.1    bouyer 
   1064   1.1    bouyer 	return (1);
   1065   1.1    bouyer }
   1066   1.1    bouyer 
   1067  1.15    bouyer int
   1068   1.1    bouyer mpii_reset_soft(struct mpii_softc *sc)
   1069   1.1    bouyer {
   1070   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_reset_soft\n", DEVNAME(sc));
   1071   1.1    bouyer 
   1072   1.1    bouyer 	if (mpii_read_db(sc) & MPII_DOORBELL_INUSE) {
   1073   1.1    bouyer 		return (1);
   1074   1.1    bouyer 	}
   1075   1.1    bouyer 
   1076   1.1    bouyer 	mpii_write_db(sc,
   1077   1.1    bouyer 	    MPII_DOORBELL_FUNCTION(MPII_FUNCTION_IOC_MESSAGE_UNIT_RESET));
   1078  1.15    bouyer 
   1079   1.1    bouyer 	/* XXX LSI waits 15 sec */
   1080   1.1    bouyer 	if (mpii_wait_db_ack(sc) != 0)
   1081   1.1    bouyer 		return (1);
   1082   1.1    bouyer 
   1083   1.1    bouyer 	/* XXX LSI waits 15 sec */
   1084   1.1    bouyer 	if (mpii_wait_eq(sc, MPII_DOORBELL, MPII_DOORBELL_STATE,
   1085   1.1    bouyer 	    MPII_DOORBELL_STATE_READY) != 0)
   1086   1.1    bouyer 		return (1);
   1087   1.1    bouyer 
   1088   1.1    bouyer 	/* XXX wait for Sys2IOCDB bit to clear in HIS?? */
   1089   1.1    bouyer 
   1090   1.1    bouyer 	return (0);
   1091   1.1    bouyer }
   1092   1.1    bouyer 
   1093  1.15    bouyer int
   1094   1.1    bouyer mpii_reset_hard(struct mpii_softc *sc)
   1095   1.1    bouyer {
   1096   1.1    bouyer 	u_int16_t		i;
   1097   1.1    bouyer 
   1098   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_reset_hard\n", DEVNAME(sc));
   1099   1.1    bouyer 
   1100   1.1    bouyer 	mpii_write_intr(sc, 0);
   1101   1.1    bouyer 
   1102   1.1    bouyer 	/* enable diagnostic register */
   1103   1.1    bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_FLUSH);
   1104   1.1    bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_1);
   1105   1.1    bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_2);
   1106   1.1    bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_3);
   1107   1.1    bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_4);
   1108   1.1    bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_5);
   1109   1.1    bouyer 	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_6);
   1110   1.1    bouyer 
   1111   1.1    bouyer 	delay(100);
   1112   1.1    bouyer 
   1113   1.1    bouyer 	if ((mpii_read(sc, MPII_HOSTDIAG) & MPII_HOSTDIAG_DWRE) == 0) {
   1114   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_reset_hard failure to enable "
   1115   1.1    bouyer 		    "diagnostic read/write\n", DEVNAME(sc));
   1116   1.1    bouyer 		return(1);
   1117   1.1    bouyer 	}
   1118   1.1    bouyer 
   1119   1.1    bouyer 	/* reset ioc */
   1120   1.1    bouyer 	mpii_write(sc, MPII_HOSTDIAG, MPII_HOSTDIAG_RESET_ADAPTER);
   1121   1.1    bouyer 
   1122   1.1    bouyer 	/* 240 milliseconds */
   1123   1.1    bouyer 	delay(240000);
   1124   1.1    bouyer 
   1125   1.1    bouyer 
   1126   1.1    bouyer 	/* XXX this whole function should be more robust */
   1127  1.15    bouyer 
   1128   1.1    bouyer 	/* XXX  read the host diagnostic reg until reset adapter bit clears ? */
   1129   1.1    bouyer 	for (i = 0; i < 30000; i++) {
   1130   1.1    bouyer 		if ((mpii_read(sc, MPII_HOSTDIAG) &
   1131   1.1    bouyer 		    MPII_HOSTDIAG_RESET_ADAPTER) == 0)
   1132   1.1    bouyer 			break;
   1133   1.1    bouyer 		delay(10000);
   1134   1.1    bouyer 	}
   1135   1.1    bouyer 
   1136   1.1    bouyer 	/* disable diagnostic register */
   1137   1.1    bouyer 	mpii_write(sc, MPII_WRITESEQ, 0xff);
   1138   1.1    bouyer 
   1139   1.1    bouyer 	/* XXX what else? */
   1140   1.1    bouyer 
   1141   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: done with mpii_reset_hard\n", DEVNAME(sc));
   1142   1.1    bouyer 
   1143   1.1    bouyer 	return(0);
   1144   1.1    bouyer }
   1145   1.1    bouyer 
   1146  1.15    bouyer int
   1147   1.1    bouyer mpii_handshake_send(struct mpii_softc *sc, void *buf, size_t dwords)
   1148   1.1    bouyer {
   1149   1.1    bouyer 	u_int32_t		*query = buf;
   1150   1.1    bouyer 	int			i;
   1151   1.1    bouyer 
   1152   1.1    bouyer 	/* make sure the doorbell is not in use. */
   1153   1.1    bouyer 	if (mpii_read_db(sc) & MPII_DOORBELL_INUSE)
   1154   1.1    bouyer 		return (1);
   1155   1.1    bouyer 
   1156   1.1    bouyer 	/* clear pending doorbell interrupts */
   1157   1.1    bouyer 	if (mpii_read_intr(sc) & MPII_INTR_STATUS_IOC2SYSDB)
   1158   1.1    bouyer 		mpii_write_intr(sc, 0);
   1159   1.1    bouyer 
   1160   1.1    bouyer 	/*
   1161   1.1    bouyer 	 * first write the doorbell with the handshake function and the
   1162   1.1    bouyer 	 * dword count.
   1163   1.1    bouyer 	 */
   1164   1.1    bouyer 	mpii_write_db(sc, MPII_DOORBELL_FUNCTION(MPII_FUNCTION_HANDSHAKE) |
   1165   1.1    bouyer 	    MPII_DOORBELL_DWORDS(dwords));
   1166   1.1    bouyer 
   1167   1.1    bouyer 	/*
   1168   1.1    bouyer 	 * the doorbell used bit will be set because a doorbell function has
   1169   1.1    bouyer 	 * started. wait for the interrupt and then ack it.
   1170   1.1    bouyer 	 */
   1171   1.1    bouyer 	if (mpii_wait_db_int(sc) != 0)
   1172   1.1    bouyer 		return (1);
   1173   1.1    bouyer 	mpii_write_intr(sc, 0);
   1174   1.1    bouyer 
   1175   1.1    bouyer 	/* poll for the acknowledgement. */
   1176   1.1    bouyer 	if (mpii_wait_db_ack(sc) != 0)
   1177   1.1    bouyer 		return (1);
   1178   1.1    bouyer 
   1179   1.1    bouyer 	/* write the query through the doorbell. */
   1180   1.1    bouyer 	for (i = 0; i < dwords; i++) {
   1181   1.1    bouyer 		mpii_write_db(sc, htole32(query[i]));
   1182   1.1    bouyer 		if (mpii_wait_db_ack(sc) != 0)
   1183   1.1    bouyer 			return (1);
   1184   1.1    bouyer 	}
   1185   1.1    bouyer 
   1186   1.1    bouyer 	return (0);
   1187   1.1    bouyer }
   1188   1.1    bouyer 
   1189  1.15    bouyer int
   1190   1.1    bouyer mpii_handshake_recv_dword(struct mpii_softc *sc, u_int32_t *dword)
   1191   1.1    bouyer {
   1192   1.1    bouyer 	u_int16_t		*words = (u_int16_t *)dword;
   1193   1.1    bouyer 	int			i;
   1194   1.1    bouyer 
   1195   1.1    bouyer 	for (i = 0; i < 2; i++) {
   1196   1.1    bouyer 		if (mpii_wait_db_int(sc) != 0)
   1197   1.1    bouyer 			return (1);
   1198   1.1    bouyer 		words[i] = le16toh(mpii_read_db(sc) & MPII_DOORBELL_DATA_MASK);
   1199   1.1    bouyer 		mpii_write_intr(sc, 0);
   1200   1.1    bouyer 	}
   1201   1.1    bouyer 
   1202   1.1    bouyer 	return (0);
   1203   1.1    bouyer }
   1204   1.1    bouyer 
   1205  1.15    bouyer int
   1206   1.1    bouyer mpii_handshake_recv(struct mpii_softc *sc, void *buf, size_t dwords)
   1207   1.1    bouyer {
   1208   1.1    bouyer 	struct mpii_msg_reply	*reply = buf;
   1209   1.1    bouyer 	u_int32_t		*dbuf = buf, dummy;
   1210   1.1    bouyer 	int			i;
   1211   1.1    bouyer 
   1212   1.1    bouyer 	/* get the first dword so we can read the length out of the header. */
   1213   1.1    bouyer 	if (mpii_handshake_recv_dword(sc, &dbuf[0]) != 0)
   1214   1.1    bouyer 		return (1);
   1215   1.1    bouyer 
   1216  1.15    bouyer 	DNPRINTF(MPII_D_CMD, "%s: mpii_handshake_recv dwords: %lu reply: %d\n",
   1217   1.1    bouyer 	    DEVNAME(sc), dwords, reply->msg_length);
   1218   1.1    bouyer 
   1219   1.1    bouyer 	/*
   1220   1.1    bouyer 	 * the total length, in dwords, is in the message length field of the
   1221   1.1    bouyer 	 * reply header.
   1222   1.1    bouyer 	 */
   1223   1.1    bouyer 	for (i = 1; i < MIN(dwords, reply->msg_length); i++) {
   1224   1.1    bouyer 		if (mpii_handshake_recv_dword(sc, &dbuf[i]) != 0)
   1225   1.1    bouyer 			return (1);
   1226   1.1    bouyer 	}
   1227   1.1    bouyer 
   1228   1.1    bouyer 	/* if there's extra stuff to come off the ioc, discard it */
   1229   1.1    bouyer 	while (i++ < reply->msg_length) {
   1230   1.1    bouyer 		if (mpii_handshake_recv_dword(sc, &dummy) != 0)
   1231   1.1    bouyer 			return (1);
   1232   1.1    bouyer 		DNPRINTF(MPII_D_CMD, "%s: mpii_handshake_recv dummy read: "
   1233   1.1    bouyer 		    "0x%08x\n", DEVNAME(sc), dummy);
   1234   1.1    bouyer 	}
   1235   1.1    bouyer 
   1236   1.1    bouyer 	/* wait for the doorbell used bit to be reset and clear the intr */
   1237   1.1    bouyer 	if (mpii_wait_db_int(sc) != 0)
   1238   1.1    bouyer 		return (1);
   1239  1.15    bouyer 
   1240   1.1    bouyer 	if (mpii_wait_eq(sc, MPII_DOORBELL, MPII_DOORBELL_INUSE, 0) != 0)
   1241   1.1    bouyer 		return (1);
   1242  1.15    bouyer 
   1243   1.1    bouyer 	mpii_write_intr(sc, 0);
   1244   1.1    bouyer 
   1245   1.1    bouyer 	return (0);
   1246   1.1    bouyer }
   1247   1.1    bouyer 
   1248  1.15    bouyer void
   1249   1.1    bouyer mpii_empty_done(struct mpii_ccb *ccb)
   1250   1.1    bouyer {
   1251   1.1    bouyer 	/* nothing to do */
   1252   1.1    bouyer }
   1253   1.1    bouyer 
   1254  1.15    bouyer int
   1255   1.1    bouyer mpii_iocfacts(struct mpii_softc *sc)
   1256   1.1    bouyer {
   1257   1.1    bouyer 	struct mpii_msg_iocfacts_request	ifq;
   1258   1.1    bouyer 	struct mpii_msg_iocfacts_reply		ifp;
   1259  1.15    bouyer 	int					irs;
   1260  1.15    bouyer 	int					sge_size;
   1261  1.15    bouyer 	u_int					qdepth;
   1262   1.1    bouyer 
   1263   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_iocfacts\n", DEVNAME(sc));
   1264   1.1    bouyer 
   1265  1.15    bouyer 	memset(&ifq, 0, sizeof(ifq));
   1266  1.15    bouyer 	memset(&ifp, 0, sizeof(ifp));
   1267   1.1    bouyer 
   1268   1.1    bouyer 	ifq.function = MPII_FUNCTION_IOC_FACTS;
   1269   1.1    bouyer 
   1270   1.1    bouyer 	if (mpii_handshake_send(sc, &ifq, dwordsof(ifq)) != 0) {
   1271   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_iocfacts send failed\n",
   1272   1.1    bouyer 		    DEVNAME(sc));
   1273   1.1    bouyer 		return (1);
   1274   1.1    bouyer 	}
   1275   1.1    bouyer 
   1276   1.1    bouyer 	if (mpii_handshake_recv(sc, &ifp, dwordsof(ifp)) != 0) {
   1277   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_iocfacts recv failed\n",
   1278   1.1    bouyer 		    DEVNAME(sc));
   1279   1.1    bouyer 		return (1);
   1280   1.1    bouyer 	}
   1281   1.1    bouyer 
   1282   1.1    bouyer 	sc->sc_ioc_number = ifp.ioc_number;
   1283   1.1    bouyer 	sc->sc_vf_id = ifp.vf_id;
   1284   1.1    bouyer 
   1285   1.1    bouyer 	sc->sc_max_volumes = ifp.max_volumes;
   1286   1.1    bouyer 	sc->sc_max_devices = ifp.max_volumes + le16toh(ifp.max_targets);
   1287   1.1    bouyer 
   1288   1.1    bouyer 	if (ISSET(le32toh(ifp.ioc_capabilities),
   1289   1.1    bouyer 	    MPII_IOCFACTS_CAPABILITY_INTEGRATED_RAID))
   1290   1.1    bouyer 		SET(sc->sc_flags, MPII_F_RAID);
   1291  1.15    bouyer 	if (ISSET(le32toh(ifp.ioc_capabilities),
   1292  1.15    bouyer 	    MPII_IOCFACTS_CAPABILITY_EVENT_REPLAY))
   1293  1.15    bouyer 		sc->sc_ioc_event_replay = 1;
   1294  1.15    bouyer 
   1295  1.15    bouyer 	sc->sc_max_cmds = MIN(le16toh(ifp.request_credit),
   1296  1.15    bouyer 	    MPII_REQUEST_CREDIT);
   1297   1.1    bouyer 
   1298  1.15    bouyer 	/* SAS3 and 3.5 controllers have different sgl layouts */
   1299  1.15    bouyer 	if (ifp.msg_version_maj == 2 && ((ifp.msg_version_min == 5)
   1300  1.15    bouyer 	    || (ifp.msg_version_min == 6)))
   1301  1.15    bouyer 		SET(sc->sc_flags, MPII_F_SAS3);
   1302   1.1    bouyer 
   1303  1.15    bouyer 	/*
   1304  1.15    bouyer 	 * The host driver must ensure that there is at least one
   1305  1.15    bouyer 	 * unused entry in the Reply Free Queue. One way to ensure
   1306  1.15    bouyer 	 * that this requirement is met is to never allocate a number
   1307  1.15    bouyer 	 * of reply frames that is a multiple of 16.
   1308  1.15    bouyer 	 */
   1309  1.15    bouyer 	sc->sc_num_reply_frames = sc->sc_max_cmds + 32;
   1310   1.1    bouyer 	if (!(sc->sc_num_reply_frames % 16))
   1311   1.1    bouyer 		sc->sc_num_reply_frames--;
   1312   1.1    bouyer 
   1313   1.1    bouyer 	/* must be multiple of 16 */
   1314  1.15    bouyer 	sc->sc_reply_post_qdepth = sc->sc_max_cmds +
   1315  1.15    bouyer 	    sc->sc_num_reply_frames;
   1316  1.15    bouyer 	sc->sc_reply_post_qdepth += 16 - (sc->sc_reply_post_qdepth % 16);
   1317  1.15    bouyer 
   1318  1.15    bouyer 	qdepth = le16toh(ifp.max_reply_descriptor_post_queue_depth);
   1319  1.15    bouyer 	if (sc->sc_reply_post_qdepth > qdepth) {
   1320  1.15    bouyer 		sc->sc_reply_post_qdepth = qdepth;
   1321  1.15    bouyer 		if (sc->sc_reply_post_qdepth < 16) {
   1322  1.15    bouyer 			printf("%s: RDPQ is too shallow\n", DEVNAME(sc));
   1323  1.15    bouyer 			return (1);
   1324  1.15    bouyer 		}
   1325  1.15    bouyer 		sc->sc_max_cmds = sc->sc_reply_post_qdepth / 2 - 4;
   1326  1.15    bouyer 		sc->sc_num_reply_frames = sc->sc_max_cmds + 4;
   1327  1.15    bouyer 	}
   1328  1.15    bouyer 
   1329   1.1    bouyer 	sc->sc_reply_free_qdepth = sc->sc_num_reply_frames +
   1330  1.15    bouyer 	    16 - (sc->sc_num_reply_frames % 16);
   1331   1.1    bouyer 
   1332   1.1    bouyer 	/*
   1333  1.15    bouyer 	 * Our request frame for an I/O operation looks like this:
   1334  1.15    bouyer 	 *
   1335  1.15    bouyer 	 * +-------------------+ -.
   1336  1.15    bouyer 	 * | mpii_msg_scsi_io  |  |
   1337  1.15    bouyer 	 * +-------------------|  |
   1338  1.15    bouyer 	 * | mpii_sge          |  |
   1339  1.15    bouyer 	 * + - - - - - - - - - +  |
   1340  1.15    bouyer 	 * | ...               |  > ioc_request_frame_size
   1341  1.15    bouyer 	 * + - - - - - - - - - +  |
   1342  1.15    bouyer 	 * | mpii_sge (tail)   |  |
   1343  1.15    bouyer 	 * + - - - - - - - - - +  |
   1344  1.15    bouyer 	 * | mpii_sge (csge)   |  | --.
   1345  1.15    bouyer 	 * + - - - - - - - - - + -'   | chain sge points to the next sge
   1346  1.15    bouyer 	 * | mpii_sge          |<-----'
   1347  1.15    bouyer 	 * + - - - - - - - - - +
   1348  1.15    bouyer 	 * | ...               |
   1349  1.15    bouyer 	 * + - - - - - - - - - +
   1350  1.15    bouyer 	 * | mpii_sge (tail)   |
   1351  1.15    bouyer 	 * +-------------------+
   1352  1.15    bouyer 	 * |                   |
   1353  1.15    bouyer 	 * ~~~~~~~~~~~~~~~~~~~~~
   1354  1.15    bouyer 	 * |                   |
   1355  1.15    bouyer 	 * +-------------------+ <- sc_request_size - sizeof(scsi_sense_data)
   1356  1.15    bouyer 	 * | scsi_sense_data   |
   1357  1.15    bouyer 	 * +-------------------+
   1358   1.1    bouyer 	 */
   1359   1.1    bouyer 
   1360  1.15    bouyer 	/* both sizes are in 32-bit words */
   1361  1.15    bouyer 	sc->sc_reply_size = ifp.reply_frame_size * 4;
   1362  1.15    bouyer 	irs = le16toh(ifp.ioc_request_frame_size) * 4;
   1363  1.15    bouyer 	sc->sc_request_size = MPII_REQUEST_SIZE;
   1364  1.15    bouyer 	/* make sure we have enough space for scsi sense data */
   1365  1.15    bouyer 	if (irs > sc->sc_request_size) {
   1366  1.15    bouyer 		sc->sc_request_size = irs + sizeof(struct scsi_sense_data);
   1367  1.15    bouyer 		sc->sc_request_size += 16 - (sc->sc_request_size % 16);
   1368  1.15    bouyer 	}
   1369  1.15    bouyer 
   1370  1.15    bouyer 	if (ISSET(sc->sc_flags, MPII_F_SAS3)) {
   1371  1.15    bouyer 		sge_size = sizeof(struct mpii_ieee_sge);
   1372  1.15    bouyer 	} else {
   1373  1.15    bouyer 		sge_size = sizeof(struct mpii_sge);
   1374  1.15    bouyer 	}
   1375   1.1    bouyer 
   1376  1.15    bouyer 	/* offset to the chain sge */
   1377  1.15    bouyer 	sc->sc_chain_sge = (irs - sizeof(struct mpii_msg_scsi_io)) /
   1378  1.15    bouyer 	    sge_size - 1;
   1379   1.1    bouyer 
   1380  1.15    bouyer 	/*
   1381  1.15    bouyer 	 * A number of simple scatter-gather elements we can fit into the
   1382  1.15    bouyer 	 * request buffer after the I/O command minus the chain element.
   1383  1.15    bouyer 	 */
   1384  1.15    bouyer 	sc->sc_max_sgl = (sc->sc_request_size -
   1385  1.15    bouyer  	    sizeof(struct mpii_msg_scsi_io) - sizeof(struct scsi_sense_data)) /
   1386  1.15    bouyer 	    sge_size - 1;
   1387   1.1    bouyer 
   1388  1.15    bouyer 	return (0);
   1389   1.1    bouyer }
   1390   1.1    bouyer 
   1391  1.15    bouyer int
   1392   1.1    bouyer mpii_iocinit(struct mpii_softc *sc)
   1393   1.1    bouyer {
   1394   1.1    bouyer 	struct mpii_msg_iocinit_request		iiq;
   1395   1.1    bouyer 	struct mpii_msg_iocinit_reply		iip;
   1396   1.1    bouyer 
   1397   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_iocinit\n", DEVNAME(sc));
   1398   1.1    bouyer 
   1399  1.15    bouyer 	memset(&iiq, 0, sizeof(iiq));
   1400  1.15    bouyer 	memset(&iip, 0, sizeof(iip));
   1401   1.1    bouyer 
   1402   1.1    bouyer 	iiq.function = MPII_FUNCTION_IOC_INIT;
   1403   1.1    bouyer 	iiq.whoinit = MPII_WHOINIT_HOST_DRIVER;
   1404  1.15    bouyer 
   1405   1.1    bouyer 	/* XXX JPG do something about vf_id */
   1406   1.1    bouyer 	iiq.vf_id = 0;
   1407   1.1    bouyer 
   1408   1.1    bouyer 	iiq.msg_version_maj = 0x02;
   1409   1.1    bouyer 	iiq.msg_version_min = 0x00;
   1410   1.1    bouyer 
   1411   1.1    bouyer 	/* XXX JPG ensure compliance with some level and hard-code? */
   1412   1.1    bouyer 	iiq.hdr_version_unit = 0x00;
   1413   1.1    bouyer 	iiq.hdr_version_dev = 0x00;
   1414   1.1    bouyer 
   1415  1.15    bouyer 	iiq.system_request_frame_size = htole16(sc->sc_request_size / 4);
   1416   1.1    bouyer 
   1417   1.1    bouyer 	iiq.reply_descriptor_post_queue_depth =
   1418   1.1    bouyer 	    htole16(sc->sc_reply_post_qdepth);
   1419   1.1    bouyer 
   1420   1.1    bouyer 	iiq.reply_free_queue_depth = htole16(sc->sc_reply_free_qdepth);
   1421   1.1    bouyer 
   1422  1.15    bouyer 	iiq.sense_buffer_address_high =
   1423  1.15    bouyer 	    htole32(MPII_DMA_DVA(sc->sc_requests) >> 32);
   1424   1.1    bouyer 
   1425  1.15    bouyer 	iiq.system_reply_address_high =
   1426  1.15    bouyer 	    htole32(MPII_DMA_DVA(sc->sc_replies) >> 32);
   1427   1.1    bouyer 
   1428  1.15    bouyer 	iiq.system_request_frame_base_address_lo =
   1429  1.15    bouyer 	    htole32(MPII_DMA_DVA(sc->sc_requests));
   1430  1.15    bouyer 	iiq.system_request_frame_base_address_hi =
   1431  1.15    bouyer 	    htole32(MPII_DMA_DVA(sc->sc_requests) >> 32);
   1432  1.15    bouyer 
   1433  1.15    bouyer 	iiq.reply_descriptor_post_queue_address_lo =
   1434  1.15    bouyer 	    htole32(MPII_DMA_DVA(sc->sc_reply_postq));
   1435  1.15    bouyer 	iiq.reply_descriptor_post_queue_address_hi =
   1436  1.15    bouyer 	    htole32(MPII_DMA_DVA(sc->sc_reply_postq) >> 32);
   1437  1.15    bouyer 
   1438  1.15    bouyer 	iiq.reply_free_queue_address_lo =
   1439  1.15    bouyer 	    htole32(MPII_DMA_DVA(sc->sc_reply_freeq));
   1440  1.15    bouyer 	iiq.reply_free_queue_address_hi =
   1441  1.15    bouyer 	    htole32(MPII_DMA_DVA(sc->sc_reply_freeq) >> 32);
   1442   1.1    bouyer 
   1443   1.1    bouyer 	if (mpii_handshake_send(sc, &iiq, dwordsof(iiq)) != 0) {
   1444   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_iocinit send failed\n",
   1445   1.1    bouyer 		    DEVNAME(sc));
   1446   1.1    bouyer 		return (1);
   1447   1.1    bouyer 	}
   1448   1.1    bouyer 
   1449   1.1    bouyer 	if (mpii_handshake_recv(sc, &iip, dwordsof(iip)) != 0) {
   1450   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_iocinit recv failed\n",
   1451   1.1    bouyer 		    DEVNAME(sc));
   1452   1.1    bouyer 		return (1);
   1453   1.1    bouyer 	}
   1454   1.1    bouyer 
   1455   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  function: 0x%02x msg_length: %d "
   1456   1.1    bouyer 	    "whoinit: 0x%02x\n", DEVNAME(sc), iip.function,
   1457   1.1    bouyer 	    iip.msg_length, iip.whoinit);
   1458   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  msg_flags: 0x%02x\n", DEVNAME(sc),
   1459   1.1    bouyer 	    iip.msg_flags);
   1460   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  vf_id: 0x%02x vp_id: 0x%02x\n", DEVNAME(sc),
   1461   1.1    bouyer 	    iip.vf_id, iip.vp_id);
   1462   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
   1463   1.1    bouyer 	    le16toh(iip.ioc_status));
   1464   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
   1465   1.1    bouyer 	    le32toh(iip.ioc_loginfo));
   1466   1.1    bouyer 
   1467  1.15    bouyer 	if (le16toh(iip.ioc_status) != MPII_IOCSTATUS_SUCCESS ||
   1468  1.15    bouyer 	    le32toh(iip.ioc_loginfo))
   1469   1.1    bouyer 		return (1);
   1470   1.1    bouyer 
   1471   1.1    bouyer 	return (0);
   1472   1.1    bouyer }
   1473   1.1    bouyer 
   1474  1.15    bouyer void
   1475   1.1    bouyer mpii_push_reply(struct mpii_softc *sc, struct mpii_rcb *rcb)
   1476   1.1    bouyer {
   1477   1.1    bouyer 	u_int32_t		*rfp;
   1478  1.15    bouyer 	u_int			idx;
   1479   1.1    bouyer 
   1480   1.1    bouyer 	if (rcb == NULL)
   1481   1.1    bouyer 		return;
   1482   1.1    bouyer 
   1483  1.15    bouyer 	mutex_enter(&sc->sc_reply_free_mtx);
   1484  1.15    bouyer 	idx = sc->sc_reply_free_host_index;
   1485  1.15    bouyer 
   1486   1.1    bouyer 	rfp = MPII_DMA_KVA(sc->sc_reply_freeq);
   1487  1.15    bouyer 	rfp[idx] = htole32(rcb->rcb_reply_dva);
   1488   1.1    bouyer 
   1489  1.15    bouyer 	if (++idx >= sc->sc_reply_free_qdepth)
   1490  1.15    bouyer 		idx = 0;
   1491   1.1    bouyer 
   1492  1.15    bouyer 	mpii_write_reply_free(sc, sc->sc_reply_free_host_index = idx);
   1493  1.15    bouyer 	mutex_exit(&sc->sc_reply_free_mtx);
   1494   1.1    bouyer }
   1495   1.1    bouyer 
   1496  1.15    bouyer int
   1497   1.1    bouyer mpii_portfacts(struct mpii_softc *sc)
   1498   1.1    bouyer {
   1499   1.1    bouyer 	struct mpii_msg_portfacts_request	*pfq;
   1500   1.1    bouyer 	struct mpii_msg_portfacts_reply		*pfp;
   1501   1.1    bouyer 	struct mpii_ccb				*ccb;
   1502   1.1    bouyer 	int					rv = 1;
   1503   1.1    bouyer 
   1504   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_portfacts\n", DEVNAME(sc));
   1505   1.1    bouyer 
   1506  1.15    bouyer 	ccb = mpii_get_ccb(sc);
   1507   1.1    bouyer 	if (ccb == NULL) {
   1508   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_portfacts mpii_get_ccb fail\n",
   1509   1.1    bouyer 		    DEVNAME(sc));
   1510   1.1    bouyer 		return (rv);
   1511   1.1    bouyer 	}
   1512   1.1    bouyer 
   1513   1.1    bouyer 	ccb->ccb_done = mpii_empty_done;
   1514   1.1    bouyer 	pfq = ccb->ccb_cmd;
   1515   1.1    bouyer 
   1516  1.15    bouyer 	memset(pfq, 0, sizeof(*pfq));
   1517   1.1    bouyer 
   1518   1.1    bouyer 	pfq->function = MPII_FUNCTION_PORT_FACTS;
   1519   1.1    bouyer 	pfq->chain_offset = 0;
   1520   1.1    bouyer 	pfq->msg_flags = 0;
   1521   1.1    bouyer 	pfq->port_number = 0;
   1522   1.1    bouyer 	pfq->vp_id = 0;
   1523   1.1    bouyer 	pfq->vf_id = 0;
   1524   1.1    bouyer 
   1525   1.1    bouyer 	if (mpii_poll(sc, ccb) != 0) {
   1526   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_portfacts poll\n",
   1527   1.1    bouyer 		    DEVNAME(sc));
   1528   1.1    bouyer 		goto err;
   1529   1.1    bouyer 	}
   1530   1.1    bouyer 
   1531   1.1    bouyer 	if (ccb->ccb_rcb == NULL) {
   1532   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: empty portfacts reply\n",
   1533   1.1    bouyer 		    DEVNAME(sc));
   1534   1.1    bouyer 		goto err;
   1535   1.1    bouyer 	}
   1536   1.1    bouyer 
   1537   1.1    bouyer 	pfp = ccb->ccb_rcb->rcb_reply;
   1538   1.1    bouyer 	sc->sc_porttype = pfp->port_type;
   1539   1.1    bouyer 
   1540   1.1    bouyer 	mpii_push_reply(sc, ccb->ccb_rcb);
   1541   1.1    bouyer 	rv = 0;
   1542   1.1    bouyer err:
   1543   1.1    bouyer 	mpii_put_ccb(sc, ccb);
   1544   1.1    bouyer 
   1545   1.1    bouyer 	return (rv);
   1546   1.1    bouyer }
   1547   1.1    bouyer 
   1548  1.15    bouyer void
   1549  1.15    bouyer mpii_eventack(struct work *wk, void * cookie)
   1550   1.1    bouyer {
   1551   1.1    bouyer 	struct mpii_softc			*sc = cookie;
   1552   1.1    bouyer 	struct mpii_ccb				*ccb;
   1553  1.15    bouyer 	struct mpii_rcb				*rcb, *next;
   1554   1.1    bouyer 	struct mpii_msg_event_reply		*enp;
   1555   1.1    bouyer 	struct mpii_msg_eventack_request	*eaq;
   1556   1.1    bouyer 
   1557  1.15    bouyer 	mutex_enter(&sc->sc_evt_ack_mtx);
   1558  1.15    bouyer 	next = SIMPLEQ_FIRST(&sc->sc_evt_ack_queue);
   1559  1.15    bouyer 	SIMPLEQ_INIT(&sc->sc_evt_ack_queue);
   1560  1.15    bouyer 	mutex_exit(&sc->sc_evt_ack_mtx);
   1561   1.1    bouyer 
   1562  1.15    bouyer 	while (next != NULL) {
   1563  1.15    bouyer 		rcb = next;
   1564  1.15    bouyer 		next = SIMPLEQ_NEXT(rcb, rcb_link);
   1565   1.1    bouyer 
   1566  1.15    bouyer 		enp = (struct mpii_msg_event_reply *)rcb->rcb_reply;
   1567   1.1    bouyer 
   1568  1.15    bouyer 		ccb = mpii_get_ccb(sc);
   1569  1.15    bouyer 		ccb->ccb_done = mpii_eventack_done;
   1570  1.15    bouyer 		eaq = ccb->ccb_cmd;
   1571   1.1    bouyer 
   1572  1.15    bouyer 		eaq->function = MPII_FUNCTION_EVENT_ACK;
   1573   1.1    bouyer 
   1574  1.15    bouyer 		eaq->event = enp->event;
   1575  1.15    bouyer 		eaq->event_context = enp->event_context;
   1576   1.1    bouyer 
   1577  1.15    bouyer 		mpii_push_reply(sc, rcb);
   1578   1.1    bouyer 
   1579  1.15    bouyer 		mpii_start(sc, ccb);
   1580  1.15    bouyer 	}
   1581   1.1    bouyer }
   1582   1.1    bouyer 
   1583  1.15    bouyer void
   1584   1.1    bouyer mpii_eventack_done(struct mpii_ccb *ccb)
   1585   1.1    bouyer {
   1586   1.1    bouyer 	struct mpii_softc			*sc = ccb->ccb_sc;
   1587   1.1    bouyer 
   1588   1.1    bouyer 	DNPRINTF(MPII_D_EVT, "%s: event ack done\n", DEVNAME(sc));
   1589   1.1    bouyer 
   1590   1.1    bouyer 	mpii_push_reply(sc, ccb->ccb_rcb);
   1591   1.1    bouyer 	mpii_put_ccb(sc, ccb);
   1592   1.1    bouyer }
   1593   1.1    bouyer 
   1594  1.15    bouyer int
   1595   1.1    bouyer mpii_portenable(struct mpii_softc *sc)
   1596   1.1    bouyer {
   1597   1.1    bouyer 	struct mpii_msg_portenable_request	*peq;
   1598   1.1    bouyer 	struct mpii_ccb				*ccb;
   1599   1.1    bouyer 
   1600   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_portenable\n", DEVNAME(sc));
   1601   1.1    bouyer 
   1602  1.15    bouyer 	ccb = mpii_get_ccb(sc);
   1603   1.1    bouyer 	if (ccb == NULL) {
   1604   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_portenable ccb_get\n",
   1605   1.1    bouyer 		    DEVNAME(sc));
   1606   1.1    bouyer 		return (1);
   1607   1.1    bouyer 	}
   1608   1.1    bouyer 
   1609   1.1    bouyer 	ccb->ccb_done = mpii_empty_done;
   1610   1.1    bouyer 	peq = ccb->ccb_cmd;
   1611   1.1    bouyer 
   1612   1.1    bouyer 	peq->function = MPII_FUNCTION_PORT_ENABLE;
   1613   1.1    bouyer 	peq->vf_id = sc->sc_vf_id;
   1614   1.1    bouyer 
   1615   1.1    bouyer 	if (mpii_poll(sc, ccb) != 0) {
   1616   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_portenable poll\n",
   1617   1.1    bouyer 		    DEVNAME(sc));
   1618   1.1    bouyer 		return (1);
   1619   1.1    bouyer 	}
   1620   1.1    bouyer 
   1621   1.1    bouyer 	if (ccb->ccb_rcb == NULL) {
   1622   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: empty portenable reply\n",
   1623   1.1    bouyer 		    DEVNAME(sc));
   1624   1.1    bouyer 		return (1);
   1625   1.1    bouyer 	}
   1626   1.1    bouyer 
   1627   1.1    bouyer 	mpii_push_reply(sc, ccb->ccb_rcb);
   1628   1.1    bouyer 	mpii_put_ccb(sc, ccb);
   1629   1.1    bouyer 
   1630   1.1    bouyer 	return (0);
   1631   1.1    bouyer }
   1632   1.1    bouyer 
   1633  1.15    bouyer int
   1634   1.1    bouyer mpii_cfg_coalescing(struct mpii_softc *sc)
   1635   1.1    bouyer {
   1636  1.15    bouyer 	struct mpii_cfg_hdr			hdr;
   1637  1.15    bouyer 	struct mpii_cfg_ioc_pg1			ipg;
   1638   1.1    bouyer 
   1639  1.15    bouyer 	hdr.page_version = 0;
   1640  1.15    bouyer 	hdr.page_length = sizeof(ipg) / 4;
   1641  1.15    bouyer 	hdr.page_number = 1;
   1642  1.15    bouyer 	hdr.page_type = MPII_CONFIG_REQ_PAGE_TYPE_IOC;
   1643  1.15    bouyer 	memset(&ipg, 0, sizeof(ipg));
   1644  1.15    bouyer 	if (mpii_req_cfg_page(sc, 0, MPII_PG_POLL, &hdr, 1, &ipg,
   1645  1.15    bouyer 	    sizeof(ipg)) != 0) {
   1646   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: unable to fetch IOC page 1\n"
   1647   1.1    bouyer 		    "page 1\n", DEVNAME(sc));
   1648   1.1    bouyer 		return (1);
   1649   1.1    bouyer 	}
   1650   1.1    bouyer 
   1651  1.15    bouyer 	if (!ISSET(le32toh(ipg.flags), MPII_CFG_IOC_1_REPLY_COALESCING))
   1652   1.1    bouyer 		return (0);
   1653   1.1    bouyer 
   1654  1.15    bouyer 	/* Disable coalescing */
   1655  1.15    bouyer 	CLR(ipg.flags, htole32(MPII_CFG_IOC_1_REPLY_COALESCING));
   1656  1.15    bouyer 	if (mpii_req_cfg_page(sc, 0, MPII_PG_POLL, &hdr, 0, &ipg,
   1657  1.15    bouyer 	    sizeof(ipg)) != 0) {
   1658   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: unable to clear coalescing\n",
   1659   1.1    bouyer 		    DEVNAME(sc));
   1660   1.1    bouyer 		return (1);
   1661   1.1    bouyer 	}
   1662   1.1    bouyer 
   1663   1.1    bouyer 	return (0);
   1664   1.1    bouyer }
   1665   1.1    bouyer 
   1666   1.1    bouyer #define MPII_EVENT_MASKALL(enq)		do {			\
   1667   1.1    bouyer 		enq->event_masks[0] = 0xffffffff;		\
   1668   1.1    bouyer 		enq->event_masks[1] = 0xffffffff;		\
   1669   1.1    bouyer 		enq->event_masks[2] = 0xffffffff;		\
   1670   1.1    bouyer 		enq->event_masks[3] = 0xffffffff;		\
   1671   1.1    bouyer 	} while (0)
   1672   1.1    bouyer 
   1673   1.1    bouyer #define MPII_EVENT_UNMASK(enq, evt)	do {			\
   1674   1.1    bouyer 		enq->event_masks[evt / 32] &=			\
   1675   1.1    bouyer 		    htole32(~(1 << (evt % 32)));		\
   1676   1.1    bouyer 	} while (0)
   1677   1.1    bouyer 
   1678  1.15    bouyer int
   1679   1.1    bouyer mpii_eventnotify(struct mpii_softc *sc)
   1680   1.1    bouyer {
   1681   1.1    bouyer 	struct mpii_msg_event_request		*enq;
   1682   1.1    bouyer 	struct mpii_ccb				*ccb;
   1683  1.15    bouyer 	char wkname[15];
   1684   1.1    bouyer 
   1685  1.15    bouyer 	ccb = mpii_get_ccb(sc);
   1686   1.1    bouyer 	if (ccb == NULL) {
   1687   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_eventnotify ccb_get\n",
   1688   1.1    bouyer 		    DEVNAME(sc));
   1689   1.1    bouyer 		return (1);
   1690   1.1    bouyer 	}
   1691   1.1    bouyer 
   1692  1.15    bouyer 	SIMPLEQ_INIT(&sc->sc_evt_sas_queue);
   1693  1.15    bouyer 	mutex_init(&sc->sc_evt_sas_mtx, MUTEX_DEFAULT, IPL_BIO);
   1694  1.15    bouyer 	snprintf(wkname, sizeof(wkname), "%ssas", DEVNAME(sc));
   1695  1.15    bouyer 	if (workqueue_create(&sc->sc_evt_sas_wq, wkname,
   1696  1.15    bouyer 	    mpii_event_sas_work, sc, PRI_NONE, IPL_BIO, WQ_MPSAFE) != 0) {
   1697  1.15    bouyer 		mpii_put_ccb(sc, ccb);
   1698  1.15    bouyer 		aprint_error_dev(sc->sc_dev,
   1699  1.15    bouyer 		    "can't create %s workqueue\n", wkname);
   1700  1.15    bouyer 		return 1;
   1701  1.15    bouyer 	}
   1702  1.15    bouyer 
   1703  1.15    bouyer 	SIMPLEQ_INIT(&sc->sc_evt_ack_queue);
   1704  1.15    bouyer 	mutex_init(&sc->sc_evt_ack_mtx, MUTEX_DEFAULT, IPL_BIO);
   1705  1.15    bouyer 	snprintf(wkname, sizeof(wkname), "%sevt", DEVNAME(sc));
   1706  1.15    bouyer 	if (workqueue_create(&sc->sc_evt_ack_wq, wkname,
   1707  1.15    bouyer 	    mpii_eventack, sc, PRI_NONE, IPL_BIO, WQ_MPSAFE) != 0) {
   1708  1.15    bouyer 		mpii_put_ccb(sc, ccb);
   1709  1.15    bouyer 		aprint_error_dev(sc->sc_dev,
   1710  1.15    bouyer 		    "can't create %s workqueue\n", wkname);
   1711  1.15    bouyer 		return 1;
   1712  1.15    bouyer 	}
   1713  1.15    bouyer 
   1714   1.1    bouyer 	ccb->ccb_done = mpii_eventnotify_done;
   1715   1.1    bouyer 	enq = ccb->ccb_cmd;
   1716   1.1    bouyer 
   1717   1.1    bouyer 	enq->function = MPII_FUNCTION_EVENT_NOTIFICATION;
   1718   1.1    bouyer 
   1719   1.1    bouyer 	/*
   1720   1.1    bouyer 	 * Enable reporting of the following events:
   1721   1.1    bouyer 	 *
   1722   1.1    bouyer 	 * MPII_EVENT_SAS_DISCOVERY
   1723   1.1    bouyer 	 * MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST
   1724   1.1    bouyer 	 * MPII_EVENT_SAS_DEVICE_STATUS_CHANGE
   1725   1.1    bouyer 	 * MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE
   1726   1.1    bouyer 	 * MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST
   1727   1.1    bouyer 	 * MPII_EVENT_IR_VOLUME
   1728   1.1    bouyer 	 * MPII_EVENT_IR_PHYSICAL_DISK
   1729   1.1    bouyer 	 * MPII_EVENT_IR_OPERATION_STATUS
   1730   1.1    bouyer 	 */
   1731   1.1    bouyer 
   1732   1.1    bouyer 	MPII_EVENT_MASKALL(enq);
   1733   1.1    bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_DISCOVERY);
   1734   1.1    bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
   1735   1.1    bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_DEVICE_STATUS_CHANGE);
   1736   1.1    bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE);
   1737   1.1    bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST);
   1738   1.1    bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_VOLUME);
   1739   1.1    bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_PHYSICAL_DISK);
   1740   1.1    bouyer 	MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_OPERATION_STATUS);
   1741   1.1    bouyer 
   1742   1.1    bouyer 	mpii_start(sc, ccb);
   1743   1.1    bouyer 
   1744   1.1    bouyer 	return (0);
   1745   1.1    bouyer }
   1746   1.1    bouyer 
   1747  1.15    bouyer void
   1748   1.1    bouyer mpii_eventnotify_done(struct mpii_ccb *ccb)
   1749   1.1    bouyer {
   1750   1.1    bouyer 	struct mpii_softc			*sc = ccb->ccb_sc;
   1751   1.1    bouyer 	struct mpii_rcb				*rcb = ccb->ccb_rcb;
   1752   1.1    bouyer 
   1753   1.1    bouyer 	DNPRINTF(MPII_D_EVT, "%s: mpii_eventnotify_done\n", DEVNAME(sc));
   1754   1.1    bouyer 
   1755   1.1    bouyer 	mpii_put_ccb(sc, ccb);
   1756   1.1    bouyer 	mpii_event_process(sc, rcb);
   1757   1.1    bouyer }
   1758   1.1    bouyer 
   1759  1.15    bouyer void
   1760   1.1    bouyer mpii_event_raid(struct mpii_softc *sc, struct mpii_msg_event_reply *enp)
   1761   1.1    bouyer {
   1762   1.1    bouyer 	struct mpii_evt_ir_cfg_change_list	*ccl;
   1763   1.1    bouyer 	struct mpii_evt_ir_cfg_element		*ce;
   1764   1.1    bouyer 	struct mpii_device			*dev;
   1765   1.1    bouyer 	u_int16_t				type;
   1766   1.1    bouyer 	int					i;
   1767   1.1    bouyer 
   1768   1.1    bouyer 	ccl = (struct mpii_evt_ir_cfg_change_list *)(enp + 1);
   1769   1.1    bouyer 	if (ccl->num_elements == 0)
   1770   1.1    bouyer 		return;
   1771  1.15    bouyer 
   1772  1.15    bouyer 	if (ISSET(le32toh(ccl->flags), MPII_EVT_IR_CFG_CHANGE_LIST_FOREIGN)) {
   1773   1.1    bouyer 		/* bail on foreign configurations */
   1774   1.1    bouyer 		return;
   1775  1.15    bouyer 	}
   1776   1.1    bouyer 
   1777   1.1    bouyer 	ce = (struct mpii_evt_ir_cfg_element *)(ccl + 1);
   1778   1.1    bouyer 
   1779   1.1    bouyer 	for (i = 0; i < ccl->num_elements; i++, ce++) {
   1780   1.1    bouyer 		type = (le16toh(ce->element_flags) &
   1781   1.1    bouyer 		    MPII_EVT_IR_CFG_ELEMENT_TYPE_MASK);
   1782   1.1    bouyer 
   1783   1.1    bouyer 		switch (type) {
   1784   1.1    bouyer 		case MPII_EVT_IR_CFG_ELEMENT_TYPE_VOLUME:
   1785   1.1    bouyer 			switch (ce->reason_code) {
   1786   1.1    bouyer 			case MPII_EVT_IR_CFG_ELEMENT_RC_ADDED:
   1787   1.1    bouyer 			case MPII_EVT_IR_CFG_ELEMENT_RC_VOLUME_CREATED:
   1788  1.15    bouyer 				dev = malloc(sizeof(*dev), M_DEVBUF,
   1789  1.15    bouyer 				    M_NOWAIT | M_ZERO);
   1790  1.15    bouyer 				if (!dev) {
   1791  1.15    bouyer 					printf("%s: failed to allocate a "
   1792  1.15    bouyer 					    "device structure\n", DEVNAME(sc));
   1793  1.15    bouyer 					break;
   1794  1.15    bouyer 				}
   1795  1.15    bouyer 				mutex_enter(&sc->sc_devs_mtx);
   1796   1.1    bouyer 				if (mpii_find_dev(sc,
   1797   1.1    bouyer 				    le16toh(ce->vol_dev_handle))) {
   1798  1.15    bouyer 					mutex_exit(&sc->sc_devs_mtx);
   1799  1.15    bouyer 					free(dev, M_DEVBUF);
   1800  1.15    bouyer 					printf("%s: device %#x is already "
   1801  1.15    bouyer 					    "configured\n", DEVNAME(sc),
   1802   1.1    bouyer 					    le16toh(ce->vol_dev_handle));
   1803   1.1    bouyer 					break;
   1804   1.1    bouyer 				}
   1805   1.1    bouyer 				SET(dev->flags, MPII_DF_VOLUME);
   1806   1.1    bouyer 				dev->slot = sc->sc_vd_id_low;
   1807   1.1    bouyer 				dev->dev_handle = le16toh(ce->vol_dev_handle);
   1808   1.1    bouyer 				if (mpii_insert_dev(sc, dev)) {
   1809  1.15    bouyer 					mutex_exit(&sc->sc_devs_mtx);
   1810   1.1    bouyer 					free(dev, M_DEVBUF);
   1811   1.1    bouyer 					break;
   1812   1.1    bouyer 				}
   1813   1.1    bouyer 				sc->sc_vd_count++;
   1814  1.15    bouyer 				mutex_exit(&sc->sc_devs_mtx);
   1815   1.1    bouyer 				break;
   1816   1.1    bouyer 			case MPII_EVT_IR_CFG_ELEMENT_RC_REMOVED:
   1817   1.1    bouyer 			case MPII_EVT_IR_CFG_ELEMENT_RC_VOLUME_DELETED:
   1818  1.15    bouyer 				mutex_enter(&sc->sc_devs_mtx);
   1819   1.1    bouyer 				if (!(dev = mpii_find_dev(sc,
   1820  1.15    bouyer 				    le16toh(ce->vol_dev_handle)))) {
   1821  1.15    bouyer 					mutex_exit(&sc->sc_devs_mtx);
   1822   1.1    bouyer 					break;
   1823  1.15    bouyer 				}
   1824   1.1    bouyer 				mpii_remove_dev(sc, dev);
   1825   1.1    bouyer 				sc->sc_vd_count--;
   1826  1.15    bouyer 				mutex_exit(&sc->sc_devs_mtx);
   1827   1.1    bouyer 				break;
   1828   1.1    bouyer 			}
   1829   1.1    bouyer 			break;
   1830   1.1    bouyer 		case MPII_EVT_IR_CFG_ELEMENT_TYPE_VOLUME_DISK:
   1831   1.1    bouyer 			if (ce->reason_code ==
   1832   1.1    bouyer 			    MPII_EVT_IR_CFG_ELEMENT_RC_PD_CREATED ||
   1833   1.1    bouyer 			    ce->reason_code ==
   1834   1.1    bouyer 			    MPII_EVT_IR_CFG_ELEMENT_RC_HIDE) {
   1835   1.1    bouyer 				/* there should be an underlying sas drive */
   1836  1.15    bouyer 				mutex_enter(&sc->sc_devs_mtx);
   1837   1.1    bouyer 				if (!(dev = mpii_find_dev(sc,
   1838  1.15    bouyer 				    le16toh(ce->phys_disk_dev_handle)))) {
   1839  1.15    bouyer 					mutex_exit(&sc->sc_devs_mtx);
   1840   1.1    bouyer 					break;
   1841  1.15    bouyer 				}
   1842   1.1    bouyer 				/* promoted from a hot spare? */
   1843   1.1    bouyer 				CLR(dev->flags, MPII_DF_HOT_SPARE);
   1844   1.1    bouyer 				SET(dev->flags, MPII_DF_VOLUME_DISK |
   1845   1.1    bouyer 				    MPII_DF_HIDDEN);
   1846  1.15    bouyer 				mutex_exit(&sc->sc_devs_mtx);
   1847   1.1    bouyer 			}
   1848   1.1    bouyer 			break;
   1849   1.1    bouyer 		case MPII_EVT_IR_CFG_ELEMENT_TYPE_HOT_SPARE:
   1850   1.1    bouyer 			if (ce->reason_code ==
   1851   1.1    bouyer 			    MPII_EVT_IR_CFG_ELEMENT_RC_HIDE) {
   1852   1.1    bouyer 				/* there should be an underlying sas drive */
   1853  1.15    bouyer 				mutex_enter(&sc->sc_devs_mtx);
   1854   1.1    bouyer 				if (!(dev = mpii_find_dev(sc,
   1855  1.15    bouyer 				    le16toh(ce->phys_disk_dev_handle)))) {
   1856  1.15    bouyer 					mutex_exit(&sc->sc_devs_mtx);
   1857   1.1    bouyer 					break;
   1858  1.15    bouyer 				}
   1859   1.1    bouyer 				SET(dev->flags, MPII_DF_HOT_SPARE |
   1860   1.1    bouyer 				    MPII_DF_HIDDEN);
   1861  1.15    bouyer 				mutex_exit(&sc->sc_devs_mtx);
   1862   1.1    bouyer 			}
   1863   1.1    bouyer 			break;
   1864   1.1    bouyer 		}
   1865   1.1    bouyer 	}
   1866   1.1    bouyer }
   1867   1.1    bouyer 
   1868  1.15    bouyer void
   1869  1.15    bouyer mpii_event_sas(struct mpii_softc *sc, struct mpii_rcb *rcb)
   1870   1.1    bouyer {
   1871  1.15    bouyer 	struct mpii_msg_event_reply 	*enp;
   1872   1.1    bouyer 	struct mpii_evt_sas_tcl		*tcl;
   1873   1.1    bouyer 	struct mpii_evt_phy_entry	*pe;
   1874   1.1    bouyer 	struct mpii_device		*dev;
   1875   1.1    bouyer 	int				i;
   1876  1.15    bouyer 	u_int16_t			handle;
   1877  1.15    bouyer 	int				need_queue = 0;
   1878  1.15    bouyer 
   1879  1.15    bouyer 	enp = (struct mpii_msg_event_reply *)rcb->rcb_reply;
   1880  1.15    bouyer 	DNPRINTF(MPII_D_EVT, "%s: mpii_event_sas 0x%x\n",
   1881  1.15    bouyer 		    DEVNAME(sc), le16toh(enp->event));
   1882  1.15    bouyer 	KASSERT(le16toh(enp->event) == MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
   1883   1.1    bouyer 
   1884   1.1    bouyer 	tcl = (struct mpii_evt_sas_tcl *)(enp + 1);
   1885   1.1    bouyer 	pe = (struct mpii_evt_phy_entry *)(tcl + 1);
   1886   1.1    bouyer 
   1887   1.1    bouyer 	for (i = 0; i < tcl->num_entries; i++, pe++) {
   1888  1.15    bouyer 		DNPRINTF(MPII_D_EVT, "%s: sas change %d stat %d h %d slot %d phy %d enc %d expand %d\n",
   1889  1.15    bouyer 		    DEVNAME(sc), i, pe->phy_status,
   1890  1.15    bouyer 		    le16toh(pe->dev_handle),
   1891  1.15    bouyer 		    sc->sc_pd_id_start + tcl->start_phy_num + i,
   1892  1.15    bouyer 		    tcl->start_phy_num + i, le16toh(tcl->enclosure_handle), le16toh(tcl->expander_handle));
   1893  1.15    bouyer 
   1894   1.1    bouyer 		switch (pe->phy_status & MPII_EVENT_SAS_TOPO_PS_RC_MASK) {
   1895   1.1    bouyer 		case MPII_EVENT_SAS_TOPO_PS_RC_ADDED:
   1896  1.15    bouyer 			handle = le16toh(pe->dev_handle);
   1897  1.15    bouyer 			DNPRINTF(MPII_D_EVT, "%s: sas add handle %d\n",
   1898  1.15    bouyer 			    DEVNAME(sc), handle);
   1899  1.15    bouyer 			dev = malloc(sizeof(*dev), M_DEVBUF, M_WAITOK | M_ZERO);
   1900  1.15    bouyer 			mutex_enter(&sc->sc_devs_mtx);
   1901  1.15    bouyer 			if (mpii_find_dev(sc, handle)) {
   1902  1.15    bouyer 				mutex_exit(&sc->sc_devs_mtx);
   1903  1.15    bouyer 				free(dev, M_DEVBUF);
   1904  1.15    bouyer 				printf("%s: device %#x is already "
   1905  1.15    bouyer 				    "configured\n", DEVNAME(sc), handle);
   1906   1.1    bouyer 				break;
   1907   1.1    bouyer 			}
   1908  1.15    bouyer 
   1909   1.1    bouyer 			dev->slot = sc->sc_pd_id_start + tcl->start_phy_num + i;
   1910  1.15    bouyer 			dev->dev_handle = handle;
   1911   1.1    bouyer 			dev->phy_num = tcl->start_phy_num + i;
   1912   1.1    bouyer 			if (tcl->enclosure_handle)
   1913   1.1    bouyer 				dev->physical_port = tcl->physical_port;
   1914   1.1    bouyer 			dev->enclosure = le16toh(tcl->enclosure_handle);
   1915   1.1    bouyer 			dev->expander = le16toh(tcl->expander_handle);
   1916  1.15    bouyer 
   1917   1.1    bouyer 			if (mpii_insert_dev(sc, dev)) {
   1918  1.15    bouyer 				mutex_exit(&sc->sc_devs_mtx);
   1919   1.1    bouyer 				free(dev, M_DEVBUF);
   1920   1.1    bouyer 				break;
   1921   1.1    bouyer 			}
   1922  1.15    bouyer 			printf("%s: physical disk inserted in slot %d\n",
   1923  1.15    bouyer 			    DEVNAME(sc), dev->slot);
   1924  1.15    bouyer 			mutex_exit(&sc->sc_devs_mtx);
   1925   1.1    bouyer 			break;
   1926  1.15    bouyer 
   1927   1.1    bouyer 		case MPII_EVENT_SAS_TOPO_PS_RC_MISSING:
   1928  1.15    bouyer 			/* defer to workqueue thread */
   1929  1.15    bouyer 			need_queue++;
   1930  1.15    bouyer 			break;
   1931  1.15    bouyer 		}
   1932  1.15    bouyer 	}
   1933  1.15    bouyer 
   1934  1.15    bouyer 	if (need_queue) {
   1935  1.15    bouyer 		bool start_wk;
   1936  1.15    bouyer 		mutex_enter(&sc->sc_evt_sas_mtx);
   1937  1.15    bouyer 		start_wk = (SIMPLEQ_FIRST(&sc->sc_evt_sas_queue) == 0);
   1938  1.15    bouyer 		SIMPLEQ_INSERT_TAIL(&sc->sc_evt_sas_queue, rcb, rcb_link);
   1939  1.15    bouyer 		if (start_wk) {
   1940  1.15    bouyer 			workqueue_enqueue(sc->sc_evt_sas_wq,
   1941  1.15    bouyer 			    &sc->sc_evt_sas_work, NULL);
   1942  1.15    bouyer 		}
   1943  1.15    bouyer 		mutex_exit(&sc->sc_evt_sas_mtx);
   1944  1.15    bouyer 	} else
   1945  1.15    bouyer 		mpii_event_done(sc, rcb);
   1946  1.15    bouyer }
   1947  1.15    bouyer 
   1948  1.15    bouyer void
   1949  1.15    bouyer mpii_event_sas_work(struct work *wq, void *xsc)
   1950  1.15    bouyer {
   1951  1.15    bouyer 	struct mpii_softc *sc = xsc;
   1952  1.15    bouyer 	struct mpii_rcb *rcb, *next;
   1953  1.15    bouyer 	struct mpii_msg_event_reply *enp;
   1954  1.15    bouyer 	struct mpii_evt_sas_tcl		*tcl;
   1955  1.15    bouyer 	struct mpii_evt_phy_entry	*pe;
   1956  1.15    bouyer 	struct mpii_device		*dev;
   1957  1.15    bouyer 	int				i;
   1958  1.15    bouyer 
   1959  1.15    bouyer 	mutex_enter(&sc->sc_evt_sas_mtx);
   1960  1.15    bouyer 	next = SIMPLEQ_FIRST(&sc->sc_evt_sas_queue);
   1961  1.15    bouyer 	SIMPLEQ_INIT(&sc->sc_evt_sas_queue);
   1962  1.15    bouyer 	mutex_exit(&sc->sc_evt_sas_mtx);
   1963  1.15    bouyer 
   1964  1.15    bouyer 	while (next != NULL) {
   1965  1.15    bouyer 		rcb = next;
   1966  1.15    bouyer 		next = SIMPLEQ_NEXT(rcb, rcb_link);
   1967  1.15    bouyer 
   1968  1.15    bouyer 		enp = (struct mpii_msg_event_reply *)rcb->rcb_reply;
   1969  1.15    bouyer 		DNPRINTF(MPII_D_EVT, "%s: mpii_event_sas_work 0x%x\n",
   1970  1.15    bouyer 			    DEVNAME(sc), le16toh(enp->event));
   1971  1.15    bouyer 		KASSERT(le16toh(enp->event) == MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
   1972  1.15    bouyer 		tcl = (struct mpii_evt_sas_tcl *)(enp + 1);
   1973  1.15    bouyer 		pe = (struct mpii_evt_phy_entry *)(tcl + 1);
   1974  1.15    bouyer 
   1975  1.15    bouyer 		for (i = 0; i < tcl->num_entries; i++, pe++) {
   1976  1.15    bouyer 			DNPRINTF(MPII_D_EVT, "%s: sas change %d stat %d h %d slot %d phy %d enc %d expand %d\n",
   1977  1.15    bouyer 			    DEVNAME(sc), i, pe->phy_status,
   1978  1.15    bouyer 			    le16toh(pe->dev_handle),
   1979  1.15    bouyer 			    sc->sc_pd_id_start + tcl->start_phy_num + i,
   1980  1.15    bouyer 			    tcl->start_phy_num + i, le16toh(tcl->enclosure_handle), le16toh(tcl->expander_handle));
   1981  1.15    bouyer 
   1982  1.15    bouyer 			switch (pe->phy_status & MPII_EVENT_SAS_TOPO_PS_RC_MASK) {
   1983  1.15    bouyer 			case MPII_EVENT_SAS_TOPO_PS_RC_ADDED:
   1984  1.15    bouyer 				/* already handled */
   1985  1.15    bouyer 				break;
   1986  1.15    bouyer 
   1987  1.15    bouyer 			case MPII_EVENT_SAS_TOPO_PS_RC_MISSING:
   1988  1.15    bouyer 				mutex_enter(&sc->sc_devs_mtx);
   1989  1.15    bouyer 				dev = mpii_find_dev(sc, le16toh(pe->dev_handle));
   1990  1.15    bouyer 				if (dev == NULL) {
   1991  1.15    bouyer 					mutex_exit(&sc->sc_devs_mtx);
   1992  1.15    bouyer 					break;
   1993  1.15    bouyer 				}
   1994  1.15    bouyer 
   1995  1.15    bouyer 				printf(
   1996  1.15    bouyer 				    "%s: physical disk removed from slot %d\n",
   1997  1.15    bouyer 				    DEVNAME(sc), dev->slot);
   1998  1.15    bouyer 				mpii_remove_dev(sc, dev);
   1999  1.15    bouyer 				mutex_exit(&sc->sc_devs_mtx);
   2000  1.15    bouyer 				mpii_sas_remove_device(sc, dev->dev_handle);
   2001  1.15    bouyer 				if (!ISSET(dev->flags, MPII_DF_HIDDEN)) {
   2002  1.15    bouyer 					scsipi_target_detach(&sc->sc_chan,
   2003  1.15    bouyer 					    dev->slot, 0, DETACH_FORCE);
   2004  1.15    bouyer 					sysmon_envsys_sensor_detach(sc->sc_sme,
   2005  1.15    bouyer 					    &sc->sc_sensors[dev->slot]);
   2006  1.15    bouyer 				}
   2007  1.15    bouyer 
   2008  1.15    bouyer 				free(dev, M_DEVBUF);
   2009   1.1    bouyer 				break;
   2010   1.1    bouyer 			}
   2011   1.1    bouyer 		}
   2012  1.15    bouyer 		mpii_event_done(sc, rcb);
   2013  1.15    bouyer 	}
   2014  1.15    bouyer }
   2015  1.15    bouyer 
   2016  1.15    bouyer void
   2017  1.15    bouyer mpii_event_discovery(struct mpii_softc *sc, struct mpii_msg_event_reply *enp)
   2018  1.15    bouyer {
   2019  1.15    bouyer 	struct mpii_evt_sas_discovery *esd =
   2020  1.15    bouyer 	    (struct mpii_evt_sas_discovery *)(enp + 1);
   2021  1.15    bouyer 
   2022  1.15    bouyer 	if (esd->reason_code == MPII_EVENT_SAS_DISC_REASON_CODE_COMPLETED) {
   2023  1.15    bouyer 		if (esd->discovery_status != 0) {
   2024  1.15    bouyer 			printf("%s: sas discovery completed with status %#x\n",
   2025  1.15    bouyer 			    DEVNAME(sc), esd->discovery_status);
   2026  1.15    bouyer 		}
   2027  1.15    bouyer 
   2028   1.1    bouyer 	}
   2029   1.1    bouyer }
   2030   1.1    bouyer 
   2031  1.15    bouyer void
   2032   1.1    bouyer mpii_event_process(struct mpii_softc *sc, struct mpii_rcb *rcb)
   2033   1.1    bouyer {
   2034   1.1    bouyer 	struct mpii_msg_event_reply		*enp;
   2035   1.1    bouyer 
   2036   1.1    bouyer 	enp = (struct mpii_msg_event_reply *)rcb->rcb_reply;
   2037   1.1    bouyer 
   2038   1.1    bouyer 	DNPRINTF(MPII_D_EVT, "%s: mpii_event_process: %#x\n", DEVNAME(sc),
   2039  1.15    bouyer 	    le16toh(enp->event));
   2040   1.1    bouyer 
   2041  1.15    bouyer 	switch (le16toh(enp->event)) {
   2042   1.1    bouyer 	case MPII_EVENT_EVENT_CHANGE:
   2043   1.1    bouyer 		/* should be properly ignored */
   2044   1.1    bouyer 		break;
   2045  1.15    bouyer 	case MPII_EVENT_SAS_DISCOVERY:
   2046  1.15    bouyer 		mpii_event_discovery(sc, enp);
   2047   1.1    bouyer 		break;
   2048   1.1    bouyer 	case MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
   2049  1.15    bouyer 		mpii_event_sas(sc, rcb);
   2050  1.15    bouyer 		return;
   2051   1.1    bouyer 	case MPII_EVENT_SAS_DEVICE_STATUS_CHANGE:
   2052   1.1    bouyer 		break;
   2053   1.1    bouyer 	case MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
   2054   1.1    bouyer 		break;
   2055   1.1    bouyer 	case MPII_EVENT_IR_VOLUME: {
   2056   1.1    bouyer 		struct mpii_evt_ir_volume	*evd =
   2057   1.1    bouyer 		    (struct mpii_evt_ir_volume *)(enp + 1);
   2058   1.1    bouyer 		struct mpii_device		*dev;
   2059   1.1    bouyer #if NBIO > 0
   2060   1.1    bouyer 		const char *vol_states[] = {
   2061   1.1    bouyer 			BIOC_SVINVALID_S,
   2062   1.1    bouyer 			BIOC_SVOFFLINE_S,
   2063   1.1    bouyer 			BIOC_SVBUILDING_S,
   2064   1.1    bouyer 			BIOC_SVONLINE_S,
   2065   1.1    bouyer 			BIOC_SVDEGRADED_S,
   2066   1.1    bouyer 			BIOC_SVONLINE_S,
   2067   1.1    bouyer 		};
   2068   1.1    bouyer #endif
   2069   1.1    bouyer 
   2070   1.1    bouyer 		if (cold)
   2071   1.1    bouyer 			break;
   2072  1.15    bouyer 		mutex_enter(&sc->sc_devs_mtx);
   2073  1.15    bouyer 		dev = mpii_find_dev(sc, le16toh(evd->vol_dev_handle));
   2074  1.15    bouyer 		if (dev == NULL) {
   2075  1.15    bouyer 			mutex_exit(&sc->sc_devs_mtx);
   2076   1.1    bouyer 			break;
   2077  1.15    bouyer 		}
   2078   1.1    bouyer #if NBIO > 0
   2079   1.1    bouyer 		if (evd->reason_code == MPII_EVENT_IR_VOL_RC_STATE_CHANGED)
   2080   1.1    bouyer 			printf("%s: volume %d state changed from %s to %s\n",
   2081   1.1    bouyer 			    DEVNAME(sc), dev->slot - sc->sc_vd_id_low,
   2082   1.1    bouyer 			    vol_states[evd->prev_value],
   2083   1.1    bouyer 			    vol_states[evd->new_value]);
   2084   1.1    bouyer #endif
   2085   1.1    bouyer 		if (evd->reason_code == MPII_EVENT_IR_VOL_RC_STATUS_CHANGED &&
   2086   1.1    bouyer 		    ISSET(evd->new_value, MPII_CFG_RAID_VOL_0_STATUS_RESYNC) &&
   2087   1.1    bouyer 		    !ISSET(evd->prev_value, MPII_CFG_RAID_VOL_0_STATUS_RESYNC))
   2088   1.1    bouyer 			printf("%s: started resync on a volume %d\n",
   2089   1.1    bouyer 			    DEVNAME(sc), dev->slot - sc->sc_vd_id_low);
   2090   1.1    bouyer 		}
   2091  1.15    bouyer 		mutex_exit(&sc->sc_devs_mtx);
   2092   1.1    bouyer 		break;
   2093   1.1    bouyer 	case MPII_EVENT_IR_PHYSICAL_DISK:
   2094   1.1    bouyer 		break;
   2095   1.1    bouyer 	case MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST:
   2096   1.1    bouyer 		mpii_event_raid(sc, enp);
   2097   1.1    bouyer 		break;
   2098   1.1    bouyer 	case MPII_EVENT_IR_OPERATION_STATUS: {
   2099   1.1    bouyer 		struct mpii_evt_ir_status	*evs =
   2100   1.1    bouyer 		    (struct mpii_evt_ir_status *)(enp + 1);
   2101   1.1    bouyer 		struct mpii_device		*dev;
   2102   1.1    bouyer 
   2103  1.15    bouyer 		mutex_enter(&sc->sc_devs_mtx);
   2104  1.15    bouyer 		dev = mpii_find_dev(sc, le16toh(evs->vol_dev_handle));
   2105  1.15    bouyer 		if (dev != NULL &&
   2106  1.15    bouyer 		    evs->operation == MPII_EVENT_IR_RAIDOP_RESYNC)
   2107   1.1    bouyer 			dev->percent = evs->percent;
   2108  1.15    bouyer 		mutex_exit(&sc->sc_devs_mtx);
   2109   1.1    bouyer 		break;
   2110   1.1    bouyer 		}
   2111   1.1    bouyer 	default:
   2112   1.1    bouyer 		DNPRINTF(MPII_D_EVT, "%s:  unhandled event 0x%02x\n",
   2113  1.15    bouyer 		    DEVNAME(sc), le16toh(enp->event));
   2114   1.1    bouyer 	}
   2115   1.1    bouyer 
   2116  1.15    bouyer 	mpii_event_done(sc, rcb);
   2117   1.1    bouyer }
   2118   1.1    bouyer 
   2119  1.15    bouyer void
   2120  1.15    bouyer mpii_event_done(struct mpii_softc *sc, struct mpii_rcb *rcb)
   2121   1.1    bouyer {
   2122  1.15    bouyer 	struct mpii_msg_event_reply *enp = rcb->rcb_reply;
   2123  1.15    bouyer 	bool	need_start;
   2124   1.1    bouyer 
   2125  1.15    bouyer 	if (enp->ack_required) {
   2126  1.15    bouyer 		mutex_enter(&sc->sc_evt_ack_mtx);
   2127  1.15    bouyer 		need_start = (SIMPLEQ_FIRST(&sc->sc_evt_ack_queue) == 0);
   2128  1.15    bouyer 		SIMPLEQ_INSERT_TAIL(&sc->sc_evt_ack_queue, rcb, rcb_link);
   2129  1.15    bouyer 		if (need_start)
   2130  1.15    bouyer 			workqueue_enqueue(sc->sc_evt_ack_wq,
   2131  1.15    bouyer 			    &sc->sc_evt_ack_work, NULL);
   2132  1.15    bouyer 		mutex_exit(&sc->sc_evt_ack_mtx);
   2133  1.15    bouyer 	} else
   2134  1.15    bouyer 		mpii_push_reply(sc, rcb);
   2135   1.1    bouyer }
   2136   1.1    bouyer 
   2137  1.15    bouyer void
   2138   1.1    bouyer mpii_sas_remove_device(struct mpii_softc *sc, u_int16_t handle)
   2139   1.1    bouyer {
   2140  1.15    bouyer 	struct mpii_msg_scsi_task_request	*stq;
   2141   1.1    bouyer 	struct mpii_msg_sas_oper_request	*soq;
   2142   1.1    bouyer 	struct mpii_ccb				*ccb;
   2143   1.1    bouyer 
   2144  1.15    bouyer 	ccb = mpii_get_ccb(sc);
   2145   1.1    bouyer 	if (ccb == NULL)
   2146   1.1    bouyer 		return;
   2147   1.1    bouyer 
   2148   1.1    bouyer 	stq = ccb->ccb_cmd;
   2149   1.1    bouyer 	stq->function = MPII_FUNCTION_SCSI_TASK_MGMT;
   2150   1.1    bouyer 	stq->task_type = MPII_SCSI_TASK_TARGET_RESET;
   2151   1.1    bouyer 	stq->dev_handle = htole16(handle);
   2152   1.1    bouyer 
   2153   1.1    bouyer 	ccb->ccb_done = mpii_empty_done;
   2154   1.1    bouyer 	mpii_wait(sc, ccb);
   2155   1.1    bouyer 
   2156   1.1    bouyer 	if (ccb->ccb_rcb != NULL)
   2157   1.1    bouyer 		mpii_push_reply(sc, ccb->ccb_rcb);
   2158   1.1    bouyer 
   2159   1.1    bouyer 	/* reuse a ccb */
   2160   1.1    bouyer 	ccb->ccb_state = MPII_CCB_READY;
   2161   1.1    bouyer 	ccb->ccb_rcb = NULL;
   2162   1.1    bouyer 
   2163   1.1    bouyer 	soq = ccb->ccb_cmd;
   2164  1.15    bouyer 	memset(soq, 0, sizeof(*soq));
   2165   1.1    bouyer 	soq->function = MPII_FUNCTION_SAS_IO_UNIT_CONTROL;
   2166   1.1    bouyer 	soq->operation = MPII_SAS_OP_REMOVE_DEVICE;
   2167   1.1    bouyer 	soq->dev_handle = htole16(handle);
   2168   1.1    bouyer 
   2169   1.1    bouyer 	ccb->ccb_done = mpii_empty_done;
   2170   1.1    bouyer 	mpii_wait(sc, ccb);
   2171   1.1    bouyer 	if (ccb->ccb_rcb != NULL)
   2172   1.1    bouyer 		mpii_push_reply(sc, ccb->ccb_rcb);
   2173  1.15    bouyer 
   2174  1.15    bouyer 	mpii_put_ccb(sc, ccb);
   2175   1.1    bouyer }
   2176   1.1    bouyer 
   2177  1.15    bouyer int
   2178  1.15    bouyer mpii_board_info(struct mpii_softc *sc)
   2179   1.1    bouyer {
   2180  1.15    bouyer 	struct mpii_msg_iocfacts_request	ifq;
   2181  1.15    bouyer 	struct mpii_msg_iocfacts_reply		ifp;
   2182  1.15    bouyer 	struct mpii_cfg_manufacturing_pg0	mpg;
   2183  1.15    bouyer 	struct mpii_cfg_hdr			hdr;
   2184  1.15    bouyer 
   2185  1.15    bouyer 	memset(&ifq, 0, sizeof(ifq));
   2186  1.15    bouyer 	memset(&ifp, 0, sizeof(ifp));
   2187   1.1    bouyer 
   2188  1.15    bouyer 	ifq.function = MPII_FUNCTION_IOC_FACTS;
   2189   1.1    bouyer 
   2190  1.15    bouyer 	if (mpii_handshake_send(sc, &ifq, dwordsof(ifq)) != 0) {
   2191  1.15    bouyer 		DNPRINTF(MPII_D_MISC, "%s: failed to request ioc facts\n",
   2192  1.15    bouyer 		    DEVNAME(sc));
   2193   1.1    bouyer 		return (1);
   2194   1.1    bouyer 	}
   2195   1.1    bouyer 
   2196  1.15    bouyer 	if (mpii_handshake_recv(sc, &ifp, dwordsof(ifp)) != 0) {
   2197  1.15    bouyer 		DNPRINTF(MPII_D_MISC, "%s: failed to receive ioc facts\n",
   2198  1.15    bouyer 		    DEVNAME(sc));
   2199   1.1    bouyer 		return (1);
   2200   1.1    bouyer 	}
   2201   1.1    bouyer 
   2202  1.15    bouyer 	hdr.page_version = 0;
   2203  1.15    bouyer 	hdr.page_length = sizeof(mpg) / 4;
   2204  1.15    bouyer 	hdr.page_number = 0;
   2205  1.15    bouyer 	hdr.page_type = MPII_CONFIG_REQ_PAGE_TYPE_MANUFACTURING;
   2206  1.15    bouyer 	memset(&mpg, 0, sizeof(mpg));
   2207  1.15    bouyer 	if (mpii_req_cfg_page(sc, 0, MPII_PG_POLL, &hdr, 1, &mpg,
   2208  1.15    bouyer 	    sizeof(mpg)) != 0) {
   2209  1.15    bouyer 		printf("%s: unable to fetch manufacturing page 0\n",
   2210  1.15    bouyer 		    DEVNAME(sc));
   2211  1.15    bouyer 		return (EINVAL);
   2212   1.1    bouyer 	}
   2213   1.1    bouyer 
   2214  1.15    bouyer 	printf("%s: %s, firmware %u.%u.%u.%u%s, MPI %u.%u\n", DEVNAME(sc),
   2215  1.15    bouyer 	    mpg.board_name, ifp.fw_version_maj, ifp.fw_version_min,
   2216  1.15    bouyer 	    ifp.fw_version_unit, ifp.fw_version_dev,
   2217  1.15    bouyer 	    ISSET(sc->sc_flags, MPII_F_RAID) ? " IR" : "",
   2218  1.15    bouyer 	    ifp.msg_version_maj, ifp.msg_version_min);
   2219  1.15    bouyer 
   2220  1.15    bouyer 	return (0);
   2221  1.15    bouyer }
   2222  1.15    bouyer 
   2223  1.15    bouyer int
   2224  1.15    bouyer mpii_target_map(struct mpii_softc *sc)
   2225  1.15    bouyer {
   2226  1.15    bouyer 	struct mpii_cfg_hdr			hdr;
   2227  1.15    bouyer 	struct mpii_cfg_ioc_pg8			ipg;
   2228  1.15    bouyer 	int					flags, pad = 0;
   2229   1.1    bouyer 
   2230  1.15    bouyer 	hdr.page_version = 0;
   2231  1.15    bouyer 	hdr.page_length = sizeof(ipg) / 4;
   2232  1.15    bouyer 	hdr.page_number = 8;
   2233  1.15    bouyer 	hdr.page_type = MPII_CONFIG_REQ_PAGE_TYPE_IOC;
   2234  1.15    bouyer 	memset(&ipg, 0, sizeof(ipg));
   2235  1.15    bouyer 	if (mpii_req_cfg_page(sc, 0, MPII_PG_POLL, &hdr, 1, &ipg,
   2236  1.15    bouyer 	    sizeof(ipg)) != 0) {
   2237  1.15    bouyer 		printf("%s: unable to fetch ioc page 8\n",
   2238  1.15    bouyer 		    DEVNAME(sc));
   2239  1.15    bouyer 		return (EINVAL);
   2240  1.15    bouyer 	}
   2241  1.15    bouyer 
   2242  1.15    bouyer 	if (le16toh(ipg.flags) & MPII_IOC_PG8_FLAGS_RESERVED_TARGETID_0)
   2243   1.1    bouyer 		pad = 1;
   2244   1.1    bouyer 
   2245  1.15    bouyer 	flags = le16toh(ipg.ir_volume_mapping_flags) &
   2246   1.1    bouyer 	    MPII_IOC_PG8_IRFLAGS_VOLUME_MAPPING_MODE_MASK;
   2247   1.1    bouyer 	if (ISSET(sc->sc_flags, MPII_F_RAID)) {
   2248   1.1    bouyer 		if (flags == MPII_IOC_PG8_IRFLAGS_LOW_VOLUME_MAPPING) {
   2249   1.1    bouyer 			sc->sc_vd_id_low += pad;
   2250   1.1    bouyer 			pad = sc->sc_max_volumes; /* for sc_pd_id_start */
   2251   1.1    bouyer 		} else
   2252   1.1    bouyer 			sc->sc_vd_id_low = sc->sc_max_devices -
   2253   1.1    bouyer 			    sc->sc_max_volumes;
   2254   1.1    bouyer 	}
   2255   1.1    bouyer 
   2256   1.1    bouyer 	sc->sc_pd_id_start += pad;
   2257   1.1    bouyer 
   2258  1.15    bouyer 	return (0);
   2259   1.1    bouyer }
   2260   1.1    bouyer 
   2261  1.15    bouyer int
   2262   1.1    bouyer mpii_req_cfg_header(struct mpii_softc *sc, u_int8_t type, u_int8_t number,
   2263   1.1    bouyer     u_int32_t address, int flags, void *p)
   2264   1.1    bouyer {
   2265   1.1    bouyer 	struct mpii_msg_config_request		*cq;
   2266   1.1    bouyer 	struct mpii_msg_config_reply		*cp;
   2267  1.15    bouyer 	struct mpii_ccb				*ccb;
   2268  1.15    bouyer 	struct mpii_cfg_hdr			*hdr = p;
   2269  1.15    bouyer 	struct mpii_ecfg_hdr			*ehdr = p;
   2270  1.15    bouyer 	int					etype = 0;
   2271  1.15    bouyer 	int					rv = 0;
   2272   1.1    bouyer 
   2273   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_req_cfg_header type: %#x number: %x "
   2274   1.1    bouyer 	    "address: 0x%08x flags: 0x%x\n", DEVNAME(sc), type, number,
   2275   1.1    bouyer 	    address, flags);
   2276   1.1    bouyer 
   2277  1.15    bouyer 	ccb = mpii_get_ccb(sc);
   2278   1.1    bouyer 	if (ccb == NULL) {
   2279   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header ccb_get\n",
   2280   1.1    bouyer 		    DEVNAME(sc));
   2281   1.1    bouyer 		return (1);
   2282   1.1    bouyer 	}
   2283   1.1    bouyer 
   2284   1.1    bouyer 	if (ISSET(flags, MPII_PG_EXTENDED)) {
   2285   1.1    bouyer 		etype = type;
   2286   1.1    bouyer 		type = MPII_CONFIG_REQ_PAGE_TYPE_EXTENDED;
   2287   1.1    bouyer 	}
   2288   1.1    bouyer 
   2289   1.1    bouyer 	cq = ccb->ccb_cmd;
   2290   1.1    bouyer 
   2291   1.1    bouyer 	cq->function = MPII_FUNCTION_CONFIG;
   2292   1.1    bouyer 
   2293   1.1    bouyer 	cq->action = MPII_CONFIG_REQ_ACTION_PAGE_HEADER;
   2294   1.1    bouyer 
   2295   1.1    bouyer 	cq->config_header.page_number = number;
   2296   1.1    bouyer 	cq->config_header.page_type = type;
   2297   1.1    bouyer 	cq->ext_page_type = etype;
   2298   1.1    bouyer 	cq->page_address = htole32(address);
   2299   1.1    bouyer 	cq->page_buffer.sg_hdr = htole32(MPII_SGE_FL_TYPE_SIMPLE |
   2300   1.1    bouyer 	    MPII_SGE_FL_LAST | MPII_SGE_FL_EOB | MPII_SGE_FL_EOL);
   2301   1.1    bouyer 
   2302   1.1    bouyer 	ccb->ccb_done = mpii_empty_done;
   2303   1.1    bouyer 	if (ISSET(flags, MPII_PG_POLL)) {
   2304   1.1    bouyer 		if (mpii_poll(sc, ccb) != 0) {
   2305   1.1    bouyer 			DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header poll\n",
   2306   1.1    bouyer 			    DEVNAME(sc));
   2307   1.1    bouyer 			return (1);
   2308   1.1    bouyer 		}
   2309   1.1    bouyer 	} else
   2310   1.1    bouyer 		mpii_wait(sc, ccb);
   2311   1.1    bouyer 
   2312   1.1    bouyer 	if (ccb->ccb_rcb == NULL) {
   2313   1.1    bouyer 		mpii_put_ccb(sc, ccb);
   2314   1.1    bouyer 		return (1);
   2315   1.1    bouyer 	}
   2316   1.1    bouyer 	cp = ccb->ccb_rcb->rcb_reply;
   2317   1.1    bouyer 
   2318   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  action: 0x%02x sgl_flags: 0x%02x "
   2319   1.1    bouyer 	    "msg_length: %d function: 0x%02x\n", DEVNAME(sc), cp->action,
   2320   1.1    bouyer 	    cp->sgl_flags, cp->msg_length, cp->function);
   2321   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ext_page_length: %d ext_page_type: 0x%02x "
   2322   1.1    bouyer 	    "msg_flags: 0x%02x\n", DEVNAME(sc),
   2323   1.1    bouyer 	    le16toh(cp->ext_page_length), cp->ext_page_type,
   2324   1.1    bouyer 	    cp->msg_flags);
   2325   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc),
   2326  1.15    bouyer 	    cp->vp_id, cp->vf_id);
   2327   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
   2328   1.1    bouyer 	    le16toh(cp->ioc_status));
   2329   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
   2330   1.1    bouyer 	    le32toh(cp->ioc_loginfo));
   2331   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  page_version: 0x%02x page_length: %d "
   2332   1.1    bouyer 	    "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc),
   2333   1.1    bouyer 	    cp->config_header.page_version,
   2334   1.1    bouyer 	    cp->config_header.page_length,
   2335   1.1    bouyer 	    cp->config_header.page_number,
   2336   1.1    bouyer 	    cp->config_header.page_type);
   2337   1.1    bouyer 
   2338   1.1    bouyer 	if (le16toh(cp->ioc_status) != MPII_IOCSTATUS_SUCCESS)
   2339   1.1    bouyer 		rv = 1;
   2340   1.1    bouyer 	else if (ISSET(flags, MPII_PG_EXTENDED)) {
   2341  1.15    bouyer 		memset(ehdr, 0, sizeof(*ehdr));
   2342   1.1    bouyer 		ehdr->page_version = cp->config_header.page_version;
   2343   1.1    bouyer 		ehdr->page_number = cp->config_header.page_number;
   2344   1.1    bouyer 		ehdr->page_type = cp->config_header.page_type;
   2345   1.1    bouyer 		ehdr->ext_page_length = cp->ext_page_length;
   2346   1.1    bouyer 		ehdr->ext_page_type = cp->ext_page_type;
   2347   1.1    bouyer 	} else
   2348   1.1    bouyer 		*hdr = cp->config_header;
   2349   1.1    bouyer 
   2350   1.1    bouyer 	mpii_push_reply(sc, ccb->ccb_rcb);
   2351   1.1    bouyer 	mpii_put_ccb(sc, ccb);
   2352   1.1    bouyer 
   2353   1.1    bouyer 	return (rv);
   2354   1.1    bouyer }
   2355   1.1    bouyer 
   2356  1.15    bouyer int
   2357   1.1    bouyer mpii_req_cfg_page(struct mpii_softc *sc, u_int32_t address, int flags,
   2358   1.1    bouyer     void *p, int read, void *page, size_t len)
   2359   1.1    bouyer {
   2360   1.1    bouyer 	struct mpii_msg_config_request		*cq;
   2361   1.1    bouyer 	struct mpii_msg_config_reply		*cp;
   2362  1.15    bouyer 	struct mpii_ccb				*ccb;
   2363  1.15    bouyer 	struct mpii_cfg_hdr			*hdr = p;
   2364  1.15    bouyer 	struct mpii_ecfg_hdr			*ehdr = p;
   2365  1.15    bouyer 	uintptr_t				kva;
   2366  1.15    bouyer 	int					page_length;
   2367  1.15    bouyer 	int					rv = 0;
   2368   1.1    bouyer 
   2369   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_page address: %d read: %d "
   2370   1.1    bouyer 	    "type: %x\n", DEVNAME(sc), address, read, hdr->page_type);
   2371   1.1    bouyer 
   2372   1.1    bouyer 	page_length = ISSET(flags, MPII_PG_EXTENDED) ?
   2373   1.1    bouyer 	    le16toh(ehdr->ext_page_length) : hdr->page_length;
   2374   1.1    bouyer 
   2375  1.15    bouyer 	if (len > sc->sc_request_size - sizeof(*cq) || len < page_length * 4)
   2376   1.1    bouyer 		return (1);
   2377   1.1    bouyer 
   2378  1.15    bouyer 	ccb = mpii_get_ccb(sc);
   2379   1.1    bouyer 	if (ccb == NULL) {
   2380   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_page ccb_get\n",
   2381   1.1    bouyer 		    DEVNAME(sc));
   2382   1.1    bouyer 		return (1);
   2383   1.1    bouyer 	}
   2384   1.1    bouyer 
   2385   1.1    bouyer 	cq = ccb->ccb_cmd;
   2386   1.1    bouyer 
   2387   1.1    bouyer 	cq->function = MPII_FUNCTION_CONFIG;
   2388   1.1    bouyer 
   2389   1.1    bouyer 	cq->action = (read ? MPII_CONFIG_REQ_ACTION_PAGE_READ_CURRENT :
   2390   1.1    bouyer 	    MPII_CONFIG_REQ_ACTION_PAGE_WRITE_CURRENT);
   2391   1.1    bouyer 
   2392   1.1    bouyer 	if (ISSET(flags, MPII_PG_EXTENDED)) {
   2393   1.1    bouyer 		cq->config_header.page_version = ehdr->page_version;
   2394   1.1    bouyer 		cq->config_header.page_number = ehdr->page_number;
   2395   1.1    bouyer 		cq->config_header.page_type = ehdr->page_type;
   2396   1.1    bouyer 		cq->ext_page_len = ehdr->ext_page_length;
   2397   1.1    bouyer 		cq->ext_page_type = ehdr->ext_page_type;
   2398   1.1    bouyer 	} else
   2399   1.1    bouyer 		cq->config_header = *hdr;
   2400   1.1    bouyer 	cq->config_header.page_type &= MPII_CONFIG_REQ_PAGE_TYPE_MASK;
   2401   1.1    bouyer 	cq->page_address = htole32(address);
   2402   1.1    bouyer 	cq->page_buffer.sg_hdr = htole32(MPII_SGE_FL_TYPE_SIMPLE |
   2403   1.1    bouyer 	    MPII_SGE_FL_LAST | MPII_SGE_FL_EOB | MPII_SGE_FL_EOL |
   2404   1.1    bouyer 	    MPII_SGE_FL_SIZE_64 | (page_length * 4) |
   2405   1.1    bouyer 	    (read ? MPII_SGE_FL_DIR_IN : MPII_SGE_FL_DIR_OUT));
   2406   1.1    bouyer 
   2407   1.1    bouyer 	/* bounce the page via the request space to avoid more bus_dma games */
   2408  1.15    bouyer 	mpii_dvatosge(&cq->page_buffer, ccb->ccb_cmd_dva +
   2409  1.15    bouyer 	    sizeof(struct mpii_msg_config_request));
   2410   1.1    bouyer 
   2411  1.15    bouyer 	kva = (uintptr_t)ccb->ccb_cmd;
   2412   1.1    bouyer 	kva += sizeof(struct mpii_msg_config_request);
   2413   1.1    bouyer 
   2414   1.1    bouyer 	if (!read)
   2415  1.15    bouyer 		memcpy((void *)kva, page, len);
   2416   1.1    bouyer 
   2417   1.1    bouyer 	ccb->ccb_done = mpii_empty_done;
   2418   1.1    bouyer 	if (ISSET(flags, MPII_PG_POLL)) {
   2419   1.1    bouyer 		if (mpii_poll(sc, ccb) != 0) {
   2420   1.1    bouyer 			DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header poll\n",
   2421   1.1    bouyer 			    DEVNAME(sc));
   2422   1.1    bouyer 			return (1);
   2423   1.1    bouyer 		}
   2424   1.1    bouyer 	} else
   2425   1.1    bouyer 		mpii_wait(sc, ccb);
   2426   1.1    bouyer 
   2427   1.1    bouyer 	if (ccb->ccb_rcb == NULL) {
   2428   1.1    bouyer 		mpii_put_ccb(sc, ccb);
   2429   1.1    bouyer 		return (1);
   2430   1.1    bouyer 	}
   2431   1.1    bouyer 	cp = ccb->ccb_rcb->rcb_reply;
   2432   1.1    bouyer 
   2433  1.15    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  action: 0x%02x msg_length: %d "
   2434  1.15    bouyer 	    "function: 0x%02x\n", DEVNAME(sc), cp->action, cp->msg_length,
   2435  1.15    bouyer 	    cp->function);
   2436   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ext_page_length: %d ext_page_type: 0x%02x "
   2437   1.1    bouyer 	    "msg_flags: 0x%02x\n", DEVNAME(sc),
   2438   1.1    bouyer 	    le16toh(cp->ext_page_length), cp->ext_page_type,
   2439   1.1    bouyer 	    cp->msg_flags);
   2440   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc),
   2441   1.1    bouyer 	    cp->vp_id, cp->vf_id);
   2442   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
   2443   1.1    bouyer 	    le16toh(cp->ioc_status));
   2444   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
   2445   1.1    bouyer 	    le32toh(cp->ioc_loginfo));
   2446   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  page_version: 0x%02x page_length: %d "
   2447   1.1    bouyer 	    "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc),
   2448   1.1    bouyer 	    cp->config_header.page_version,
   2449   1.1    bouyer 	    cp->config_header.page_length,
   2450   1.1    bouyer 	    cp->config_header.page_number,
   2451   1.1    bouyer 	    cp->config_header.page_type);
   2452  1.15    bouyer 
   2453   1.1    bouyer 	if (le16toh(cp->ioc_status) != MPII_IOCSTATUS_SUCCESS)
   2454   1.1    bouyer 		rv = 1;
   2455   1.1    bouyer 	else if (read)
   2456  1.15    bouyer 		memcpy(page, (void *)kva, len);
   2457   1.1    bouyer 
   2458   1.1    bouyer 	mpii_push_reply(sc, ccb->ccb_rcb);
   2459   1.1    bouyer 	mpii_put_ccb(sc, ccb);
   2460   1.1    bouyer 
   2461   1.1    bouyer 	return (rv);
   2462   1.1    bouyer }
   2463   1.1    bouyer 
   2464  1.15    bouyer struct mpii_rcb *
   2465   1.1    bouyer mpii_reply(struct mpii_softc *sc, struct mpii_reply_descr *rdp)
   2466   1.1    bouyer {
   2467   1.1    bouyer 	struct mpii_rcb		*rcb = NULL;
   2468   1.1    bouyer 	u_int32_t		rfid;
   2469   1.1    bouyer 
   2470  1.15    bouyer 	KASSERT(mutex_owned(&sc->sc_rep_mtx));
   2471   1.1    bouyer 	DNPRINTF(MPII_D_INTR, "%s: mpii_reply\n", DEVNAME(sc));
   2472   1.1    bouyer 
   2473   1.1    bouyer 	if ((rdp->reply_flags & MPII_REPLY_DESCR_TYPE_MASK) ==
   2474   1.1    bouyer 	    MPII_REPLY_DESCR_ADDRESS_REPLY) {
   2475   1.1    bouyer 		rfid = (le32toh(rdp->frame_addr) -
   2476  1.15    bouyer 		    (u_int32_t)MPII_DMA_DVA(sc->sc_replies)) /
   2477  1.15    bouyer 		    sc->sc_reply_size;
   2478   1.1    bouyer 
   2479   1.1    bouyer 		bus_dmamap_sync(sc->sc_dmat,
   2480  1.15    bouyer 		    MPII_DMA_MAP(sc->sc_replies), sc->sc_reply_size * rfid,
   2481  1.15    bouyer 		    sc->sc_reply_size, BUS_DMASYNC_POSTREAD);
   2482   1.1    bouyer 
   2483   1.1    bouyer 		rcb = &sc->sc_rcbs[rfid];
   2484   1.1    bouyer 	}
   2485   1.1    bouyer 
   2486   1.1    bouyer 	memset(rdp, 0xff, sizeof(*rdp));
   2487   1.1    bouyer 
   2488   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq),
   2489   1.1    bouyer 	    8 * sc->sc_reply_post_host_index, 8,
   2490   1.1    bouyer 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
   2491   1.1    bouyer 
   2492   1.1    bouyer 	return (rcb);
   2493   1.1    bouyer }
   2494   1.1    bouyer 
   2495  1.15    bouyer struct mpii_dmamem *
   2496   1.1    bouyer mpii_dmamem_alloc(struct mpii_softc *sc, size_t size)
   2497   1.1    bouyer {
   2498   1.1    bouyer 	struct mpii_dmamem	*mdm;
   2499   1.1    bouyer 	int			nsegs;
   2500   1.1    bouyer 
   2501   1.1    bouyer 	mdm = malloc(sizeof(*mdm), M_DEVBUF, M_NOWAIT | M_ZERO);
   2502   1.1    bouyer 	if (mdm == NULL)
   2503  1.11      maya 		return (NULL);
   2504   1.1    bouyer 
   2505   1.1    bouyer 	mdm->mdm_size = size;
   2506   1.1    bouyer 
   2507   1.1    bouyer 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
   2508   1.1    bouyer 	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mdm->mdm_map) != 0)
   2509   1.1    bouyer 		goto mdmfree;
   2510   1.1    bouyer 
   2511   1.1    bouyer 	if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &mdm->mdm_seg,
   2512  1.15    bouyer 	    1, &nsegs, BUS_DMA_NOWAIT) != 0)
   2513  1.15    bouyer 		goto destroy;
   2514   1.1    bouyer 
   2515   1.1    bouyer 	if (bus_dmamem_map(sc->sc_dmat, &mdm->mdm_seg, nsegs, size,
   2516   1.1    bouyer 	    &mdm->mdm_kva, BUS_DMA_NOWAIT) != 0)
   2517   1.1    bouyer 		goto free;
   2518   1.1    bouyer 
   2519   1.1    bouyer 	if (bus_dmamap_load(sc->sc_dmat, mdm->mdm_map, mdm->mdm_kva, size,
   2520   1.1    bouyer 	    NULL, BUS_DMA_NOWAIT) != 0)
   2521   1.1    bouyer 		goto unmap;
   2522   1.1    bouyer 
   2523  1.15    bouyer 	memset(mdm->mdm_kva, 0, size);
   2524   1.1    bouyer 
   2525   1.1    bouyer 	return (mdm);
   2526   1.1    bouyer 
   2527   1.1    bouyer unmap:
   2528   1.1    bouyer 	bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, size);
   2529   1.1    bouyer free:
   2530   1.1    bouyer 	bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1);
   2531   1.1    bouyer destroy:
   2532   1.1    bouyer 	bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map);
   2533   1.1    bouyer mdmfree:
   2534   1.1    bouyer 	free(mdm, M_DEVBUF);
   2535   1.1    bouyer 
   2536   1.1    bouyer 	return (NULL);
   2537   1.1    bouyer }
   2538   1.1    bouyer 
   2539  1.15    bouyer void
   2540   1.1    bouyer mpii_dmamem_free(struct mpii_softc *sc, struct mpii_dmamem *mdm)
   2541   1.1    bouyer {
   2542   1.1    bouyer 	DNPRINTF(MPII_D_MEM, "%s: mpii_dmamem_free %p\n", DEVNAME(sc), mdm);
   2543   1.1    bouyer 
   2544   1.1    bouyer 	bus_dmamap_unload(sc->sc_dmat, mdm->mdm_map);
   2545   1.1    bouyer 	bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, mdm->mdm_size);
   2546   1.1    bouyer 	bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1);
   2547   1.1    bouyer 	bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map);
   2548   1.1    bouyer 	free(mdm, M_DEVBUF);
   2549   1.1    bouyer }
   2550   1.1    bouyer 
   2551  1.15    bouyer int
   2552   1.1    bouyer mpii_insert_dev(struct mpii_softc *sc, struct mpii_device *dev)
   2553   1.1    bouyer {
   2554  1.15    bouyer 	int		slot;	/* initial hint */
   2555  1.10      maya 
   2556  1.15    bouyer 	KASSERT(mutex_owned(&sc->sc_devs_mtx));
   2557  1.15    bouyer 	DNPRINTF(MPII_D_EVT, "%s: mpii_insert_dev wants slot %d\n",
   2558  1.15    bouyer 	    DEVNAME(sc), dev->slot);
   2559  1.15    bouyer 	if (dev == NULL || dev->slot < 0)
   2560  1.10      maya 		return (1);
   2561  1.15    bouyer 	slot = dev->slot;
   2562   1.1    bouyer 
   2563   1.1    bouyer 	while (slot < sc->sc_max_devices && sc->sc_devs[slot] != NULL)
   2564   1.1    bouyer 		slot++;
   2565  1.15    bouyer 
   2566   1.1    bouyer 	if (slot >= sc->sc_max_devices)
   2567   1.1    bouyer 		return (1);
   2568  1.15    bouyer 
   2569  1.15    bouyer 	DNPRINTF(MPII_D_EVT, "%s: mpii_insert_dev alloc slot %d\n",
   2570  1.15    bouyer 	    DEVNAME(sc), slot);
   2571  1.15    bouyer 
   2572   1.1    bouyer 	dev->slot = slot;
   2573   1.1    bouyer 	sc->sc_devs[slot] = dev;
   2574  1.15    bouyer 
   2575   1.1    bouyer 	return (0);
   2576   1.1    bouyer }
   2577   1.1    bouyer 
   2578  1.15    bouyer int
   2579   1.1    bouyer mpii_remove_dev(struct mpii_softc *sc, struct mpii_device *dev)
   2580   1.1    bouyer {
   2581   1.1    bouyer 	int			i;
   2582   1.1    bouyer 
   2583  1.15    bouyer 	KASSERT(mutex_owned(&sc->sc_devs_mtx));
   2584  1.15    bouyer 	if (dev == NULL)
   2585   1.1    bouyer 		return (1);
   2586  1.15    bouyer 
   2587  1.15    bouyer 	for (i = 0; i < sc->sc_max_devices; i++) {
   2588  1.15    bouyer 		if (sc->sc_devs[i] == NULL)
   2589  1.15    bouyer 			continue;
   2590  1.15    bouyer 
   2591  1.15    bouyer 		if (sc->sc_devs[i]->dev_handle == dev->dev_handle) {
   2592   1.1    bouyer 			sc->sc_devs[i] = NULL;
   2593   1.1    bouyer 			return (0);
   2594   1.1    bouyer 		}
   2595  1.15    bouyer 	}
   2596  1.15    bouyer 
   2597   1.1    bouyer 	return (1);
   2598   1.1    bouyer }
   2599   1.1    bouyer 
   2600  1.15    bouyer struct mpii_device *
   2601   1.1    bouyer mpii_find_dev(struct mpii_softc *sc, u_int16_t handle)
   2602   1.1    bouyer {
   2603   1.1    bouyer 	int			i;
   2604  1.15    bouyer 	KASSERT(mutex_owned(&sc->sc_devs_mtx));
   2605   1.1    bouyer 
   2606  1.15    bouyer 	for (i = 0; i < sc->sc_max_devices; i++) {
   2607  1.15    bouyer 		if (sc->sc_devs[i] == NULL)
   2608  1.15    bouyer 			continue;
   2609  1.15    bouyer 
   2610  1.15    bouyer 		if (sc->sc_devs[i]->dev_handle == handle)
   2611   1.1    bouyer 			return (sc->sc_devs[i]);
   2612  1.15    bouyer 	}
   2613  1.15    bouyer 
   2614   1.1    bouyer 	return (NULL);
   2615   1.1    bouyer }
   2616   1.1    bouyer 
   2617  1.15    bouyer int
   2618   1.1    bouyer mpii_alloc_ccbs(struct mpii_softc *sc)
   2619   1.1    bouyer {
   2620   1.1    bouyer 	struct mpii_ccb		*ccb;
   2621   1.1    bouyer 	u_int8_t		*cmd;
   2622   1.1    bouyer 	int			i;
   2623  1.15    bouyer 	char wqname[16];
   2624   1.1    bouyer 
   2625   1.1    bouyer 	SIMPLEQ_INIT(&sc->sc_ccb_free);
   2626  1.15    bouyer 	SIMPLEQ_INIT(&sc->sc_ccb_tmos);
   2627  1.15    bouyer 	mutex_init(&sc->sc_ccb_free_mtx, MUTEX_DEFAULT, IPL_BIO);
   2628  1.15    bouyer 	cv_init(&sc->sc_ccb_free_cv, "mpii_ccbs");
   2629  1.15    bouyer 	mutex_init(&sc->sc_ssb_tmomtx, MUTEX_DEFAULT, IPL_BIO);
   2630  1.15    bouyer 	snprintf(wqname, sizeof(wqname) - 1, "%sabrt", DEVNAME(sc));
   2631  1.15    bouyer 	workqueue_create(&sc->sc_ssb_tmowk, wqname, mpii_scsi_cmd_tmo_handler,
   2632  1.15    bouyer 	    sc, PRI_BIO, IPL_BIO, WQ_MPSAFE);
   2633  1.15    bouyer 	if (sc->sc_ssb_tmowk == NULL)
   2634  1.15    bouyer 		return 1;
   2635   1.1    bouyer 
   2636  1.15    bouyer 	sc->sc_ccbs = malloc((sc->sc_max_cmds-1) * sizeof(*ccb),
   2637   1.1    bouyer 	    M_DEVBUF, M_NOWAIT | M_ZERO);
   2638   1.1    bouyer 	if (sc->sc_ccbs == NULL) {
   2639   1.1    bouyer 		printf("%s: unable to allocate ccbs\n", DEVNAME(sc));
   2640   1.1    bouyer 		return (1);
   2641   1.1    bouyer 	}
   2642   1.1    bouyer 
   2643   1.1    bouyer 	sc->sc_requests = mpii_dmamem_alloc(sc,
   2644  1.15    bouyer 	    sc->sc_request_size * sc->sc_max_cmds);
   2645   1.1    bouyer 	if (sc->sc_requests == NULL) {
   2646   1.1    bouyer 		printf("%s: unable to allocate ccb dmamem\n", DEVNAME(sc));
   2647   1.1    bouyer 		goto free_ccbs;
   2648   1.1    bouyer 	}
   2649   1.1    bouyer 	cmd = MPII_DMA_KVA(sc->sc_requests);
   2650   1.1    bouyer 
   2651   1.1    bouyer 	/*
   2652  1.15    bouyer 	 * we have sc->sc_max_cmds system request message
   2653   1.1    bouyer 	 * frames, but smid zero cannot be used. so we then
   2654  1.15    bouyer 	 * have (sc->sc_max_cmds - 1) number of ccbs
   2655   1.1    bouyer 	 */
   2656  1.15    bouyer 	for (i = 1; i < sc->sc_max_cmds; i++) {
   2657   1.1    bouyer 		ccb = &sc->sc_ccbs[i - 1];
   2658   1.1    bouyer 
   2659  1.15    bouyer 		if (bus_dmamap_create(sc->sc_dmat, MAXPHYS, sc->sc_max_sgl,
   2660  1.15    bouyer 		    MAXPHYS, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
   2661   1.1    bouyer 		    &ccb->ccb_dmamap) != 0) {
   2662   1.1    bouyer 			printf("%s: unable to create dma map\n", DEVNAME(sc));
   2663   1.1    bouyer 			goto free_maps;
   2664   1.1    bouyer 		}
   2665   1.1    bouyer 
   2666   1.1    bouyer 		ccb->ccb_sc = sc;
   2667  1.15    bouyer 		mutex_init(&ccb->ccb_mtx, MUTEX_DEFAULT, IPL_BIO);
   2668  1.15    bouyer 		cv_init(&ccb->ccb_cv, "mpiiexec");
   2669  1.15    bouyer 
   2670  1.15    bouyer 		ccb->ccb_smid = htole16(i);
   2671  1.15    bouyer 		ccb->ccb_offset = sc->sc_request_size * i;
   2672   1.1    bouyer 
   2673   1.1    bouyer 		ccb->ccb_cmd = &cmd[ccb->ccb_offset];
   2674   1.1    bouyer 		ccb->ccb_cmd_dva = (u_int32_t)MPII_DMA_DVA(sc->sc_requests) +
   2675   1.1    bouyer 		    ccb->ccb_offset;
   2676   1.1    bouyer 
   2677   1.1    bouyer 		DNPRINTF(MPII_D_CCB, "%s: mpii_alloc_ccbs(%d) ccb: %p map: %p "
   2678  1.15    bouyer 		    "sc: %p smid: %#x offs: %#lx cmd: %p dva: %#lx\n",
   2679   1.1    bouyer 		    DEVNAME(sc), i, ccb, ccb->ccb_dmamap, ccb->ccb_sc,
   2680  1.15    bouyer 		    ccb->ccb_smid, ccb->ccb_offset, ccb->ccb_cmd,
   2681  1.15    bouyer 		    ccb->ccb_cmd_dva);
   2682   1.1    bouyer 
   2683   1.1    bouyer 		mpii_put_ccb(sc, ccb);
   2684   1.1    bouyer 	}
   2685   1.1    bouyer 
   2686   1.1    bouyer 	return (0);
   2687   1.1    bouyer 
   2688   1.1    bouyer free_maps:
   2689  1.15    bouyer 	while ((ccb = mpii_get_ccb(sc)) != NULL)
   2690   1.1    bouyer 		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
   2691   1.1    bouyer 
   2692   1.1    bouyer 	mpii_dmamem_free(sc, sc->sc_requests);
   2693   1.1    bouyer free_ccbs:
   2694   1.1    bouyer 	free(sc->sc_ccbs, M_DEVBUF);
   2695   1.1    bouyer 
   2696   1.1    bouyer 	return (1);
   2697   1.1    bouyer }
   2698   1.1    bouyer 
   2699  1.15    bouyer void
   2700   1.1    bouyer mpii_put_ccb(struct mpii_softc *sc, struct mpii_ccb *ccb)
   2701   1.1    bouyer {
   2702   1.1    bouyer 	DNPRINTF(MPII_D_CCB, "%s: mpii_put_ccb %p\n", DEVNAME(sc), ccb);
   2703   1.1    bouyer 
   2704   1.1    bouyer 	ccb->ccb_state = MPII_CCB_FREE;
   2705   1.1    bouyer 	ccb->ccb_cookie = NULL;
   2706   1.1    bouyer 	ccb->ccb_done = NULL;
   2707   1.1    bouyer 	ccb->ccb_rcb = NULL;
   2708  1.15    bouyer 	memset(ccb->ccb_cmd, 0, sc->sc_request_size);
   2709   1.1    bouyer 
   2710   1.1    bouyer 	mutex_enter(&sc->sc_ccb_free_mtx);
   2711  1.15    bouyer 	SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ccb, ccb_link);
   2712   1.1    bouyer 	mutex_exit(&sc->sc_ccb_free_mtx);
   2713   1.1    bouyer }
   2714   1.1    bouyer 
   2715  1.15    bouyer struct mpii_ccb *
   2716  1.15    bouyer mpii_get_ccb(struct mpii_softc *sc)
   2717   1.1    bouyer {
   2718   1.1    bouyer 	struct mpii_ccb		*ccb;
   2719   1.1    bouyer 
   2720   1.1    bouyer 	mutex_enter(&sc->sc_ccb_free_mtx);
   2721  1.15    bouyer 	ccb = SIMPLEQ_FIRST(&sc->sc_ccb_free);
   2722   1.1    bouyer 	if (ccb != NULL) {
   2723  1.15    bouyer 		SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ccb_link);
   2724   1.1    bouyer 		ccb->ccb_state = MPII_CCB_READY;
   2725   1.1    bouyer 		KASSERT(ccb->ccb_sc == sc);
   2726   1.1    bouyer 	}
   2727   1.1    bouyer 	mutex_exit(&sc->sc_ccb_free_mtx);
   2728   1.1    bouyer 
   2729   1.1    bouyer 	DNPRINTF(MPII_D_CCB, "%s: mpii_get_ccb %p\n", DEVNAME(sc), ccb);
   2730   1.1    bouyer 
   2731   1.1    bouyer 	return (ccb);
   2732   1.1    bouyer }
   2733   1.1    bouyer 
   2734  1.15    bouyer int
   2735   1.1    bouyer mpii_alloc_replies(struct mpii_softc *sc)
   2736   1.1    bouyer {
   2737   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_alloc_replies\n", DEVNAME(sc));
   2738   1.1    bouyer 
   2739   1.1    bouyer 	sc->sc_rcbs = malloc(sc->sc_num_reply_frames * sizeof(struct mpii_rcb),
   2740   1.1    bouyer 	    M_DEVBUF, M_NOWAIT);
   2741   1.1    bouyer 	if (sc->sc_rcbs == NULL)
   2742   1.1    bouyer 		return (1);
   2743   1.1    bouyer 
   2744  1.15    bouyer 	sc->sc_replies = mpii_dmamem_alloc(sc, sc->sc_reply_size *
   2745   1.1    bouyer 	    sc->sc_num_reply_frames);
   2746   1.1    bouyer 	if (sc->sc_replies == NULL) {
   2747   1.1    bouyer 		free(sc->sc_rcbs, M_DEVBUF);
   2748   1.1    bouyer 		return (1);
   2749   1.1    bouyer 	}
   2750   1.1    bouyer 
   2751   1.1    bouyer 	return (0);
   2752   1.1    bouyer }
   2753   1.1    bouyer 
   2754  1.15    bouyer void
   2755   1.1    bouyer mpii_push_replies(struct mpii_softc *sc)
   2756   1.1    bouyer {
   2757   1.1    bouyer 	struct mpii_rcb		*rcb;
   2758  1.15    bouyer 	uintptr_t		kva = (uintptr_t)MPII_DMA_KVA(sc->sc_replies);
   2759   1.1    bouyer 	int			i;
   2760   1.1    bouyer 
   2761   1.1    bouyer 	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_replies),
   2762  1.15    bouyer 	    0, sc->sc_reply_size * sc->sc_num_reply_frames,
   2763  1.15    bouyer 	    BUS_DMASYNC_PREREAD);
   2764   1.1    bouyer 
   2765   1.1    bouyer 	for (i = 0; i < sc->sc_num_reply_frames; i++) {
   2766   1.1    bouyer 		rcb = &sc->sc_rcbs[i];
   2767   1.1    bouyer 
   2768  1.15    bouyer 		rcb->rcb_reply = (void *)(kva + sc->sc_reply_size * i);
   2769   1.1    bouyer 		rcb->rcb_reply_dva = (u_int32_t)MPII_DMA_DVA(sc->sc_replies) +
   2770  1.15    bouyer 		    sc->sc_reply_size * i;
   2771   1.1    bouyer 		mpii_push_reply(sc, rcb);
   2772   1.1    bouyer 	}
   2773   1.1    bouyer }
   2774   1.1    bouyer 
   2775  1.15    bouyer void
   2776   1.1    bouyer mpii_start(struct mpii_softc *sc, struct mpii_ccb *ccb)
   2777   1.1    bouyer {
   2778   1.1    bouyer 	struct mpii_request_header	*rhp;
   2779   1.1    bouyer 	struct mpii_request_descr	descr;
   2780  1.15    bouyer #if defined(__LP64__) && 0
   2781  1.15    bouyer 	u_long				 *rdp = (u_long *)&descr;
   2782  1.15    bouyer #else
   2783  1.15    bouyer 	u_int32_t			 *rdp = (u_int32_t *)&descr;
   2784  1.15    bouyer #endif
   2785  1.15    bouyer 
   2786  1.15    bouyer 	DNPRINTF(MPII_D_RW, "%s: mpii_start %#lx\n", DEVNAME(sc),
   2787  1.15    bouyer 	    ccb->ccb_cmd_dva);
   2788   1.1    bouyer 
   2789  1.15    bouyer 	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_requests),
   2790  1.15    bouyer 	    ccb->ccb_offset, sc->sc_request_size,
   2791  1.15    bouyer 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
   2792  1.15    bouyer 
   2793  1.15    bouyer 	ccb->ccb_state = MPII_CCB_QUEUED;
   2794   1.1    bouyer 
   2795   1.1    bouyer 	rhp = ccb->ccb_cmd;
   2796   1.1    bouyer 
   2797  1.15    bouyer 	memset(&descr, 0, sizeof(descr));
   2798   1.1    bouyer 
   2799   1.1    bouyer 	switch (rhp->function) {
   2800   1.1    bouyer 	case MPII_FUNCTION_SCSI_IO_REQUEST:
   2801   1.1    bouyer 		descr.request_flags = MPII_REQ_DESCR_SCSI_IO;
   2802   1.1    bouyer 		descr.dev_handle = htole16(ccb->ccb_dev_handle);
   2803   1.1    bouyer 		break;
   2804   1.1    bouyer 	case MPII_FUNCTION_SCSI_TASK_MGMT:
   2805   1.1    bouyer 		descr.request_flags = MPII_REQ_DESCR_HIGH_PRIORITY;
   2806   1.1    bouyer 		break;
   2807   1.1    bouyer 	default:
   2808   1.1    bouyer 		descr.request_flags = MPII_REQ_DESCR_DEFAULT;
   2809   1.1    bouyer 	}
   2810   1.1    bouyer 
   2811   1.1    bouyer 	descr.vf_id = sc->sc_vf_id;
   2812  1.15    bouyer 	descr.smid = ccb->ccb_smid;
   2813   1.1    bouyer 
   2814  1.15    bouyer #if defined(__LP64__) && 0
   2815  1.15    bouyer 	DNPRINTF(MPII_D_RW, "%s:   MPII_REQ_DESCR_POST_LOW (0x%08x) write "
   2816  1.15    bouyer 	    "0x%08lx\n", DEVNAME(sc), MPII_REQ_DESCR_POST_LOW, *rdp);
   2817  1.15    bouyer 	bus_space_write_raw_8(sc->sc_iot, sc->sc_ioh,
   2818  1.15    bouyer 	    MPII_REQ_DESCR_POST_LOW, *rdp);
   2819  1.15    bouyer #else
   2820   1.1    bouyer 	DNPRINTF(MPII_D_RW, "%s:   MPII_REQ_DESCR_POST_LOW (0x%08x) write "
   2821  1.15    bouyer 	    "0x%04x\n", DEVNAME(sc), MPII_REQ_DESCR_POST_LOW, *rdp);
   2822   1.1    bouyer 
   2823   1.1    bouyer 	DNPRINTF(MPII_D_RW, "%s:   MPII_REQ_DESCR_POST_HIGH (0x%08x) write "
   2824  1.15    bouyer 	    "0x%04x\n", DEVNAME(sc), MPII_REQ_DESCR_POST_HIGH, *(rdp+1));
   2825   1.1    bouyer 
   2826   1.1    bouyer 	mutex_enter(&sc->sc_req_mtx);
   2827  1.15    bouyer 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
   2828  1.15    bouyer 	    MPII_REQ_DESCR_POST_LOW, rdp[0]);
   2829  1.15    bouyer 	bus_space_barrier(sc->sc_iot, sc->sc_ioh,
   2830  1.15    bouyer 	    MPII_REQ_DESCR_POST_LOW, 8, BUS_SPACE_BARRIER_WRITE);
   2831  1.15    bouyer 
   2832  1.15    bouyer 	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
   2833  1.15    bouyer 	    MPII_REQ_DESCR_POST_HIGH, rdp[1]);
   2834  1.15    bouyer 	bus_space_barrier(sc->sc_iot, sc->sc_ioh,
   2835  1.15    bouyer 	    MPII_REQ_DESCR_POST_LOW, 8, BUS_SPACE_BARRIER_WRITE);
   2836   1.1    bouyer 	mutex_exit(&sc->sc_req_mtx);
   2837  1.15    bouyer #endif
   2838   1.1    bouyer }
   2839   1.1    bouyer 
   2840  1.15    bouyer int
   2841   1.1    bouyer mpii_poll(struct mpii_softc *sc, struct mpii_ccb *ccb)
   2842   1.1    bouyer {
   2843   1.1    bouyer 	void				(*done)(struct mpii_ccb *);
   2844   1.1    bouyer 	void				*cookie;
   2845   1.1    bouyer 	int				rv = 1;
   2846   1.1    bouyer 
   2847  1.15    bouyer 	DNPRINTF(MPII_D_INTR, "%s: mpii_poll\n", DEVNAME(sc));
   2848   1.1    bouyer 
   2849   1.1    bouyer 	done = ccb->ccb_done;
   2850   1.1    bouyer 	cookie = ccb->ccb_cookie;
   2851   1.1    bouyer 
   2852   1.1    bouyer 	ccb->ccb_done = mpii_poll_done;
   2853   1.1    bouyer 	ccb->ccb_cookie = &rv;
   2854   1.1    bouyer 
   2855   1.1    bouyer 	mpii_start(sc, ccb);
   2856   1.1    bouyer 
   2857   1.1    bouyer 	while (rv == 1) {
   2858   1.1    bouyer 		/* avoid excessive polling */
   2859   1.1    bouyer 		if (mpii_reply_waiting(sc))
   2860   1.1    bouyer 			mpii_intr(sc);
   2861   1.1    bouyer 		else
   2862   1.1    bouyer 			delay(10);
   2863   1.1    bouyer 	}
   2864   1.1    bouyer 
   2865   1.1    bouyer 	ccb->ccb_cookie = cookie;
   2866   1.1    bouyer 	done(ccb);
   2867   1.1    bouyer 
   2868   1.1    bouyer 	return (0);
   2869   1.1    bouyer }
   2870   1.1    bouyer 
   2871  1.15    bouyer void
   2872   1.1    bouyer mpii_poll_done(struct mpii_ccb *ccb)
   2873   1.1    bouyer {
   2874   1.1    bouyer 	int				*rv = ccb->ccb_cookie;
   2875   1.1    bouyer 
   2876   1.1    bouyer 	*rv = 0;
   2877   1.1    bouyer }
   2878   1.1    bouyer 
   2879  1.15    bouyer int
   2880   1.1    bouyer mpii_alloc_queues(struct mpii_softc *sc)
   2881   1.1    bouyer {
   2882  1.15    bouyer 	u_int32_t		*rfp;
   2883   1.1    bouyer 	int			i;
   2884  1.15    bouyer 
   2885   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_alloc_queues\n", DEVNAME(sc));
   2886   1.1    bouyer 
   2887  1.15    bouyer 	mutex_init(&sc->sc_reply_free_mtx, MUTEX_DEFAULT, IPL_BIO);
   2888   1.1    bouyer 	sc->sc_reply_freeq = mpii_dmamem_alloc(sc,
   2889  1.15    bouyer 	    sc->sc_reply_free_qdepth * sizeof(*rfp));
   2890   1.1    bouyer 	if (sc->sc_reply_freeq == NULL)
   2891   1.1    bouyer 		return (1);
   2892  1.15    bouyer 	rfp = MPII_DMA_KVA(sc->sc_reply_freeq);
   2893   1.1    bouyer 	for (i = 0; i < sc->sc_num_reply_frames; i++) {
   2894  1.15    bouyer 		rfp[i] = (u_int32_t)MPII_DMA_DVA(sc->sc_replies) +
   2895  1.15    bouyer 		    sc->sc_reply_size * i;
   2896   1.1    bouyer 	}
   2897   1.1    bouyer 
   2898  1.15    bouyer 	sc->sc_reply_postq = mpii_dmamem_alloc(sc,
   2899  1.15    bouyer 	    sc->sc_reply_post_qdepth * sizeof(struct mpii_reply_descr));
   2900   1.1    bouyer 	if (sc->sc_reply_postq == NULL)
   2901   1.1    bouyer 		goto free_reply_freeq;
   2902   1.1    bouyer 	sc->sc_reply_postq_kva = MPII_DMA_KVA(sc->sc_reply_postq);
   2903  1.15    bouyer 	memset(sc->sc_reply_postq_kva, 0xff, sc->sc_reply_post_qdepth *
   2904  1.15    bouyer 	    sizeof(struct mpii_reply_descr));
   2905   1.1    bouyer 
   2906   1.1    bouyer 	return (0);
   2907   1.1    bouyer 
   2908   1.1    bouyer free_reply_freeq:
   2909   1.1    bouyer 	mpii_dmamem_free(sc, sc->sc_reply_freeq);
   2910   1.1    bouyer 	return (1);
   2911   1.1    bouyer }
   2912   1.1    bouyer 
   2913  1.15    bouyer void
   2914   1.1    bouyer mpii_init_queues(struct mpii_softc *sc)
   2915   1.1    bouyer {
   2916   1.1    bouyer 	DNPRINTF(MPII_D_MISC, "%s:  mpii_init_queues\n", DEVNAME(sc));
   2917   1.1    bouyer 
   2918   1.1    bouyer 	sc->sc_reply_free_host_index = sc->sc_reply_free_qdepth - 1;
   2919   1.1    bouyer 	sc->sc_reply_post_host_index = 0;
   2920   1.1    bouyer 	mpii_write_reply_free(sc, sc->sc_reply_free_host_index);
   2921   1.1    bouyer 	mpii_write_reply_post(sc, sc->sc_reply_post_host_index);
   2922   1.1    bouyer }
   2923   1.1    bouyer 
   2924  1.15    bouyer void
   2925   1.1    bouyer mpii_wait(struct mpii_softc *sc, struct mpii_ccb *ccb)
   2926   1.1    bouyer {
   2927   1.1    bouyer 	void			(*done)(struct mpii_ccb *);
   2928   1.1    bouyer 	void			*cookie;
   2929   1.1    bouyer 
   2930   1.1    bouyer 	done = ccb->ccb_done;
   2931   1.1    bouyer 	cookie = ccb->ccb_cookie;
   2932   1.1    bouyer 
   2933   1.1    bouyer 	ccb->ccb_done = mpii_wait_done;
   2934  1.15    bouyer 	ccb->ccb_cookie = ccb;
   2935   1.1    bouyer 
   2936   1.1    bouyer 	/* XXX this will wait forever for the ccb to complete */
   2937   1.1    bouyer 
   2938   1.1    bouyer 	mpii_start(sc, ccb);
   2939   1.1    bouyer 
   2940  1.15    bouyer 	mutex_enter(&ccb->ccb_mtx);
   2941  1.15    bouyer 	while (ccb->ccb_cookie != NULL)
   2942  1.15    bouyer 		cv_wait(&ccb->ccb_cv, &ccb->ccb_mtx);
   2943  1.15    bouyer 	mutex_exit(&ccb->ccb_mtx);
   2944   1.1    bouyer 
   2945   1.1    bouyer 	ccb->ccb_cookie = cookie;
   2946   1.1    bouyer 	done(ccb);
   2947   1.1    bouyer }
   2948   1.1    bouyer 
   2949  1.15    bouyer void
   2950   1.1    bouyer mpii_wait_done(struct mpii_ccb *ccb)
   2951   1.1    bouyer {
   2952  1.15    bouyer 	mutex_enter(&ccb->ccb_mtx);
   2953   1.1    bouyer 	ccb->ccb_cookie = NULL;
   2954  1.15    bouyer 	cv_signal(&ccb->ccb_cv);
   2955  1.15    bouyer 	mutex_exit(&ccb->ccb_mtx);
   2956   1.1    bouyer }
   2957   1.1    bouyer 
   2958  1.15    bouyer void
   2959   1.1    bouyer mpii_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
   2960   1.1    bouyer     void *arg)
   2961   1.1    bouyer {
   2962   1.1    bouyer 	struct scsipi_periph	*periph;
   2963   1.1    bouyer 	struct scsipi_xfer	*xs;
   2964   1.1    bouyer 	struct scsipi_adapter	*adapt = chan->chan_adapter;
   2965   1.1    bouyer 	struct mpii_softc	*sc = device_private(adapt->adapt_dev);
   2966   1.1    bouyer 	struct mpii_ccb		*ccb;
   2967   1.1    bouyer 	struct mpii_msg_scsi_io	*io;
   2968   1.1    bouyer 	struct mpii_device	*dev;
   2969  1.15    bouyer 	int			target, timeout, ret;
   2970  1.15    bouyer 	u_int16_t		dev_handle;
   2971   1.1    bouyer 
   2972   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s: mpii_scsipi_request\n", DEVNAME(sc));
   2973  1.15    bouyer 
   2974   1.1    bouyer 	switch (req) {
   2975   1.1    bouyer 	case ADAPTER_REQ_GROW_RESOURCES:
   2976  1.15    bouyer 		/* Not supported. */
   2977   1.1    bouyer 		return;
   2978   1.1    bouyer 	case ADAPTER_REQ_SET_XFER_MODE:
   2979   1.1    bouyer 	{
   2980   1.1    bouyer 		struct scsipi_xfer_mode *xm = arg;
   2981   1.1    bouyer 		xm->xm_mode = PERIPH_CAP_TQING;
   2982  1.15    bouyer 		xm->xm_period = 0;
   2983  1.15    bouyer 		xm->xm_offset = 0;
   2984   1.1    bouyer 		scsipi_async_event(&sc->sc_chan, ASYNC_EVENT_XFER_MODE, xm);
   2985   1.1    bouyer 		return;
   2986   1.1    bouyer 	}
   2987  1.15    bouyer 	case ADAPTER_REQ_RUN_XFER:
   2988   1.1    bouyer 		break;
   2989   1.1    bouyer 	}
   2990   1.1    bouyer 
   2991   1.1    bouyer 	xs = arg;
   2992   1.1    bouyer 	periph = xs->xs_periph;
   2993   1.1    bouyer 	target = periph->periph_target;
   2994   1.1    bouyer 
   2995   1.1    bouyer 	if (xs->cmdlen > MPII_CDB_LEN) {
   2996  1.15    bouyer 		DNPRINTF(MPII_D_CMD, "%s: CDB too big %d\n",
   2997   1.1    bouyer 		    DEVNAME(sc), xs->cmdlen);
   2998  1.15    bouyer 		memset(&xs->sense, 0, sizeof(xs->sense));
   2999   1.1    bouyer 		xs->sense.scsi_sense.response_code =
   3000   1.1    bouyer 		    SSD_RCODE_VALID | SSD_RCODE_CURRENT;
   3001   1.1    bouyer 		xs->sense.scsi_sense.flags = SKEY_ILLEGAL_REQUEST;
   3002   1.1    bouyer 		xs->sense.scsi_sense.asc = 0x20;
   3003   1.1    bouyer 		xs->error = XS_SENSE;
   3004   1.1    bouyer 		scsipi_done(xs);
   3005   1.1    bouyer 		return;
   3006   1.1    bouyer 	}
   3007   1.1    bouyer 
   3008  1.15    bouyer 	mutex_enter(&sc->sc_devs_mtx);
   3009   1.1    bouyer 	if ((dev = sc->sc_devs[target]) == NULL) {
   3010  1.15    bouyer 		mutex_exit(&sc->sc_devs_mtx);
   3011   1.1    bouyer 		/* device no longer exists */
   3012   1.1    bouyer 		xs->error = XS_SELTIMEOUT;
   3013   1.1    bouyer 		scsipi_done(xs);
   3014   1.1    bouyer 		return;
   3015   1.1    bouyer 	}
   3016  1.15    bouyer 	dev_handle = dev->dev_handle;
   3017  1.15    bouyer 	mutex_exit(&sc->sc_devs_mtx);
   3018   1.1    bouyer 
   3019  1.15    bouyer 	ccb = mpii_get_ccb(sc);
   3020   1.1    bouyer 	if (ccb == NULL) {
   3021   1.1    bouyer 		xs->error = XS_RESOURCE_SHORTAGE;
   3022   1.1    bouyer 		scsipi_done(xs);
   3023   1.1    bouyer 		return;
   3024   1.1    bouyer 	}
   3025   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s: ccb_smid: %d xs->xs_control: 0x%x\n",
   3026   1.1    bouyer 	    DEVNAME(sc), ccb->ccb_smid, xs->xs_control);
   3027   1.1    bouyer 
   3028   1.1    bouyer 	ccb->ccb_cookie = xs;
   3029   1.1    bouyer 	ccb->ccb_done = mpii_scsi_cmd_done;
   3030  1.15    bouyer 	ccb->ccb_dev_handle = dev_handle;
   3031   1.1    bouyer 
   3032  1.15    bouyer 	io = ccb->ccb_cmd;
   3033  1.15    bouyer 	memset(io, 0, sizeof(*io));
   3034   1.1    bouyer 	io->function = MPII_FUNCTION_SCSI_IO_REQUEST;
   3035   1.1    bouyer 	io->sense_buffer_length = sizeof(xs->sense);
   3036  1.15    bouyer 	io->sgl_offset0 = sizeof(struct mpii_msg_scsi_io) / 4;
   3037   1.1    bouyer 	io->io_flags = htole16(xs->cmdlen);
   3038   1.1    bouyer 	io->dev_handle = htole16(ccb->ccb_dev_handle);
   3039  1.15    bouyer 	io->lun[0] = htole16(periph->periph_lun);
   3040   1.1    bouyer 
   3041   1.1    bouyer 	switch (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
   3042   1.1    bouyer 	case XS_CTL_DATA_IN:
   3043   1.1    bouyer 		io->direction = MPII_SCSIIO_DIR_READ;
   3044   1.1    bouyer 		break;
   3045   1.1    bouyer 	case XS_CTL_DATA_OUT:
   3046   1.1    bouyer 		io->direction = MPII_SCSIIO_DIR_WRITE;
   3047   1.1    bouyer 		break;
   3048   1.1    bouyer 	default:
   3049   1.1    bouyer 		io->direction = MPII_SCSIIO_DIR_NONE;
   3050  1.15    bouyer 		break;
   3051   1.1    bouyer 	}
   3052   1.1    bouyer 
   3053   1.1    bouyer 	io->tagging = MPII_SCSIIO_ATTR_SIMPLE_Q;
   3054   1.1    bouyer 
   3055   1.1    bouyer 	memcpy(io->cdb, xs->cmd, xs->cmdlen);
   3056   1.1    bouyer 
   3057   1.1    bouyer 	io->data_length = htole32(xs->datalen);
   3058   1.1    bouyer 
   3059  1.15    bouyer 	/* sense data is at the end of a request */
   3060   1.1    bouyer 	io->sense_buffer_low_address = htole32(ccb->ccb_cmd_dva +
   3061  1.15    bouyer 	    sc->sc_request_size - sizeof(struct scsi_sense_data));
   3062  1.15    bouyer 
   3063  1.15    bouyer 	if (ISSET(sc->sc_flags, MPII_F_SAS3))
   3064  1.15    bouyer 		ret = mpii_load_xs_sas3(ccb);
   3065  1.15    bouyer 	else
   3066  1.15    bouyer 		ret = mpii_load_xs(ccb);
   3067   1.1    bouyer 
   3068  1.15    bouyer 	if (ret != 0) {
   3069   1.1    bouyer 		xs->error = XS_DRIVER_STUFFUP;
   3070  1.15    bouyer 		goto done;
   3071   1.1    bouyer 	}
   3072   1.1    bouyer 
   3073   1.1    bouyer 	if (xs->xs_control & XS_CTL_POLL) {
   3074   1.1    bouyer 		if (mpii_poll(sc, ccb) != 0) {
   3075   1.1    bouyer 			xs->error = XS_DRIVER_STUFFUP;
   3076  1.15    bouyer 			goto done;
   3077   1.1    bouyer 		}
   3078   1.1    bouyer 		return;
   3079   1.1    bouyer 	}
   3080  1.15    bouyer         timeout = mstohz(xs->timeout);
   3081   1.1    bouyer 	if (timeout == 0)
   3082   1.1    bouyer 		timeout = 1;
   3083   1.1    bouyer 	callout_reset(&xs->xs_callout, timeout, mpii_scsi_cmd_tmo, ccb);
   3084   1.1    bouyer 	mpii_start(sc, ccb);
   3085  1.15    bouyer 	return;
   3086  1.15    bouyer done:
   3087  1.15    bouyer 	mpii_put_ccb(sc, ccb);
   3088  1.15    bouyer 	scsipi_done(xs);
   3089   1.1    bouyer }
   3090   1.1    bouyer 
   3091  1.15    bouyer void
   3092   1.1    bouyer mpii_scsi_cmd_tmo(void *xccb)
   3093   1.1    bouyer {
   3094   1.1    bouyer 	struct mpii_ccb		*ccb = xccb;
   3095   1.1    bouyer 	struct mpii_softc	*sc = ccb->ccb_sc;
   3096  1.15    bouyer 	bool	start_work;
   3097   1.1    bouyer 
   3098   1.1    bouyer 	printf("%s: mpii_scsi_cmd_tmo\n", DEVNAME(sc));
   3099   1.1    bouyer 
   3100   1.1    bouyer 	if (ccb->ccb_state == MPII_CCB_QUEUED) {
   3101  1.15    bouyer 		mutex_enter(&sc->sc_ssb_tmomtx);
   3102  1.15    bouyer 		start_work = (SIMPLEQ_FIRST(&sc->sc_ccb_tmos) == 0);
   3103   1.1    bouyer 		ccb->ccb_state = MPII_CCB_TIMEOUT;
   3104  1.15    bouyer 		SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_tmos, ccb, ccb_link);
   3105  1.15    bouyer 		if (start_work) {
   3106  1.15    bouyer 			workqueue_enqueue(sc->sc_ssb_tmowk,
   3107  1.15    bouyer 			    &sc->sc_ssb_tmowork, NULL);
   3108  1.15    bouyer 		}
   3109  1.15    bouyer 		mutex_exit(&sc->sc_ssb_tmomtx);
   3110   1.1    bouyer 	}
   3111   1.1    bouyer }
   3112   1.1    bouyer 
   3113  1.15    bouyer void
   3114   1.1    bouyer mpii_scsi_cmd_tmo_handler(struct work *wk, void *cookie)
   3115   1.1    bouyer {
   3116   1.1    bouyer 	struct mpii_softc			*sc = cookie;
   3117  1.15    bouyer 	struct mpii_ccb				*next;
   3118  1.15    bouyer 	struct mpii_ccb				*ccb;
   3119   1.1    bouyer 	struct mpii_ccb				*tccb;
   3120   1.1    bouyer 	struct mpii_msg_scsi_task_request	*stq;
   3121   1.1    bouyer 
   3122  1.15    bouyer 	mutex_enter(&sc->sc_ssb_tmomtx);
   3123  1.15    bouyer 	next = SIMPLEQ_FIRST(&sc->sc_ccb_tmos);
   3124  1.15    bouyer 	SIMPLEQ_INIT(&sc->sc_ccb_tmos);
   3125  1.15    bouyer 	mutex_exit(&sc->sc_ssb_tmomtx);
   3126  1.15    bouyer 
   3127  1.15    bouyer 	while (next != NULL) {
   3128  1.15    bouyer 		ccb = next;
   3129  1.15    bouyer 		next = SIMPLEQ_NEXT(ccb, ccb_link);
   3130  1.15    bouyer 		if (ccb->ccb_state != MPII_CCB_TIMEOUT)
   3131  1.15    bouyer 			continue;
   3132  1.15    bouyer 		tccb = mpii_get_ccb(sc);
   3133  1.15    bouyer 		stq = tccb->ccb_cmd;
   3134  1.15    bouyer 		stq->function = MPII_FUNCTION_SCSI_TASK_MGMT;
   3135  1.15    bouyer 		stq->task_type = MPII_SCSI_TASK_TARGET_RESET;
   3136  1.15    bouyer 		stq->dev_handle = htole16(ccb->ccb_dev_handle);
   3137   1.1    bouyer 
   3138  1.15    bouyer 		tccb->ccb_done = mpii_scsi_cmd_tmo_done;
   3139  1.15    bouyer 		mpii_wait(sc, tccb);
   3140   1.1    bouyer 	}
   3141   1.1    bouyer }
   3142   1.1    bouyer 
   3143  1.15    bouyer void
   3144   1.1    bouyer mpii_scsi_cmd_tmo_done(struct mpii_ccb *tccb)
   3145   1.1    bouyer {
   3146  1.15    bouyer 	mpii_put_ccb(tccb->ccb_sc, tccb);
   3147   1.1    bouyer }
   3148   1.1    bouyer 
   3149   1.3    kardel static u_int8_t
   3150   1.3    kardel map_scsi_status(u_int8_t mpii_scsi_status)
   3151   1.3    kardel {
   3152   1.3    kardel 	u_int8_t scsi_status;
   3153   1.3    kardel 
   3154   1.3    kardel 	switch (mpii_scsi_status)
   3155   1.3    kardel 	{
   3156  1.15    bouyer 	case MPII_SCSIIO_STATUS_GOOD:
   3157   1.3    kardel 		scsi_status = SCSI_OK;
   3158   1.3    kardel 		break;
   3159   1.3    kardel 
   3160  1.15    bouyer 	case MPII_SCSIIO_STATUS_CHECK_COND:
   3161   1.3    kardel 		scsi_status = SCSI_CHECK;
   3162   1.3    kardel 		break;
   3163   1.3    kardel 
   3164  1.15    bouyer 	case MPII_SCSIIO_STATUS_BUSY:
   3165   1.3    kardel 		scsi_status = SCSI_BUSY;
   3166   1.3    kardel 		break;
   3167   1.3    kardel 
   3168  1.15    bouyer 	case MPII_SCSIIO_STATUS_INTERMEDIATE:
   3169   1.3    kardel 		scsi_status = SCSI_INTERM;
   3170   1.3    kardel 		break;
   3171   1.3    kardel 
   3172  1.15    bouyer 	case MPII_SCSIIO_STATUS_INTERMEDIATE_CONDMET:
   3173   1.3    kardel 		scsi_status = SCSI_INTERM;
   3174   1.3    kardel 		break;
   3175   1.3    kardel 
   3176  1.15    bouyer 	case MPII_SCSIIO_STATUS_RESERVATION_CONFLICT:
   3177   1.3    kardel 		scsi_status = SCSI_RESV_CONFLICT;
   3178   1.3    kardel 		break;
   3179   1.3    kardel 
   3180  1.15    bouyer 	case MPII_SCSIIO_STATUS_CMD_TERM:
   3181  1.15    bouyer 	case MPII_SCSIIO_STATUS_TASK_ABORTED:
   3182   1.3    kardel 		scsi_status = SCSI_TERMINATED;
   3183   1.3    kardel 		break;
   3184   1.3    kardel 
   3185  1.15    bouyer 	case MPII_SCSIIO_STATUS_TASK_SET_FULL:
   3186   1.3    kardel 		scsi_status = SCSI_QUEUE_FULL;
   3187   1.3    kardel 		break;
   3188   1.3    kardel 
   3189  1.15    bouyer 	case MPII_SCSIIO_STATUS_ACA_ACTIVE:
   3190   1.3    kardel 		scsi_status = SCSI_ACA_ACTIVE;
   3191   1.3    kardel 		break;
   3192   1.3    kardel 
   3193   1.3    kardel 	default:
   3194   1.3    kardel 		/* XXX: for the lack of anything better and other than OK */
   3195   1.3    kardel 		scsi_status = 0xFF;
   3196   1.3    kardel 		break;
   3197   1.3    kardel 	}
   3198   1.3    kardel 
   3199   1.3    kardel 	return scsi_status;
   3200   1.3    kardel }
   3201   1.1    bouyer 
   3202  1.15    bouyer void
   3203   1.1    bouyer mpii_scsi_cmd_done(struct mpii_ccb *ccb)
   3204   1.1    bouyer {
   3205   1.1    bouyer 	struct mpii_msg_scsi_io_error	*sie;
   3206   1.1    bouyer 	struct mpii_softc	*sc = ccb->ccb_sc;
   3207   1.1    bouyer 	struct scsipi_xfer	*xs = ccb->ccb_cookie;
   3208  1.15    bouyer 	struct scsi_sense_data	*sense;
   3209   1.1    bouyer 	bus_dmamap_t		dmap = ccb->ccb_dmamap;
   3210  1.15    bouyer 	bool timeout = 1;
   3211   1.1    bouyer 
   3212   1.1    bouyer 	callout_stop(&xs->xs_callout);
   3213   1.1    bouyer 	if (ccb->ccb_state == MPII_CCB_TIMEOUT)
   3214   1.1    bouyer 		timeout = 1;
   3215   1.1    bouyer 	ccb->ccb_state = MPII_CCB_READY;
   3216   1.1    bouyer 
   3217   1.1    bouyer 	if (xs->datalen != 0) {
   3218   1.1    bouyer 		bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
   3219   1.1    bouyer 		    (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_POSTREAD :
   3220   1.1    bouyer 		    BUS_DMASYNC_POSTWRITE);
   3221   1.1    bouyer 
   3222   1.1    bouyer 		bus_dmamap_unload(sc->sc_dmat, dmap);
   3223   1.1    bouyer 	}
   3224   1.1    bouyer 
   3225   1.1    bouyer 	xs->error = XS_NOERROR;
   3226   1.1    bouyer 	xs->resid = 0;
   3227   1.1    bouyer 
   3228   1.1    bouyer 	if (ccb->ccb_rcb == NULL) {
   3229   1.1    bouyer 		/* no scsi error, we're ok so drop out early */
   3230   1.1    bouyer 		xs->status = SCSI_OK;
   3231  1.15    bouyer 		goto done;
   3232   1.1    bouyer 	}
   3233   1.1    bouyer 
   3234   1.1    bouyer 	sie = ccb->ccb_rcb->rcb_reply;
   3235   1.1    bouyer 
   3236   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s: mpii_scsi_cmd_done xs cmd: 0x%02x len: %d "
   3237  1.15    bouyer 	    "flags 0x%x\n", DEVNAME(sc), xs->cmd->opcode, xs->datalen,
   3238   1.1    bouyer 	    xs->xs_control);
   3239   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  dev_handle: %d msg_length: %d "
   3240   1.1    bouyer 	    "function: 0x%02x\n", DEVNAME(sc), le16toh(sie->dev_handle),
   3241   1.1    bouyer 	    sie->msg_length, sie->function);
   3242   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc),
   3243   1.1    bouyer 	    sie->vp_id, sie->vf_id);
   3244   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  scsi_status: 0x%02x scsi_state: 0x%02x "
   3245   1.1    bouyer 	    "ioc_status: 0x%04x\n", DEVNAME(sc), sie->scsi_status,
   3246   1.1    bouyer 	    sie->scsi_state, le16toh(sie->ioc_status));
   3247   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
   3248   1.1    bouyer 	    le32toh(sie->ioc_loginfo));
   3249   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  transfer_count: %d\n", DEVNAME(sc),
   3250   1.1    bouyer 	    le32toh(sie->transfer_count));
   3251   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  sense_count: %d\n", DEVNAME(sc),
   3252   1.1    bouyer 	    le32toh(sie->sense_count));
   3253   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  response_info: 0x%08x\n", DEVNAME(sc),
   3254   1.1    bouyer 	    le32toh(sie->response_info));
   3255   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  task_tag: 0x%04x\n", DEVNAME(sc),
   3256   1.1    bouyer 	    le16toh(sie->task_tag));
   3257   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  bidirectional_transfer_count: 0x%08x\n",
   3258   1.1    bouyer 	    DEVNAME(sc), le32toh(sie->bidirectional_transfer_count));
   3259   1.1    bouyer 
   3260   1.3    kardel 	xs->status = map_scsi_status(sie->scsi_status);
   3261   1.3    kardel 
   3262   1.1    bouyer 	switch (le16toh(sie->ioc_status) & MPII_IOCSTATUS_MASK) {
   3263   1.1    bouyer 	case MPII_IOCSTATUS_SCSI_DATA_UNDERRUN:
   3264  1.15    bouyer 		switch(sie->scsi_status) {
   3265  1.15    bouyer 		case MPII_SCSIIO_STATUS_CHECK_COND:
   3266   1.3    kardel 			xs->error = XS_SENSE;
   3267  1.15    bouyer 		case MPII_SCSIIO_STATUS_GOOD:
   3268   1.1    bouyer 			xs->resid = xs->datalen - le32toh(sie->transfer_count);
   3269   1.1    bouyer 			break;
   3270   1.1    bouyer 		default:
   3271   1.1    bouyer 			xs->error = XS_DRIVER_STUFFUP;
   3272   1.1    bouyer 			break;
   3273   1.1    bouyer 		}
   3274   1.1    bouyer 		break;
   3275   1.3    kardel 
   3276   1.1    bouyer 	case MPII_IOCSTATUS_SUCCESS:
   3277   1.1    bouyer 	case MPII_IOCSTATUS_SCSI_RECOVERED_ERROR:
   3278   1.3    kardel 		switch (sie->scsi_status) {
   3279  1.15    bouyer 		case MPII_SCSIIO_STATUS_GOOD:
   3280   1.1    bouyer 			break;
   3281   1.1    bouyer 
   3282  1.15    bouyer 		case MPII_SCSIIO_STATUS_CHECK_COND:
   3283   1.1    bouyer 			xs->error = XS_SENSE;
   3284   1.1    bouyer 			break;
   3285  1.15    bouyer 
   3286  1.15    bouyer 		case MPII_SCSIIO_STATUS_BUSY:
   3287  1.15    bouyer 		case MPII_SCSIIO_STATUS_TASK_SET_FULL:
   3288   1.1    bouyer 			xs->error = XS_BUSY;
   3289   1.1    bouyer 			break;
   3290   1.1    bouyer 
   3291   1.1    bouyer 		default:
   3292   1.1    bouyer 			xs->error = XS_DRIVER_STUFFUP;
   3293   1.1    bouyer 		}
   3294   1.1    bouyer 		break;
   3295   1.1    bouyer 
   3296   1.1    bouyer 	case MPII_IOCSTATUS_BUSY:
   3297   1.1    bouyer 	case MPII_IOCSTATUS_INSUFFICIENT_RESOURCES:
   3298   1.1    bouyer 		xs->error = XS_BUSY;
   3299   1.1    bouyer 		break;
   3300   1.1    bouyer 
   3301   1.1    bouyer 	case MPII_IOCSTATUS_SCSI_IOC_TERMINATED:
   3302   1.1    bouyer 	case MPII_IOCSTATUS_SCSI_TASK_TERMINATED:
   3303   1.1    bouyer 		xs->error = timeout ? XS_TIMEOUT : XS_RESET;
   3304   1.1    bouyer 		break;
   3305   1.1    bouyer 
   3306   1.1    bouyer 	case MPII_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
   3307   1.1    bouyer 	case MPII_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
   3308   1.1    bouyer 		xs->error = XS_SELTIMEOUT;
   3309   1.1    bouyer 		break;
   3310   1.1    bouyer 
   3311   1.1    bouyer 	default:
   3312   1.1    bouyer 		xs->error = XS_DRIVER_STUFFUP;
   3313   1.1    bouyer 		break;
   3314   1.1    bouyer 	}
   3315   1.1    bouyer 
   3316  1.15    bouyer 	sense = (struct scsi_sense_data *)((uintptr_t)ccb->ccb_cmd +
   3317  1.15    bouyer 	    sc->sc_request_size - sizeof(*sense));
   3318  1.15    bouyer 	if (sie->scsi_state & MPII_SCSIIO_STATE_AUTOSENSE_VALID)
   3319  1.15    bouyer 		memcpy(&xs->sense, sense, sizeof(xs->sense));
   3320   1.1    bouyer 
   3321   1.1    bouyer 	DNPRINTF(MPII_D_CMD, "%s:  xs err: %d status: %#x\n", DEVNAME(sc),
   3322   1.1    bouyer 	    xs->error, xs->status);
   3323   1.1    bouyer 
   3324   1.1    bouyer 	mpii_push_reply(sc, ccb->ccb_rcb);
   3325  1.15    bouyer done:
   3326   1.1    bouyer 	mpii_put_ccb(sc, ccb);
   3327   1.1    bouyer 	scsipi_done(xs);
   3328   1.1    bouyer }
   3329   1.1    bouyer 
   3330   1.1    bouyer #if 0
   3331  1.15    bouyer int
   3332  1.15    bouyer mpii_scsi_ioctl(struct scsi_link *link, u_long cmd, void *addr, int flag)
   3333  1.15    bouyer {
   3334  1.15    bouyer 	struct mpii_softc	*sc = (struct mpii_softc *)link->adapter_softc;
   3335  1.15    bouyer 	struct mpii_device	*dev = sc->sc_devs[link->target];
   3336  1.15    bouyer 
   3337  1.15    bouyer 	DNPRINTF(MPII_D_IOCTL, "%s: mpii_scsi_ioctl\n", DEVNAME(sc));
   3338  1.15    bouyer 
   3339  1.15    bouyer 	switch (cmd) {
   3340  1.15    bouyer 	case DIOCGCACHE:
   3341  1.15    bouyer 	case DIOCSCACHE:
   3342  1.15    bouyer 		if (dev != NULL && ISSET(dev->flags, MPII_DF_VOLUME)) {
   3343  1.15    bouyer 			return (mpii_ioctl_cache(link, cmd,
   3344  1.15    bouyer 			    (struct dk_cache *)addr));
   3345  1.15    bouyer 		}
   3346  1.15    bouyer 		break;
   3347  1.15    bouyer 
   3348  1.15    bouyer 	default:
   3349  1.15    bouyer 		if (sc->sc_ioctl)
   3350  1.15    bouyer 			return (sc->sc_ioctl(link->adapter_softc, cmd, addr));
   3351  1.15    bouyer 
   3352  1.15    bouyer 		break;
   3353  1.15    bouyer 	}
   3354  1.15    bouyer 
   3355  1.15    bouyer 	return (ENOTTY);
   3356  1.15    bouyer }
   3357  1.15    bouyer 
   3358  1.15    bouyer int
   3359   1.1    bouyer mpii_ioctl_cache(struct scsi_link *link, u_long cmd, struct dk_cache *dc)
   3360   1.1    bouyer {
   3361   1.1    bouyer 	struct mpii_softc *sc = (struct mpii_softc *)link->adapter_softc;
   3362   1.1    bouyer 	struct mpii_device *dev = sc->sc_devs[link->target];
   3363   1.1    bouyer 	struct mpii_cfg_raid_vol_pg0 *vpg;
   3364   1.1    bouyer 	struct mpii_msg_raid_action_request *req;
   3365  1.15    bouyer 	struct mpii_msg_raid_action_reply *rep;
   3366   1.1    bouyer 	struct mpii_cfg_hdr hdr;
   3367   1.1    bouyer 	struct mpii_ccb	*ccb;
   3368   1.1    bouyer 	u_int32_t addr = MPII_CFG_RAID_VOL_ADDR_HANDLE | dev->dev_handle;
   3369   1.1    bouyer 	size_t pagelen;
   3370   1.1    bouyer 	int rv = 0;
   3371   1.1    bouyer 	int enabled;
   3372   1.1    bouyer 
   3373   1.1    bouyer 	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
   3374   1.1    bouyer 	    addr, MPII_PG_POLL, &hdr) != 0)
   3375   1.1    bouyer 		return (EINVAL);
   3376   1.1    bouyer 
   3377   1.1    bouyer 	pagelen = hdr.page_length * 4;
   3378  1.12  jdolecek 	vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_ZERO);
   3379   1.1    bouyer 	if (vpg == NULL)
   3380   1.1    bouyer 		return (ENOMEM);
   3381   1.1    bouyer 
   3382   1.1    bouyer 	if (mpii_req_cfg_page(sc, addr, MPII_PG_POLL, &hdr, 1,
   3383   1.1    bouyer 	    vpg, pagelen) != 0) {
   3384   1.1    bouyer 		rv = EINVAL;
   3385   1.1    bouyer 		goto done;
   3386   1.1    bouyer 	}
   3387   1.1    bouyer 
   3388   1.1    bouyer 	enabled = ((le16toh(vpg->volume_settings) &
   3389   1.1    bouyer 	    MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_MASK) ==
   3390   1.1    bouyer 	    MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_ENABLED) ? 1 : 0;
   3391   1.1    bouyer 
   3392   1.1    bouyer 	if (cmd == DIOCGCACHE) {
   3393   1.1    bouyer 		dc->wrcache = enabled;
   3394   1.1    bouyer 		dc->rdcache = 0;
   3395   1.1    bouyer 		goto done;
   3396   1.1    bouyer 	} /* else DIOCSCACHE */
   3397   1.1    bouyer 
   3398   1.1    bouyer 	if (dc->rdcache) {
   3399   1.1    bouyer 		rv = EOPNOTSUPP;
   3400   1.1    bouyer 		goto done;
   3401   1.1    bouyer 	}
   3402   1.1    bouyer 
   3403   1.1    bouyer 	if (((dc->wrcache) ? 1 : 0) == enabled)
   3404   1.1    bouyer 		goto done;
   3405   1.1    bouyer 
   3406  1.15    bouyer 	ccb = scsi_io_get(&sc->sc_iopool, SCSI_POLL);
   3407   1.1    bouyer 	if (ccb == NULL) {
   3408   1.1    bouyer 		rv = ENOMEM;
   3409   1.1    bouyer 		goto done;
   3410   1.1    bouyer 	}
   3411   1.1    bouyer 
   3412   1.1    bouyer 	ccb->ccb_done = mpii_empty_done;
   3413   1.1    bouyer 
   3414   1.1    bouyer 	req = ccb->ccb_cmd;
   3415  1.15    bouyer 	memset(req, 0, sizeof(*req));
   3416   1.1    bouyer 	req->function = MPII_FUNCTION_RAID_ACTION;
   3417   1.1    bouyer 	req->action = MPII_RAID_ACTION_CHANGE_VOL_WRITE_CACHE;
   3418   1.1    bouyer 	req->vol_dev_handle = htole16(dev->dev_handle);
   3419   1.1    bouyer 	req->action_data = htole32(dc->wrcache ?
   3420   1.1    bouyer 	    MPII_RAID_VOL_WRITE_CACHE_ENABLE :
   3421   1.1    bouyer 	    MPII_RAID_VOL_WRITE_CACHE_DISABLE);
   3422   1.1    bouyer 
   3423   1.1    bouyer 	if (mpii_poll(sc, ccb) != 0) {
   3424   1.1    bouyer 		rv = EIO;
   3425   1.1    bouyer 		goto done;
   3426   1.1    bouyer 	}
   3427   1.1    bouyer 
   3428   1.1    bouyer 	if (ccb->ccb_rcb != NULL) {
   3429   1.1    bouyer 		rep = ccb->ccb_rcb->rcb_reply;
   3430   1.1    bouyer 		if ((rep->ioc_status != MPII_IOCSTATUS_SUCCESS) ||
   3431   1.1    bouyer 		    ((rep->action_data[0] &
   3432   1.1    bouyer 		     MPII_RAID_VOL_WRITE_CACHE_MASK) !=
   3433   1.1    bouyer 		    (dc->wrcache ? MPII_RAID_VOL_WRITE_CACHE_ENABLE :
   3434   1.1    bouyer 		     MPII_RAID_VOL_WRITE_CACHE_DISABLE)))
   3435   1.1    bouyer 			rv = EINVAL;
   3436   1.1    bouyer 		mpii_push_reply(sc, ccb->ccb_rcb);
   3437   1.1    bouyer 	}
   3438   1.1    bouyer 
   3439  1.15    bouyer 	scsi_io_put(&sc->sc_iopool, ccb);
   3440   1.1    bouyer 
   3441   1.1    bouyer done:
   3442   1.1    bouyer 	free(vpg, M_TEMP);
   3443   1.1    bouyer 	return (rv);
   3444   1.1    bouyer }
   3445  1.15    bouyer #endif /* 0 */
   3446   1.1    bouyer 
   3447   1.1    bouyer #if NBIO > 0
   3448  1.15    bouyer int
   3449   1.1    bouyer mpii_ioctl(device_t dev, u_long cmd, void *addr)
   3450   1.1    bouyer {
   3451   1.1    bouyer 	struct mpii_softc	*sc = device_private(dev);
   3452  1.15    bouyer 	int			error = 0;
   3453   1.1    bouyer 
   3454   1.1    bouyer 	DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl ", DEVNAME(sc));
   3455   1.1    bouyer 
   3456   1.1    bouyer 	switch (cmd) {
   3457   1.1    bouyer 	case BIOCINQ:
   3458   1.1    bouyer 		DNPRINTF(MPII_D_IOCTL, "inq\n");
   3459   1.1    bouyer 		error = mpii_ioctl_inq(sc, (struct bioc_inq *)addr);
   3460   1.1    bouyer 		break;
   3461   1.1    bouyer 	case BIOCVOL:
   3462   1.1    bouyer 		DNPRINTF(MPII_D_IOCTL, "vol\n");
   3463   1.1    bouyer 		error = mpii_ioctl_vol(sc, (struct bioc_vol *)addr);
   3464   1.1    bouyer 		break;
   3465   1.1    bouyer 	case BIOCDISK:
   3466   1.1    bouyer 		DNPRINTF(MPII_D_IOCTL, "disk\n");
   3467   1.1    bouyer 		error = mpii_ioctl_disk(sc, (struct bioc_disk *)addr);
   3468   1.1    bouyer 		break;
   3469   1.1    bouyer 	default:
   3470   1.1    bouyer 		DNPRINTF(MPII_D_IOCTL, " invalid ioctl\n");
   3471  1.15    bouyer 		error = ENOTTY;
   3472   1.1    bouyer 	}
   3473   1.1    bouyer 
   3474   1.1    bouyer 	return (error);
   3475   1.1    bouyer }
   3476   1.1    bouyer 
   3477  1.15    bouyer int
   3478   1.1    bouyer mpii_ioctl_inq(struct mpii_softc *sc, struct bioc_inq *bi)
   3479   1.1    bouyer {
   3480   1.1    bouyer 	int			i;
   3481   1.1    bouyer 
   3482   1.1    bouyer 	DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl_inq\n", DEVNAME(sc));
   3483   1.1    bouyer 
   3484   1.1    bouyer 	strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev));
   3485  1.15    bouyer 	mutex_enter(&sc->sc_devs_mtx);
   3486   1.1    bouyer 	for (i = 0; i < sc->sc_max_devices; i++)
   3487   1.1    bouyer 		if (sc->sc_devs[i] &&
   3488   1.1    bouyer 		    ISSET(sc->sc_devs[i]->flags, MPII_DF_VOLUME))
   3489   1.1    bouyer 			bi->bi_novol++;
   3490  1.15    bouyer 	mutex_exit(&sc->sc_devs_mtx);
   3491   1.1    bouyer 	return (0);
   3492   1.1    bouyer }
   3493   1.1    bouyer 
   3494  1.15    bouyer int
   3495   1.1    bouyer mpii_ioctl_vol(struct mpii_softc *sc, struct bioc_vol *bv)
   3496   1.1    bouyer {
   3497   1.1    bouyer 	struct mpii_cfg_raid_vol_pg0	*vpg;
   3498   1.1    bouyer 	struct mpii_cfg_hdr		hdr;
   3499   1.1    bouyer 	struct mpii_device		*dev;
   3500   1.1    bouyer 	size_t				pagelen;
   3501   1.1    bouyer 	u_int16_t			volh;
   3502   1.1    bouyer 	int				rv, hcnt = 0;
   3503  1.15    bouyer 	int				percent;
   3504   1.1    bouyer 
   3505   1.1    bouyer 	DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl_vol %d\n",
   3506   1.1    bouyer 	    DEVNAME(sc), bv->bv_volid);
   3507   1.1    bouyer 
   3508  1.15    bouyer 	mutex_enter(&sc->sc_devs_mtx);
   3509  1.15    bouyer 	if ((dev = mpii_find_vol(sc, bv->bv_volid)) == NULL) {
   3510  1.15    bouyer 		mutex_exit(&sc->sc_devs_mtx);
   3511   1.1    bouyer 		return (ENODEV);
   3512  1.15    bouyer 	}
   3513   1.1    bouyer 	volh = dev->dev_handle;
   3514  1.15    bouyer 	percent = dev->percent;
   3515  1.15    bouyer 	mutex_exit(&sc->sc_devs_mtx);
   3516   1.1    bouyer 
   3517   1.1    bouyer 	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
   3518   1.1    bouyer 	    MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0, &hdr) != 0) {
   3519   1.1    bouyer 		printf("%s: unable to fetch header for raid volume page 0\n",
   3520   1.1    bouyer 		    DEVNAME(sc));
   3521   1.1    bouyer 		return (EINVAL);
   3522   1.1    bouyer 	}
   3523   1.1    bouyer 
   3524   1.1    bouyer 	pagelen = hdr.page_length * 4;
   3525  1.12  jdolecek 	vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_ZERO);
   3526   1.1    bouyer 	if (vpg == NULL) {
   3527   1.1    bouyer 		printf("%s: unable to allocate space for raid "
   3528   1.1    bouyer 		    "volume page 0\n", DEVNAME(sc));
   3529   1.1    bouyer 		return (ENOMEM);
   3530   1.1    bouyer 	}
   3531   1.1    bouyer 
   3532   1.1    bouyer 	if (mpii_req_cfg_page(sc, MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0,
   3533   1.1    bouyer 	    &hdr, 1, vpg, pagelen) != 0) {
   3534   1.1    bouyer 		printf("%s: unable to fetch raid volume page 0\n",
   3535   1.1    bouyer 		    DEVNAME(sc));
   3536   1.1    bouyer 		free(vpg, M_TEMP);
   3537   1.1    bouyer 		return (EINVAL);
   3538   1.1    bouyer 	}
   3539   1.1    bouyer 
   3540   1.1    bouyer 	switch (vpg->volume_state) {
   3541   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_ONLINE:
   3542   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_OPTIMAL:
   3543   1.1    bouyer 		bv->bv_status = BIOC_SVONLINE;
   3544   1.1    bouyer 		break;
   3545   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_DEGRADED:
   3546   1.1    bouyer 		if (ISSET(le32toh(vpg->volume_status),
   3547   1.1    bouyer 		    MPII_CFG_RAID_VOL_0_STATUS_RESYNC)) {
   3548   1.1    bouyer 			bv->bv_status = BIOC_SVREBUILD;
   3549  1.15    bouyer 			bv->bv_percent = percent;
   3550   1.1    bouyer 		} else
   3551   1.1    bouyer 			bv->bv_status = BIOC_SVDEGRADED;
   3552   1.1    bouyer 		break;
   3553   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_FAILED:
   3554   1.1    bouyer 		bv->bv_status = BIOC_SVOFFLINE;
   3555   1.1    bouyer 		break;
   3556   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_INITIALIZING:
   3557   1.1    bouyer 		bv->bv_status = BIOC_SVBUILDING;
   3558   1.1    bouyer 		break;
   3559   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_MISSING:
   3560   1.1    bouyer 	default:
   3561   1.1    bouyer 		bv->bv_status = BIOC_SVINVALID;
   3562   1.1    bouyer 		break;
   3563   1.1    bouyer 	}
   3564   1.1    bouyer 
   3565   1.1    bouyer 	switch (vpg->volume_type) {
   3566   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_TYPE_RAID0:
   3567   1.1    bouyer 		bv->bv_level = 0;
   3568   1.1    bouyer 		break;
   3569   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_TYPE_RAID1:
   3570   1.1    bouyer 		bv->bv_level = 1;
   3571   1.1    bouyer 		break;
   3572   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_TYPE_RAID1E:
   3573   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_TYPE_RAID10:
   3574   1.1    bouyer 		bv->bv_level = 10;
   3575   1.1    bouyer 		break;
   3576   1.1    bouyer 	default:
   3577   1.1    bouyer 		bv->bv_level = -1;
   3578   1.1    bouyer 	}
   3579   1.1    bouyer 
   3580   1.1    bouyer 	if ((rv = mpii_bio_hs(sc, NULL, 0, vpg->hot_spare_pool, &hcnt)) != 0) {
   3581   1.1    bouyer 		free(vpg, M_TEMP);
   3582   1.1    bouyer 		return (rv);
   3583   1.1    bouyer 	}
   3584   1.1    bouyer 
   3585   1.1    bouyer 	bv->bv_nodisk = vpg->num_phys_disks + hcnt;
   3586   1.1    bouyer 
   3587   1.1    bouyer 	bv->bv_size = le64toh(vpg->max_lba) * le16toh(vpg->block_size);
   3588   1.1    bouyer 
   3589   1.1    bouyer 	free(vpg, M_TEMP);
   3590   1.1    bouyer 	return (0);
   3591   1.1    bouyer }
   3592   1.1    bouyer 
   3593  1.15    bouyer int
   3594   1.1    bouyer mpii_ioctl_disk(struct mpii_softc *sc, struct bioc_disk *bd)
   3595   1.1    bouyer {
   3596   1.1    bouyer 	struct mpii_cfg_raid_vol_pg0		*vpg;
   3597   1.1    bouyer 	struct mpii_cfg_raid_vol_pg0_physdisk	*pd;
   3598   1.1    bouyer 	struct mpii_cfg_hdr			hdr;
   3599   1.1    bouyer 	struct mpii_device			*dev;
   3600   1.1    bouyer 	size_t					pagelen;
   3601   1.1    bouyer 	u_int16_t				volh;
   3602   1.1    bouyer 	u_int8_t				dn;
   3603   1.1    bouyer 
   3604   1.1    bouyer 	DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl_disk %d/%d\n",
   3605   1.1    bouyer 	    DEVNAME(sc), bd->bd_volid, bd->bd_diskid);
   3606   1.1    bouyer 
   3607  1.15    bouyer 	mutex_enter(&sc->sc_devs_mtx);
   3608  1.15    bouyer 	if ((dev = mpii_find_vol(sc, bd->bd_volid)) == NULL) {
   3609  1.15    bouyer 		mutex_exit(&sc->sc_devs_mtx);
   3610   1.1    bouyer 		return (ENODEV);
   3611  1.15    bouyer 	}
   3612   1.1    bouyer 	volh = dev->dev_handle;
   3613  1.15    bouyer 	mutex_exit(&sc->sc_devs_mtx);
   3614   1.1    bouyer 
   3615   1.1    bouyer 	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
   3616   1.1    bouyer 	    MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0, &hdr) != 0) {
   3617   1.1    bouyer 		printf("%s: unable to fetch header for raid volume page 0\n",
   3618   1.1    bouyer 		    DEVNAME(sc));
   3619   1.1    bouyer 		return (EINVAL);
   3620   1.1    bouyer 	}
   3621   1.1    bouyer 
   3622   1.1    bouyer 	pagelen = hdr.page_length * 4;
   3623  1.12  jdolecek 	vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_ZERO);
   3624   1.1    bouyer 	if (vpg == NULL) {
   3625   1.1    bouyer 		printf("%s: unable to allocate space for raid "
   3626   1.1    bouyer 		    "volume page 0\n", DEVNAME(sc));
   3627   1.1    bouyer 		return (ENOMEM);
   3628   1.1    bouyer 	}
   3629   1.1    bouyer 
   3630   1.1    bouyer 	if (mpii_req_cfg_page(sc, MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0,
   3631   1.1    bouyer 	    &hdr, 1, vpg, pagelen) != 0) {
   3632   1.1    bouyer 		printf("%s: unable to fetch raid volume page 0\n",
   3633   1.1    bouyer 		    DEVNAME(sc));
   3634   1.1    bouyer 		free(vpg, M_TEMP);
   3635   1.1    bouyer 		return (EINVAL);
   3636   1.1    bouyer 	}
   3637   1.1    bouyer 
   3638   1.1    bouyer 	if (bd->bd_diskid >= vpg->num_phys_disks) {
   3639   1.1    bouyer 		int		nvdsk = vpg->num_phys_disks;
   3640   1.1    bouyer 		int		hsmap = vpg->hot_spare_pool;
   3641   1.1    bouyer 
   3642   1.1    bouyer 		free(vpg, M_TEMP);
   3643   1.1    bouyer 		return (mpii_bio_hs(sc, bd, nvdsk, hsmap, NULL));
   3644   1.1    bouyer 	}
   3645   1.1    bouyer 
   3646   1.1    bouyer 	pd = (struct mpii_cfg_raid_vol_pg0_physdisk *)(vpg + 1) +
   3647   1.1    bouyer 	    bd->bd_diskid;
   3648   1.1    bouyer 	dn = pd->phys_disk_num;
   3649   1.1    bouyer 
   3650   1.1    bouyer 	free(vpg, M_TEMP);
   3651   1.1    bouyer 	return (mpii_bio_disk(sc, bd, dn));
   3652   1.1    bouyer }
   3653   1.1    bouyer 
   3654  1.15    bouyer int
   3655   1.1    bouyer mpii_bio_hs(struct mpii_softc *sc, struct bioc_disk *bd, int nvdsk,
   3656   1.1    bouyer      int hsmap, int *hscnt)
   3657   1.1    bouyer {
   3658   1.1    bouyer 	struct mpii_cfg_raid_config_pg0	*cpg;
   3659   1.1    bouyer 	struct mpii_raid_config_element	*el;
   3660   1.1    bouyer 	struct mpii_ecfg_hdr		ehdr;
   3661   1.1    bouyer 	size_t				pagelen;
   3662   1.1    bouyer 	int				i, nhs = 0;
   3663   1.1    bouyer 
   3664   1.1    bouyer 	if (bd) {
   3665   1.1    bouyer 		DNPRINTF(MPII_D_IOCTL, "%s: mpii_bio_hs %d\n", DEVNAME(sc),
   3666   1.1    bouyer 		    bd->bd_diskid - nvdsk);
   3667   1.1    bouyer 	} else {
   3668   1.1    bouyer 		DNPRINTF(MPII_D_IOCTL, "%s: mpii_bio_hs\n", DEVNAME(sc));
   3669   1.1    bouyer 	}
   3670   1.1    bouyer 
   3671   1.1    bouyer 	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_CONFIG,
   3672   1.1    bouyer 	    0, MPII_CFG_RAID_CONFIG_ACTIVE_CONFIG, MPII_PG_EXTENDED,
   3673   1.1    bouyer 	    &ehdr) != 0) {
   3674   1.1    bouyer 		printf("%s: unable to fetch header for raid config page 0\n",
   3675   1.1    bouyer 		    DEVNAME(sc));
   3676   1.1    bouyer 		return (EINVAL);
   3677   1.1    bouyer 	}
   3678   1.1    bouyer 
   3679   1.1    bouyer 	pagelen = le16toh(ehdr.ext_page_length) * 4;
   3680  1.12  jdolecek 	cpg = malloc(pagelen, M_TEMP, M_WAITOK | M_ZERO);
   3681   1.1    bouyer 	if (cpg == NULL) {
   3682   1.1    bouyer 		printf("%s: unable to allocate space for raid config page 0\n",
   3683   1.1    bouyer 		    DEVNAME(sc));
   3684   1.1    bouyer 		return (ENOMEM);
   3685   1.1    bouyer 	}
   3686   1.1    bouyer 
   3687   1.1    bouyer 	if (mpii_req_cfg_page(sc, MPII_CFG_RAID_CONFIG_ACTIVE_CONFIG,
   3688   1.1    bouyer 	    MPII_PG_EXTENDED, &ehdr, 1, cpg, pagelen) != 0) {
   3689   1.1    bouyer 		printf("%s: unable to fetch raid config page 0\n",
   3690   1.1    bouyer 		    DEVNAME(sc));
   3691   1.1    bouyer 		free(cpg, M_TEMP);
   3692   1.1    bouyer 		return (EINVAL);
   3693   1.1    bouyer 	}
   3694   1.1    bouyer 
   3695   1.1    bouyer 	el = (struct mpii_raid_config_element *)(cpg + 1);
   3696   1.1    bouyer 	for (i = 0; i < cpg->num_elements; i++, el++) {
   3697   1.1    bouyer 		if (ISSET(le16toh(el->element_flags),
   3698   1.1    bouyer 		    MPII_RAID_CONFIG_ELEMENT_FLAG_HSP_PHYS_DISK) &&
   3699   1.1    bouyer 		    el->hot_spare_pool == hsmap) {
   3700   1.1    bouyer 			/*
   3701   1.1    bouyer 			 * diskid comparison is based on the idea that all
   3702   1.1    bouyer 			 * disks are counted by the bio(4) in sequence, thus
   3703   1.1    bouyer 			 * substracting the number of disks in the volume
   3704   1.1    bouyer 			 * from the diskid yields us a "relative" hotspare
   3705   1.1    bouyer 			 * number, which is good enough for us.
   3706   1.1    bouyer 			 */
   3707   1.1    bouyer 			if (bd != NULL && bd->bd_diskid == nhs + nvdsk) {
   3708   1.1    bouyer 				u_int8_t dn = el->phys_disk_num;
   3709   1.1    bouyer 
   3710   1.1    bouyer 				free(cpg, M_TEMP);
   3711   1.1    bouyer 				return (mpii_bio_disk(sc, bd, dn));
   3712   1.1    bouyer 			}
   3713   1.1    bouyer 			nhs++;
   3714   1.1    bouyer 		}
   3715   1.1    bouyer 	}
   3716   1.1    bouyer 
   3717   1.1    bouyer 	if (hscnt)
   3718   1.1    bouyer 		*hscnt = nhs;
   3719   1.1    bouyer 
   3720   1.1    bouyer 	free(cpg, M_TEMP);
   3721   1.1    bouyer 	return (0);
   3722   1.1    bouyer }
   3723   1.1    bouyer 
   3724  1.15    bouyer int
   3725   1.1    bouyer mpii_bio_disk(struct mpii_softc *sc, struct bioc_disk *bd, u_int8_t dn)
   3726   1.1    bouyer {
   3727   1.1    bouyer 	struct mpii_cfg_raid_physdisk_pg0	*ppg;
   3728   1.1    bouyer 	struct mpii_cfg_hdr			hdr;
   3729   1.1    bouyer 	struct mpii_device			*dev;
   3730   1.1    bouyer 	int					len;
   3731   1.1    bouyer 
   3732   1.1    bouyer 	DNPRINTF(MPII_D_IOCTL, "%s: mpii_bio_disk %d\n", DEVNAME(sc),
   3733   1.1    bouyer 	    bd->bd_diskid);
   3734   1.1    bouyer 
   3735  1.12  jdolecek 	ppg = malloc(sizeof(*ppg), M_TEMP, M_WAITOK | M_ZERO);
   3736   1.1    bouyer 	if (ppg == NULL) {
   3737   1.1    bouyer 		printf("%s: unable to allocate space for raid physical disk "
   3738   1.1    bouyer 		    "page 0\n", DEVNAME(sc));
   3739   1.1    bouyer 		return (ENOMEM);
   3740   1.1    bouyer 	}
   3741   1.1    bouyer 
   3742   1.1    bouyer 	hdr.page_version = 0;
   3743   1.1    bouyer 	hdr.page_length = sizeof(*ppg) / 4;
   3744   1.1    bouyer 	hdr.page_number = 0;
   3745   1.1    bouyer 	hdr.page_type = MPII_CONFIG_REQ_PAGE_TYPE_RAID_PD;
   3746   1.1    bouyer 
   3747   1.1    bouyer 	if (mpii_req_cfg_page(sc, MPII_CFG_RAID_PHYS_DISK_ADDR_NUMBER | dn, 0,
   3748   1.1    bouyer 	    &hdr, 1, ppg, sizeof(*ppg)) != 0) {
   3749   1.1    bouyer 		printf("%s: unable to fetch raid drive page 0\n",
   3750   1.1    bouyer 		    DEVNAME(sc));
   3751   1.1    bouyer 		free(ppg, M_TEMP);
   3752   1.1    bouyer 		return (EINVAL);
   3753   1.1    bouyer 	}
   3754   1.1    bouyer 
   3755   1.1    bouyer 	bd->bd_target = ppg->phys_disk_num;
   3756   1.1    bouyer 
   3757  1.15    bouyer 	mutex_enter(&sc->sc_devs_mtx);
   3758   1.1    bouyer 	if ((dev = mpii_find_dev(sc, le16toh(ppg->dev_handle))) == NULL) {
   3759  1.15    bouyer 		mutex_exit(&sc->sc_devs_mtx);
   3760   1.1    bouyer 		bd->bd_status = BIOC_SDINVALID;
   3761   1.1    bouyer 		free(ppg, M_TEMP);
   3762   1.1    bouyer 		return (0);
   3763   1.1    bouyer 	}
   3764  1.15    bouyer 	mutex_exit(&sc->sc_devs_mtx);
   3765   1.1    bouyer 
   3766   1.1    bouyer 	switch (ppg->phys_disk_state) {
   3767   1.1    bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_ONLINE:
   3768   1.1    bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_OPTIMAL:
   3769   1.1    bouyer 		bd->bd_status = BIOC_SDONLINE;
   3770   1.1    bouyer 		break;
   3771   1.1    bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_OFFLINE:
   3772   1.1    bouyer 		if (ppg->offline_reason ==
   3773   1.1    bouyer 		    MPII_CFG_RAID_PHYDISK_0_OFFLINE_FAILED ||
   3774   1.1    bouyer 		    ppg->offline_reason ==
   3775   1.1    bouyer 		    MPII_CFG_RAID_PHYDISK_0_OFFLINE_FAILEDREQ)
   3776   1.1    bouyer 			bd->bd_status = BIOC_SDFAILED;
   3777   1.1    bouyer 		else
   3778   1.1    bouyer 			bd->bd_status = BIOC_SDOFFLINE;
   3779   1.1    bouyer 		break;
   3780   1.1    bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_DEGRADED:
   3781   1.1    bouyer 		bd->bd_status = BIOC_SDFAILED;
   3782   1.1    bouyer 		break;
   3783   1.1    bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_REBUILDING:
   3784   1.1    bouyer 		bd->bd_status = BIOC_SDREBUILD;
   3785   1.1    bouyer 		break;
   3786   1.1    bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_HOTSPARE:
   3787   1.1    bouyer 		bd->bd_status = BIOC_SDHOTSPARE;
   3788   1.1    bouyer 		break;
   3789   1.1    bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_NOTCONFIGURED:
   3790   1.1    bouyer 		bd->bd_status = BIOC_SDUNUSED;
   3791   1.1    bouyer 		break;
   3792   1.1    bouyer 	case MPII_CFG_RAID_PHYDISK_0_STATE_NOTCOMPATIBLE:
   3793   1.1    bouyer 	default:
   3794   1.1    bouyer 		bd->bd_status = BIOC_SDINVALID;
   3795   1.1    bouyer 		break;
   3796   1.1    bouyer 	}
   3797   1.1    bouyer 
   3798   1.1    bouyer 	bd->bd_size = le64toh(ppg->dev_max_lba) * le16toh(ppg->block_size);
   3799   1.1    bouyer 
   3800   1.8  christos 	strnvisx(bd->bd_vendor, sizeof(bd->bd_vendor),
   3801   1.8  christos 	    ppg->vendor_id, sizeof(ppg->vendor_id),
   3802   1.8  christos 	    VIS_TRIM|VIS_SAFE|VIS_OCTAL);
   3803   1.1    bouyer 	len = strlen(bd->bd_vendor);
   3804   1.1    bouyer 	bd->bd_vendor[len] = ' ';
   3805   1.8  christos 	strnvisx(&bd->bd_vendor[len + 1], sizeof(ppg->vendor_id) - len - 1,
   3806   1.8  christos 	    ppg->product_id, sizeof(ppg->product_id),
   3807   1.8  christos 	    VIS_TRIM|VIS_SAFE|VIS_OCTAL);
   3808   1.8  christos 	strnvisx(bd->bd_serial, sizeof(bd->bd_serial),
   3809   1.8  christos 	    ppg->serial, sizeof(ppg->serial), VIS_TRIM|VIS_SAFE|VIS_OCTAL);
   3810   1.1    bouyer 
   3811   1.1    bouyer 	free(ppg, M_TEMP);
   3812   1.1    bouyer 	return (0);
   3813   1.1    bouyer }
   3814   1.1    bouyer 
   3815  1.15    bouyer struct mpii_device *
   3816   1.1    bouyer mpii_find_vol(struct mpii_softc *sc, int volid)
   3817   1.1    bouyer {
   3818   1.1    bouyer 	struct mpii_device	*dev = NULL;
   3819   1.1    bouyer 
   3820  1.15    bouyer 	KASSERT(mutex_owned(&sc->sc_devs_mtx));
   3821   1.1    bouyer 	if (sc->sc_vd_id_low + volid >= sc->sc_max_devices)
   3822   1.1    bouyer 		return (NULL);
   3823   1.1    bouyer 	dev = sc->sc_devs[sc->sc_vd_id_low + volid];
   3824   1.1    bouyer 	if (dev && ISSET(dev->flags, MPII_DF_VOLUME))
   3825   1.1    bouyer 		return (dev);
   3826   1.1    bouyer 	return (NULL);
   3827   1.1    bouyer }
   3828   1.1    bouyer 
   3829   1.1    bouyer /*
   3830   1.1    bouyer  * Non-sleeping lightweight version of the mpii_ioctl_vol
   3831   1.1    bouyer  */
   3832  1.15    bouyer int
   3833   1.1    bouyer mpii_bio_volstate(struct mpii_softc *sc, struct bioc_vol *bv)
   3834   1.1    bouyer {
   3835   1.1    bouyer 	struct mpii_cfg_raid_vol_pg0	*vpg;
   3836   1.1    bouyer 	struct mpii_cfg_hdr		hdr;
   3837   1.1    bouyer 	struct mpii_device		*dev = NULL;
   3838   1.1    bouyer 	size_t				pagelen;
   3839   1.1    bouyer 	u_int16_t			volh;
   3840   1.1    bouyer 
   3841  1.15    bouyer 	mutex_enter(&sc->sc_devs_mtx);
   3842  1.15    bouyer 	if ((dev = mpii_find_vol(sc, bv->bv_volid)) == NULL) {
   3843  1.15    bouyer 		mutex_exit(&sc->sc_devs_mtx);
   3844   1.1    bouyer 		return (ENODEV);
   3845  1.15    bouyer 	}
   3846   1.1    bouyer 	volh = dev->dev_handle;
   3847  1.15    bouyer 	mutex_exit(&sc->sc_devs_mtx);
   3848   1.1    bouyer 
   3849  1.15    bouyer 	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
   3850  1.15    bouyer 	    MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, MPII_PG_POLL, &hdr) != 0) {
   3851   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: unable to fetch header for raid "
   3852   1.1    bouyer 		    "volume page 0\n", DEVNAME(sc));
   3853   1.1    bouyer 		return (EINVAL);
   3854   1.1    bouyer 	}
   3855   1.1    bouyer 
   3856   1.1    bouyer 	pagelen = hdr.page_length * 4;
   3857   1.1    bouyer 	vpg = malloc(pagelen, M_TEMP, M_NOWAIT | M_ZERO);
   3858   1.1    bouyer 	if (vpg == NULL) {
   3859   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: unable to allocate space for raid "
   3860   1.1    bouyer 		    "volume page 0\n", DEVNAME(sc));
   3861   1.1    bouyer 		return (ENOMEM);
   3862   1.1    bouyer 	}
   3863   1.1    bouyer 
   3864  1.15    bouyer 	if (mpii_req_cfg_page(sc, MPII_CFG_RAID_VOL_ADDR_HANDLE | volh,
   3865  1.15    bouyer 	    MPII_PG_POLL, &hdr, 1, vpg, pagelen) != 0) {
   3866   1.1    bouyer 		DNPRINTF(MPII_D_MISC, "%s: unable to fetch raid volume "
   3867   1.1    bouyer 		    "page 0\n", DEVNAME(sc));
   3868   1.1    bouyer 		free(vpg, M_TEMP);
   3869   1.1    bouyer 		return (EINVAL);
   3870   1.1    bouyer 	}
   3871   1.1    bouyer 
   3872   1.1    bouyer 	switch (vpg->volume_state) {
   3873   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_ONLINE:
   3874   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_OPTIMAL:
   3875   1.1    bouyer 		bv->bv_status = BIOC_SVONLINE;
   3876   1.1    bouyer 		break;
   3877   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_DEGRADED:
   3878   1.1    bouyer 		if (ISSET(le32toh(vpg->volume_status),
   3879   1.1    bouyer 		    MPII_CFG_RAID_VOL_0_STATUS_RESYNC))
   3880   1.1    bouyer 			bv->bv_status = BIOC_SVREBUILD;
   3881   1.1    bouyer 		else
   3882   1.1    bouyer 			bv->bv_status = BIOC_SVDEGRADED;
   3883   1.1    bouyer 		break;
   3884   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_FAILED:
   3885   1.1    bouyer 		bv->bv_status = BIOC_SVOFFLINE;
   3886   1.1    bouyer 		break;
   3887   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_INITIALIZING:
   3888   1.1    bouyer 		bv->bv_status = BIOC_SVBUILDING;
   3889   1.1    bouyer 		break;
   3890   1.1    bouyer 	case MPII_CFG_RAID_VOL_0_STATE_MISSING:
   3891   1.1    bouyer 	default:
   3892   1.1    bouyer 		bv->bv_status = BIOC_SVINVALID;
   3893   1.1    bouyer 		break;
   3894   1.1    bouyer 	}
   3895   1.1    bouyer 
   3896   1.1    bouyer 	free(vpg, M_TEMP);
   3897   1.1    bouyer 	return (0);
   3898   1.1    bouyer }
   3899   1.1    bouyer 
   3900  1.15    bouyer int
   3901   1.1    bouyer mpii_create_sensors(struct mpii_softc *sc)
   3902   1.1    bouyer {
   3903   1.1    bouyer 	int			i, rv;
   3904   1.1    bouyer 
   3905  1.15    bouyer 	DNPRINTF(MPII_D_MISC, "%s: mpii_create_sensors(%d)\n",
   3906  1.15    bouyer 	    DEVNAME(sc), sc->sc_max_volumes);
   3907   1.1    bouyer 	sc->sc_sme = sysmon_envsys_create();
   3908  1.15    bouyer 	sc->sc_sensors = malloc(sizeof(envsys_data_t) * sc->sc_max_volumes,
   3909   1.1    bouyer 	    M_DEVBUF, M_NOWAIT | M_ZERO);
   3910   1.1    bouyer 	if (sc->sc_sensors == NULL) {
   3911  1.15    bouyer 		aprint_error_dev(sc->sc_dev, "can't allocate envsys_data_t\n");
   3912   1.1    bouyer 		return (1);
   3913   1.1    bouyer 	}
   3914   1.1    bouyer 
   3915  1.15    bouyer 	for (i = 0; i < sc->sc_max_volumes; i++) {
   3916   1.1    bouyer 		sc->sc_sensors[i].units = ENVSYS_DRIVE;
   3917   1.1    bouyer 		sc->sc_sensors[i].state = ENVSYS_SINVALID;
   3918   1.1    bouyer 		sc->sc_sensors[i].value_cur = ENVSYS_DRIVE_EMPTY;
   3919   1.1    bouyer 		sc->sc_sensors[i].flags |= ENVSYS_FMONSTCHANGED;
   3920   1.1    bouyer 
   3921  1.15    bouyer 		/* logical drives */
   3922   1.1    bouyer 		snprintf(sc->sc_sensors[i].desc,
   3923   1.1    bouyer 		    sizeof(sc->sc_sensors[i].desc), "%s:%d",
   3924  1.15    bouyer 		    DEVNAME(sc), i);
   3925  1.15    bouyer 												if ((rv = sysmon_envsys_sensor_attach(sc->sc_sme,
   3926   1.1    bouyer 		    &sc->sc_sensors[i])) != 0) {
   3927   1.1    bouyer 			aprint_error_dev(sc->sc_dev,
   3928   1.1    bouyer 			    "unable to attach sensor (rv = %d)\n", rv);
   3929  1.15    bouyer 			goto out;
   3930  1.15    bouyer 												}
   3931   1.1    bouyer 	}
   3932   1.1    bouyer 	sc->sc_sme->sme_name =  DEVNAME(sc);
   3933  1.15    bouyer 	sc->sc_sme->sme_cookie = sc;
   3934   1.1    bouyer 	sc->sc_sme->sme_refresh = mpii_refresh_sensors;
   3935   1.1    bouyer 
   3936   1.1    bouyer 	rv = sysmon_envsys_register(sc->sc_sme);
   3937   1.1    bouyer 	if (rv != 0) {
   3938   1.1    bouyer 		aprint_error_dev(sc->sc_dev,
   3939  1.15    bouyer 		    "unable to register with sysmon (rv = %d)\n", rv);
   3940   1.1    bouyer 		goto out;
   3941   1.1    bouyer 	}
   3942   1.1    bouyer 	return 0;
   3943   1.1    bouyer 
   3944   1.1    bouyer out:
   3945   1.1    bouyer 	free(sc->sc_sensors, M_DEVBUF);
   3946   1.1    bouyer 	sysmon_envsys_destroy(sc->sc_sme);
   3947   1.1    bouyer 	sc->sc_sme = NULL;
   3948  1.15    bouyer 	return 1;
   3949   1.1    bouyer }
   3950   1.1    bouyer 
   3951  1.15    bouyer int
   3952   1.1    bouyer mpii_destroy_sensors(struct mpii_softc *sc)
   3953   1.1    bouyer {
   3954  1.15    bouyer 	if (sc->sc_sme == NULL)
   3955   1.1    bouyer 		return 0;
   3956   1.1    bouyer 	sysmon_envsys_unregister(sc->sc_sme);
   3957   1.1    bouyer 	sc->sc_sme = NULL;
   3958   1.1    bouyer 	free(sc->sc_sensors, M_DEVBUF);
   3959   1.1    bouyer 	return 0;
   3960  1.15    bouyer 
   3961   1.1    bouyer }
   3962   1.1    bouyer 
   3963  1.15    bouyer void
   3964   1.1    bouyer mpii_refresh_sensors(struct sysmon_envsys *sme, envsys_data_t *edata)
   3965   1.1    bouyer {
   3966  1.15    bouyer 	struct mpii_softc	*sc = sme->sme_cookie;
   3967   1.1    bouyer 	struct bioc_vol		bv;
   3968   1.1    bouyer 
   3969  1.15    bouyer 	memset(&bv, 0, sizeof(bv));
   3970   1.1    bouyer 	bv.bv_volid = edata->sensor;
   3971  1.15    bouyer 	if (mpii_bio_volstate(sc, &bv))
   3972   1.6  christos 		bv.bv_status = BIOC_SVINVALID;
   3973   1.6  christos 	bio_vol_to_envsys(edata, &bv);
   3974   1.1    bouyer }
   3975   1.1    bouyer #endif /* NBIO > 0 */
   3976