151973Smsmith/*-
251973Smsmith * Copyright (c) 1999 Michael Smith
351973Smsmith * All rights reserved.
451973Smsmith *
551973Smsmith * Redistribution and use in source and binary forms, with or without
651973Smsmith * modification, are permitted provided that the following conditions
751973Smsmith * are met:
851973Smsmith * 1. Redistributions of source code must retain the above copyright
951973Smsmith *    notice, this list of conditions and the following disclaimer.
1051973Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1151973Smsmith *    notice, this list of conditions and the following disclaimer in the
1251973Smsmith *    documentation and/or other materials provided with the distribution.
1351973Smsmith *
1451973Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1551973Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1651973Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1751973Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1851973Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1951973Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2051973Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2151973Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2251973Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2351973Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2451973Smsmith * SUCH DAMAGE.
2551973Smsmith *
2651973Smsmith *	$FreeBSD$
2751973Smsmith */
2851973Smsmith
2951973Smsmith/*
3058188Smsmith * Debugging levels:
3158188Smsmith *  0 - quiet, only emit warnings
3258188Smsmith *  1 - noisy, emit major function points and things done
3358188Smsmith *  2 - extremely noisy, emit trace items in loops, etc.
3458188Smsmith */
3558188Smsmith#ifdef MLX_DEBUG
3687599Sobrien#define debug(level, fmt, args...)	do { if (level <= MLX_DEBUG) printf("%s: " fmt "\n", __func__ , ##args); } while(0)
3787599Sobrien#define debug_called(level)		do { if (level <= MLX_DEBUG) printf(__func__ ": called\n"); } while(0)
3858188Smsmith#else
3958188Smsmith#define debug(level, fmt, args...)
4058188Smsmith#define debug_called(level)
4158188Smsmith#endif
4258188Smsmith
4358188Smsmith/*
4460074Smsmith * Regardless of the actual capacity of the controller, we will allocate space
4560074Smsmith * for 64 s/g entries.  Typically controllers support 17 or 33 entries (64k or
4660074Smsmith * 128k maximum transfer assuming 4k page size and non-optimal alignment), but
4760074Smsmith * making that fit cleanly without crossing page boundaries requires rounding up
4860074Smsmith * to the next power of two.
4951973Smsmith */
50238997Sdelphij#define MLX_MAXPHYS	(128 * 1024)
5160074Smsmith#define MLX_NSEG	64
5260074Smsmith
5351973Smsmith#define MLX_NSLOTS	256		/* max number of command slots */
5451973Smsmith
5558188Smsmith#define MLX_MAXDRIVES	32		/* max number of system drives */
5651973Smsmith
5751973Smsmith/*
5851973Smsmith * Structure describing a System Drive as attached to the controller.
5951973Smsmith */
6051973Smsmithstruct mlx_sysdrive
6151973Smsmith{
6251973Smsmith    /* from MLX_CMD_ENQSYSDRIVE */
6351973Smsmith    u_int32_t		ms_size;
6451973Smsmith    int			ms_state;
6551973Smsmith    int			ms_raidlevel;
6651973Smsmith
6751973Smsmith    /* synthetic geometry */
6851973Smsmith    int			ms_cylinders;
6951973Smsmith    int			ms_heads;
7051973Smsmith    int			ms_sectors;
7151973Smsmith
7251973Smsmith    /* handle for attached driver */
7351973Smsmith    device_t		ms_disk;
7451973Smsmith};
7551973Smsmith
7651973Smsmith/*
7751973Smsmith * Per-command control structure.
7851973Smsmith */
7951973Smsmithstruct mlx_command
8051973Smsmith{
8160938Sjake    TAILQ_ENTRY(mlx_command)	mc_link;	/* list linkage */
8251973Smsmith
8351973Smsmith    struct mlx_softc		*mc_sc;		/* controller that owns us */
8451973Smsmith    u_int8_t			mc_slot;	/* command slot we occupy */
8551973Smsmith    u_int16_t			mc_status;	/* command completion status */
8654419Smsmith    time_t			mc_timeout;	/* when this command expires */
8751973Smsmith    u_int8_t			mc_mailbox[16];	/* command mailbox */
8851973Smsmith    u_int32_t			mc_sgphys;	/* physical address of s/g array in controller space */
8951973Smsmith    int				mc_nsgent;	/* number of entries in s/g map */
9051973Smsmith    int				mc_flags;
9151973Smsmith#define MLX_CMD_DATAIN		(1<<0)
9251973Smsmith#define MLX_CMD_DATAOUT		(1<<1)
9351973Smsmith#define MLX_CMD_PRIORITY	(1<<2)		/* high-priority command */
9451973Smsmith
9551973Smsmith    void			*mc_data;	/* data buffer */
9651973Smsmith    size_t			mc_length;
9751973Smsmith    bus_dmamap_t		mc_dmamap;	/* DMA map for data */
9851973Smsmith    u_int32_t			mc_dataphys;	/* data buffer base address controller space */
9951973Smsmith
10051973Smsmith    void			(* mc_complete)(struct mlx_command *mc);	/* completion handler */
10151973Smsmith    void			*mc_private;	/* submitter-private data or wait channel */
102119665Sscottl    int				mc_command;
10351973Smsmith};
10451973Smsmith
10551973Smsmith/*
10651973Smsmith * Per-controller structure.
10751973Smsmith */
10851973Smsmithstruct mlx_softc
10951973Smsmith{
11051973Smsmith    /* bus connections */
11151973Smsmith    device_t		mlx_dev;
112130585Sphk    struct cdev *mlx_dev_t;
11351973Smsmith    struct resource	*mlx_mem;	/* mailbox interface window */
11469292Smdodd    int			mlx_mem_rid;
11569292Smdodd    int			mlx_mem_type;
11651973Smsmith    bus_dma_tag_t	mlx_parent_dmat;/* parent DMA tag */
11751973Smsmith    bus_dma_tag_t	mlx_buffer_dmat;/* data buffer DMA tag */
11851973Smsmith    struct resource	*mlx_irq;	/* interrupt */
11951973Smsmith    void		*mlx_intr;	/* interrupt handle */
12051973Smsmith
12151973Smsmith    /* scatter/gather lists and their controller-visible mappings */
12251973Smsmith    struct mlx_sgentry	*mlx_sgtable;	/* s/g lists */
12351973Smsmith    u_int32_t		mlx_sgbusaddr;	/* s/g table base address in bus space */
12451973Smsmith    bus_dma_tag_t	mlx_sg_dmat;	/* s/g buffer DMA tag */
12551973Smsmith    bus_dmamap_t	mlx_sg_dmamap;	/* map for s/g buffers */
12651973Smsmith
12751973Smsmith    /* controller limits and features */
12854979Smsmith    struct mlx_enquiry2	*mlx_enq2;
12951973Smsmith    int			mlx_feature;	/* controller features/quirks */
13051973Smsmith#define MLX_FEAT_PAUSEWORKS	(1<<0)	/* channel pause works as expected */
13151973Smsmith
13251973Smsmith    /* controller queues and arrays */
13360938Sjake    TAILQ_HEAD(, mlx_command)	mlx_freecmds;		/* command structures available for reuse */
13460938Sjake    TAILQ_HEAD(, mlx_command)	mlx_work;		/* active commands */
13551973Smsmith    struct mlx_command	*mlx_busycmd[MLX_NSLOTS];	/* busy commands */
13651973Smsmith    int			mlx_busycmds;			/* count of busy commands */
13751973Smsmith    struct mlx_sysdrive	mlx_sysdrive[MLX_MAXDRIVES];	/* system drives */
138240963Sjhb    struct bio_queue_head mlx_bioq;			/* outstanding I/O operations */
13951973Smsmith    int			mlx_waitbufs;			/* number of bufs awaiting commands */
14051973Smsmith
14151973Smsmith    /* controller status */
14251973Smsmith    int			mlx_geom;
14351973Smsmith#define MLX_GEOM_128_32		0	/* geoemetry translation modes */
14451973Smsmith#define MLX_GEOM_256_63		1
14551973Smsmith    int			mlx_state;
14651973Smsmith#define MLX_STATE_INTEN		(1<<0)	/* interrupts have been enabled */
14751973Smsmith#define MLX_STATE_SHUTDOWN	(1<<1)	/* controller is shut down */
14851973Smsmith#define MLX_STATE_OPEN		(1<<2)	/* control device is open */
14951973Smsmith#define MLX_STATE_SUSPEND	(1<<3)	/* controller is suspended */
150240608Sjhb#define	MLX_STATE_QFROZEN	(1<<4)  /* bio queue frozen */
151240608Sjhb    struct mtx		mlx_io_lock;
152240608Sjhb    struct sx		mlx_config_lock;
153240608Sjhb    struct callout	mlx_timeout;	/* periodic status monitor */
15451973Smsmith    time_t		mlx_lastpoll;	/* last time_second we polled for status */
15559136Smsmith    u_int16_t		mlx_lastevent;	/* sequence number of the last event we recorded */
15654979Smsmith    int			mlx_currevent;	/* sequence number last time we looked */
15759136Smsmith    int			mlx_background;	/* if != 0 rebuild or check is in progress */
15859136Smsmith#define MLX_BACKGROUND_CHECK		1	/* we started a check */
15959136Smsmith#define MLX_BACKGROUND_REBUILD		2	/* we started a rebuild */
16059136Smsmith#define MLX_BACKGROUND_SPONTANEOUS	3	/* it just happened somehow */
16159136Smsmith    struct mlx_rebuild_status mlx_rebuildstat;	/* last rebuild status */
16251973Smsmith    struct mlx_pause	mlx_pause;	/* pending pause operation details */
16351973Smsmith
16458188Smsmith    int			mlx_flags;
16558188Smsmith#define MLX_SPINUP_REPORTED	(1<<0)	/* "spinning up drives" message displayed */
16659447Smsmith#define MLX_EVENTLOG_BUSY	(1<<1)	/* currently reading event log */
16754419Smsmith
16851973Smsmith    /* interface-specific accessor functions */
16951973Smsmith    int			mlx_iftype;	/* interface protocol */
17058188Smsmith#define MLX_IFTYPE_2	2
17151973Smsmith#define MLX_IFTYPE_3	3
17251973Smsmith#define MLX_IFTYPE_4	4
17351973Smsmith#define MLX_IFTYPE_5	5
17451973Smsmith    int			(* mlx_tryqueue)(struct mlx_softc *sc, struct mlx_command *mc);
17551973Smsmith    int			(* mlx_findcomplete)(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
17651973Smsmith    void		(* mlx_intaction)(struct mlx_softc *sc, int action);
177240608Sjhb    int			(* mlx_fw_handshake)(struct mlx_softc *sc, int *error, int *param1, int *param2, int first);
17851973Smsmith#define MLX_INTACTION_DISABLE		0
17951973Smsmith#define MLX_INTACTION_ENABLE		1
18051973Smsmith};
18151973Smsmith
182240608Sjhb#define	MLX_IO_LOCK(sc)			mtx_lock(&(sc)->mlx_io_lock)
183240608Sjhb#define	MLX_IO_UNLOCK(sc)		mtx_unlock(&(sc)->mlx_io_lock)
184240608Sjhb#define	MLX_IO_ASSERT_LOCKED(sc)	mtx_assert(&(sc)->mlx_io_lock, MA_OWNED)
185240608Sjhb#define	MLX_CONFIG_LOCK(sc)		sx_xlock(&(sc)->mlx_config_lock)
186240608Sjhb#define	MLX_CONFIG_UNLOCK(sc)		sx_xunlock(&(sc)->mlx_config_lock)
187240608Sjhb#define	MLX_CONFIG_ASSERT_LOCKED(sc)	sx_assert(&(sc)->mlx_config_lock, SA_XLOCKED)
18854419Smsmith
18954419Smsmith/*
19051973Smsmith * Interface between bus connections and driver core.
19151973Smsmith */
19251973Smsmithextern void		mlx_free(struct mlx_softc *sc);
19351973Smsmithextern int		mlx_attach(struct mlx_softc *sc);
19451973Smsmithextern void		mlx_startup(struct mlx_softc *sc);
19551973Smsmithextern void		mlx_intr(void *data);
19651973Smsmithextern int		mlx_detach(device_t dev);
19751973Smsmithextern int		mlx_shutdown(device_t dev);
19851973Smsmithextern int		mlx_suspend(device_t dev);
19951973Smsmithextern int		mlx_resume(device_t dev);
20051973Smsmithextern d_open_t		mlx_open;
20151973Smsmithextern d_close_t	mlx_close;
20251973Smsmithextern d_ioctl_t	mlx_ioctl;
20351973Smsmith
20451973Smsmithextern devclass_t	mlx_devclass;
20559136Smsmithextern devclass_t	mlxd_devclass;
20651973Smsmith
20751973Smsmith/*
20851973Smsmith * Mylex System Disk driver
20951973Smsmith */
21051973Smsmithstruct mlxd_softc
21151973Smsmith{
21251973Smsmith    device_t		mlxd_dev;
21351973Smsmith    struct mlx_softc	*mlxd_controller;
21451973Smsmith    struct mlx_sysdrive	*mlxd_drive;
215125975Sphk    struct disk		*mlxd_disk;
21651973Smsmith    int			mlxd_unit;
21751973Smsmith    int			mlxd_flags;
21851973Smsmith#define MLXD_OPEN	(1<<0)		/* drive is open (can't shut down) */
21951973Smsmith};
22051973Smsmith
22151973Smsmith/*
22251973Smsmith * Interface between driver core and disk driver (should be using a bus?)
22351973Smsmith */
224240963Sjhbextern int	mlx_submit_buf(struct mlx_softc *sc, struct bio *bp);
22583366Sjulianextern int	mlx_submit_ioctl(struct mlx_softc *sc,
22683366Sjulian			struct mlx_sysdrive *drive, u_long cmd,
22783366Sjulian			caddr_t addr, int32_t flag, struct thread *td);
228240963Sjhbextern void	mlxd_intr(struct bio *bp);
22951973Smsmith
23051973Smsmith
231