amrvar.h revision 120988
119878Swollman/*-
22742Swollman * Copyright (c) 1999,2000 Michael Smith
32742Swollman * Copyright (c) 2000 BSDi
42742Swollman * All rights reserved.
52742Swollman *
62742Swollman * Redistribution and use in source and binary forms, with or without
72742Swollman * modification, are permitted provided that the following conditions
82742Swollman * are met:
92742Swollman * 1. Redistributions of source code must retain the above copyright
102742Swollman *    notice, this list of conditions and the following disclaimer.
112742Swollman * 2. Redistributions in binary form must reproduce the above copyright
122742Swollman *    notice, this list of conditions and the following disclaimer in the
132742Swollman *    documentation and/or other materials provided with the distribution.
142742Swollman *
152742Swollman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
162742Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
172742Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
182742Swollman * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
192742Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
202742Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
212742Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
222742Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
239908Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
242742Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
252742Swollman * SUCH DAMAGE.
262742Swollman *
279908Swollman * Copyright (c) 2002 Eric Moore
282742Swollman * Copyright (c) 2002 LSI Logic Corporation
292742Swollman * All rights reserved.
3014343Swollman *
3114343Swollman * Redistribution and use in source and binary forms, with or without
3214343Swollman * modification, are permitted provided that the following conditions
3314343Swollman * are met:
3414343Swollman * 1. Redistributions of source code must retain the above copyright
3514343Swollman *    notice, this list of conditions and the following disclaimer.
362742Swollman * 2. Redistributions in binary form must reproduce the above copyright
379908Swollman *    notice, this list of conditions and the following disclaimer in the
382742Swollman *    documentation and/or other materials provided with the distribution.
392742Swollman * 3. The party using or redistributing the source code and binary forms
4014343Swollman *    agrees to the disclaimer below and the terms and conditions set forth
4114343Swollman *    herein.
4214343Swollman *
4314343Swollman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
4414343Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4514343Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4614343Swollman * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4714343Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
482742Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
492742Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
509908Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
512742Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5214343Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5314343Swollman * SUCH DAMAGE.
5414343Swollman *
5514343Swollman *
5614343Swollman *      $FreeBSD: head/sys/dev/amr/amrvar.h 120988 2003-10-10 22:49:40Z ps $
5714343Swollman */
5814343Swollman
5914343Swollman#if __FreeBSD_version >= 500005
6014343Swollman# include <sys/taskqueue.h>
612742Swollman# include <geom/geom_disk.h>
622742Swollman#endif
632742Swollman
642742Swollman#ifdef AMR_DEBUG
6514343Swollman# define debug(level, fmt, args...)	do {if (level <= AMR_DEBUG) printf("%s: " fmt "\n", __func__ , ##args);} while(0)
662742Swollman# define debug_called(level)		do {if (level <= AMR_DEBUG) printf("%s: called\n", __func__);} while(0)
672742Swollman#else
689908Swollman# define debug(level, fmt, args...)
692742Swollman# define debug_called(level)
7014343Swollman#endif
7114343Swollman#define xdebug(fmt, args...)	printf("%s: " fmt "\n", __func__ , ##args)
7214343Swollman
7314343Swollman/*
7414343Swollman * Per-logical-drive datastructure
7514343Swollman */
7614343Swollmanstruct amr_logdrive
7714343Swollman{
7814343Swollman    u_int32_t	al_size;
7914343Swollman    int		al_state;
8014343Swollman    int		al_properties;
8114343Swollman
8214343Swollman    /* synthetic geometry */
832742Swollman    int		al_cylinders;
842742Swollman    int		al_heads;
852742Swollman    int		al_sectors;
8614343Swollman
872742Swollman    /* driver */
882742Swollman    device_t	al_disk;
899908Swollman};
902742Swollman
9114343Swollman/*
9214343Swollman * Due to the difficulty of using the zone allocator to create a new
9314343Swollman * zone from within a module, we use our own clustering to reduce
9414343Swollman * memory wastage due to allocating lots of these small structures.
9514343Swollman *
9614343Swollman * 16k gives us a little under 200 command structures, which should
9714343Swollman * normally be plenty.  We will grab more if we need them.
9814343Swollman */
992742Swollman
1002742Swollman#define AMR_CMD_CLUSTERSIZE	(16 * 1024)
1012742Swollman
10214343Swollman/*
1032742Swollman * Per-command control structure.
1042742Swollman */
1059908Swollmanstruct amr_command
1062742Swollman{
10714343Swollman    TAILQ_ENTRY(amr_command)	ac_link;
10814343Swollman
10914343Swollman    struct amr_softc		*ac_sc;
11014343Swollman    u_int8_t			ac_slot;
11114343Swollman    int				ac_status;	/* command completion status */
11214343Swollman    struct amr_mailbox		ac_mailbox;
11314343Swollman    int				ac_flags;
11414343Swollman#define AMR_CMD_DATAIN		(1<<0)
11514343Swollman#define AMR_CMD_DATAOUT		(1<<1)
11614343Swollman#define AMR_CMD_CCB_DATAIN	(1<<2)
1172742Swollman#define AMR_CMD_CCB_DATAOUT	(1<<3)
1182742Swollman#define AMR_CMD_PRIORITY	(1<<4)
1192742Swollman#define AMR_CMD_MAPPED		(1<<5)
12014343Swollman#define AMR_CMD_SLEEP		(1<<6)
1212742Swollman#define AMR_CMD_BUSY		(1<<7)
1222742Swollman
1232742Swollman    struct bio			*ac_bio;
1242742Swollman
1252742Swollman    void			*ac_data;
12614343Swollman    size_t			ac_length;
1272742Swollman    bus_dmamap_t		ac_dmamap;
1288029Swollman    u_int32_t			ac_dataphys;
12914343Swollman
13014343Swollman    void			*ac_ccb_data;
13114343Swollman    size_t			ac_ccb_length;
13214343Swollman    bus_dmamap_t		ac_ccb_dmamap;
13314343Swollman    u_int32_t			ac_ccb_dataphys;
13414343Swollman
13514343Swollman    void			(* ac_complete)(struct amr_command *ac);
13614343Swollman    void			*ac_private;
13714343Swollman};
13814343Swollman
1392742Swollmanstruct amr_command_cluster
1402742Swollman{
14114343Swollman    TAILQ_ENTRY(amr_command_cluster)	acc_link;
1428029Swollman    struct amr_command		acc_command[0];
14314343Swollman};
14414343Swollman
1452742Swollman#define AMR_CMD_CLUSTERCOUNT	((AMR_CMD_CLUSTERSIZE - sizeof(struct amr_command_cluster)) /	\
14619878Swollman				 sizeof(struct amr_command))
1472742Swollman
1482742Swollman/*
14914343Swollman * Per-controller-instance data
1502742Swollman */
1512742Swollmanstruct amr_softc
15214343Swollman{
15314343Swollman    /* bus attachments */
15414343Swollman    device_t			amr_dev;
15514343Swollman    struct resource		*amr_reg;		/* control registers */
1562742Swollman    bus_space_handle_t		amr_bhandle;
1572742Swollman    bus_space_tag_t		amr_btag;
1582742Swollman    bus_dma_tag_t		amr_parent_dmat;	/* parent DMA tag */
1592742Swollman    bus_dma_tag_t		amr_buffer_dmat;	/* data buffer DMA tag */
1602742Swollman    struct resource		*amr_irq;		/* interrupt */
1612742Swollman    void			*amr_intr;
16219878Swollman
16319878Swollman    /* mailbox */
16419878Swollman    volatile struct amr_mailbox		*amr_mailbox;
1652742Swollman    volatile struct amr_mailbox64	*amr_mailbox64;
1662742Swollman    u_int32_t			amr_mailboxphys;
16719878Swollman    bus_dma_tag_t		amr_mailbox_dmat;
16819878Swollman    bus_dmamap_t		amr_mailbox_dmamap;
1692742Swollman
1702742Swollman    /* scatter/gather lists and their controller-visible mappings */
1712742Swollman    struct amr_sgentry		*amr_sgtable;		/* s/g lists */
1722742Swollman    u_int32_t			amr_sgbusaddr;		/* s/g table base address in bus space */
17319878Swollman    bus_dma_tag_t		amr_sg_dmat;		/* s/g buffer DMA tag */
1742742Swollman    bus_dmamap_t		amr_sg_dmamap;		/* map for s/g buffers */
1752742Swollman
1762742Swollman    /* controller limits and features */
1772742Swollman    int				amr_maxio;		/* maximum number of I/O transactions */
17819878Swollman    int				amr_maxdrives;		/* max number of logical drives */
1792742Swollman    int				amr_maxchan;		/* count of SCSI channels */
1802742Swollman
1812742Swollman    /* connected logical drives */
1822742Swollman    struct amr_logdrive		amr_drive[AMR_MAXLD];
18319878Swollman
1842742Swollman    /* controller state */
18519878Swollman    int				amr_state;
1862742Swollman#define AMR_STATE_OPEN		(1<<0)
18719878Swollman#define AMR_STATE_SUSPEND	(1<<1)
1882742Swollman#define AMR_STATE_INTEN		(1<<2)
1892742Swollman#define AMR_STATE_SHUTDOWN	(1<<3)
1902742Swollman
1912742Swollman    /* per-controller queues */
1922742Swollman    struct bio_queue_head 	amr_bioq;		/* pending I/O with no commands */
1932742Swollman    TAILQ_HEAD(,amr_command)	amr_ready;		/* commands ready to be submitted */
1942742Swollman    struct amr_command		*amr_busycmd[AMR_MAXCMD];
19514343Swollman    int				amr_busyslots;
19614343Swollman    TAILQ_HEAD(,amr_command)	amr_completed;
1972742Swollman    TAILQ_HEAD(,amr_command)	amr_freecmds;
1982742Swollman    TAILQ_HEAD(,amr_command_cluster)	amr_cmd_clusters;
19914343Swollman
20014343Swollman    /* CAM attachments for passthrough */
2012742Swollman    struct cam_sim		*amr_cam_sim[AMR_MAX_CHANNELS];
2022742Swollman    TAILQ_HEAD(, ccb_hdr)	amr_cam_ccbq;
20314343Swollman
20414343Swollman    /* control device */
2052742Swollman    dev_t			amr_dev_t;
20614343Swollman
20714343Swollman    /* controller type-specific support */
20814343Swollman    int				amr_type;
2092742Swollman#define AMR_TYPE_QUARTZ		(1<<0)
2102742Swollman#define AMR_IS_QUARTZ(sc)	((sc)->amr_type & AMR_TYPE_QUARTZ)
2112742Swollman#define AMR_TYPE_40LD		(1<<1)
21219878Swollman#define AMR_IS_40LD(sc)		((sc)->amr_type & AMR_TYPE_40LD)
2132742Swollman    int				(* amr_submit_command)(struct amr_softc *sc);
21419878Swollman    int				(* amr_get_work)(struct amr_softc *sc, struct amr_mailbox *mbsave);
21519878Swollman    int				(*amr_poll_command)(struct amr_command *ac);
21619878Swollman    int 			support_ext_cdb;	/* greater than 10 byte cdb support */
2172742Swollman
21819878Swollman    /* misc glue */
21919878Swollman    struct intr_config_hook	amr_ich;		/* wait-for-interrupts probe hook */
22019878Swollman    struct callout_handle	amr_timeout;		/* periodic status check */
2212742Swollman#if __FreeBSD_version >= 500005
22214343Swollman    struct task			amr_task_complete;	/* deferred-completion task */
22314343Swollman#endif
22414343Swollman};
22519878Swollman
22619878Swollman/*
22714343Swollman * Interface between bus connections and driver core.
22814343Swollman */
22914343Swollmanextern int              amr_attach(struct amr_softc *sc);
23014343Swollmanextern void		amr_free(struct amr_softc *sc);
23119878Swollmanextern int		amr_flush(struct amr_softc *sc);
23219878Swollmanextern int		amr_done(struct amr_softc *sc);
23314343Swollmanextern void		amr_startio(struct amr_softc *sc);
23419878Swollman
23519878Swollman/*
23619878Swollman * Command buffer allocation.
23714343Swollman */
23814343Swollmanextern struct amr_command	*amr_alloccmd(struct amr_softc *sc);
23914343Swollmanextern void			amr_releasecmd(struct amr_command *ac);
24014343Swollman
24119878Swollman/*
24219878Swollman * CAM interface
24314343Swollman */
24419878Swollmanextern int		amr_cam_attach(struct amr_softc *sc);
24514343Swollmanextern void		amr_cam_detach(struct amr_softc *sc);
24619878Swollmanextern int		amr_cam_command(struct amr_softc *sc, struct amr_command **acp);
24714343Swollman
24819878Swollman/*
24919878Swollman * MegaRAID logical disk driver
25014343Swollman */
2512742Swollmanstruct amrd_softc
2522742Swollman{
2532742Swollman    device_t		amrd_dev;
25419878Swollman    struct amr_softc	*amrd_controller;
2552742Swollman    struct amr_logdrive	*amrd_drive;
25619878Swollman    struct disk		amrd_disk;
25719878Swollman    int			amrd_unit;
2582742Swollman};
2592742Swollman
2602742Swollman/*
26119878Swollman * Interface between driver core and disk driver (should be using a bus?)
26219878Swollman */
2632742Swollmanextern int	amr_submit_bio(struct amr_softc *sc, struct bio *bio);
2642742Swollmanextern int 	amr_dump_blocks(struct amr_softc *sc, int unit, u_int32_t lba, void *data, int blks);
2652742Swollmanextern void	amrd_intr(void *data);
2662742Swollman
2672742Swollman/********************************************************************************
2682742Swollman * Enqueue/dequeue functions
2692742Swollman */
2702742Swollmanstatic __inline void
2712742Swollmanamr_enqueue_bio(struct amr_softc *sc, struct bio *bio)
2722742Swollman{
2732742Swollman    int		s;
2742742Swollman
27514343Swollman    s = splbio();
2762742Swollman    bioq_insert_tail(&sc->amr_bioq, bio);
27714343Swollman    splx(s);
27814343Swollman}
2792742Swollman
28014343Swollmanstatic __inline struct bio *
28114343Swollmanamr_dequeue_bio(struct amr_softc *sc)
28214343Swollman{
28314343Swollman    struct bio	*bio;
28414343Swollman    int		s;
2859908Swollman
2869908Swollman    s = splbio();
2879908Swollman    if ((bio = bioq_first(&sc->amr_bioq)) != NULL)
2889908Swollman	bioq_remove(&sc->amr_bioq, bio);
2899908Swollman    splx(s);
2909908Swollman    return(bio);
2919908Swollman}
2922742Swollman
2932742Swollmanstatic __inline void
29414343Swollmanamr_enqueue_ready(struct amr_command *ac)
2952742Swollman{
29619878Swollman    int		s;
2972742Swollman
2988029Swollman    s = splbio();
2992742Swollman    TAILQ_INSERT_TAIL(&ac->ac_sc->amr_ready, ac, ac_link);
30019878Swollman    splx(s);
3012742Swollman}
3022742Swollman
3032742Swollmanstatic __inline void
3042742Swollmanamr_requeue_ready(struct amr_command *ac)
3052742Swollman{
3062742Swollman    int		s;
3072742Swollman
30819878Swollman    s = splbio();
30919878Swollman    TAILQ_INSERT_HEAD(&ac->ac_sc->amr_ready, ac, ac_link);
31019878Swollman    splx(s);
3112742Swollman}
3122742Swollman
3132742Swollmanstatic __inline struct amr_command *
3142742Swollmanamr_dequeue_ready(struct amr_softc *sc)
31519878Swollman{
31619878Swollman    struct amr_command	*ac;
3172742Swollman    int			s;
3189908Swollman
3199908Swollman    s = splbio();
3209908Swollman    if ((ac = TAILQ_FIRST(&sc->amr_ready)) != NULL)
32119878Swollman	TAILQ_REMOVE(&sc->amr_ready, ac, ac_link);
3229908Swollman    splx(s);
3232742Swollman    return(ac);
32414343Swollman}
3252742Swollman
3262742Swollmanstatic __inline void
3272742Swollmanamr_enqueue_completed(struct amr_command *ac)
3282742Swollman{
32919878Swollman    int		s;
33019878Swollman
3312742Swollman    s = splbio();
3322742Swollman    TAILQ_INSERT_TAIL(&ac->ac_sc->amr_completed, ac, ac_link);
3332742Swollman    splx(s);
3342742Swollman}
33519878Swollman
3362742Swollmanstatic __inline struct amr_command *
33714343Swollmanamr_dequeue_completed(struct amr_softc *sc)
33814343Swollman{
33914343Swollman    struct amr_command	*ac;
34019878Swollman    int			s;
34114343Swollman
34214343Swollman    s = splbio();
34314343Swollman    if ((ac = TAILQ_FIRST(&sc->amr_completed)) != NULL)
34414343Swollman	TAILQ_REMOVE(&sc->amr_completed, ac, ac_link);
34514343Swollman    splx(s);
34614343Swollman    return(ac);
34714343Swollman}
34819878Swollman
34919878Swollmanstatic __inline void
35014343Swollmanamr_enqueue_free(struct amr_command *ac)
3512742Swollman{
3522742Swollman    int		s;
3532742Swollman
3542742Swollman    s = splbio();
35519878Swollman    TAILQ_INSERT_TAIL(&ac->ac_sc->amr_freecmds, ac, ac_link);
3562742Swollman    splx(s);
3572742Swollman}
3582742Swollman
3592742Swollmanstatic __inline struct amr_command *
36019878Swollmanamr_dequeue_free(struct amr_softc *sc)
3612742Swollman{
3622742Swollman    struct amr_command	*ac;
3632742Swollman    int			s;
3642742Swollman
36519878Swollman    s = splbio();
36619878Swollman    if ((ac = TAILQ_FIRST(&sc->amr_freecmds)) != NULL)
3672742Swollman	TAILQ_REMOVE(&sc->amr_freecmds, ac, ac_link);
3682742Swollman    splx(s);
3692742Swollman    return(ac);
3702742Swollman}
37119878Swollman