151974Smsmith/*-
265245Smsmith * Copyright (c) 1999,2000 Michael Smith
365245Smsmith * Copyright (c) 2000 BSDi
451974Smsmith * All rights reserved.
551974Smsmith *
651974Smsmith * Redistribution and use in source and binary forms, with or without
751974Smsmith * modification, are permitted provided that the following conditions
851974Smsmith * are met:
951974Smsmith * 1. Redistributions of source code must retain the above copyright
1051974Smsmith *    notice, this list of conditions and the following disclaimer.
1151974Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1251974Smsmith *    notice, this list of conditions and the following disclaimer in the
1351974Smsmith *    documentation and/or other materials provided with the distribution.
1451974Smsmith *
1551974Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1651974Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1751974Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1851974Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1951974Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2051974Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2151974Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2251974Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2351974Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2451974Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2551974Smsmith * SUCH DAMAGE.
2651974Smsmith *
27106225Semoore * Copyright (c) 2002 Eric Moore
28106225Semoore * Copyright (c) 2002 LSI Logic Corporation
29106225Semoore * All rights reserved.
30106225Semoore *
31106225Semoore * Redistribution and use in source and binary forms, with or without
32106225Semoore * modification, are permitted provided that the following conditions
33106225Semoore * are met:
34106225Semoore * 1. Redistributions of source code must retain the above copyright
35106225Semoore *    notice, this list of conditions and the following disclaimer.
36106225Semoore * 2. Redistributions in binary form must reproduce the above copyright
37106225Semoore *    notice, this list of conditions and the following disclaimer in the
38106225Semoore *    documentation and/or other materials provided with the distribution.
39105419Semoore * 3. The party using or redistributing the source code and binary forms
40106225Semoore *    agrees to the disclaimer below and the terms and conditions set forth
41105419Semoore *    herein.
42105419Semoore *
43106225Semoore * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
44106225Semoore * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45106225Semoore * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46106225Semoore * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
47106225Semoore * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48106225Semoore * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49106225Semoore * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50106225Semoore * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51106225Semoore * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52106225Semoore * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53106225Semoore * SUCH DAMAGE.
54105419Semoore *
55106225Semoore *
5651974Smsmith *      $FreeBSD$
5751974Smsmith */
5851974Smsmith
59148841Sscottl#include <geom/geom_disk.h>
60148841Sscottl#include <sys/lock.h>
61148841Sscottl#include <sys/mutex.h>
6251974Smsmith
63153409Sscottl#define LSI_DESC_PCI "LSILogic MegaRAID 1.53"
64140688Sscottl
6565245Smsmith#ifdef AMR_DEBUG
6687599Sobrien# define debug(level, fmt, args...)	do {if (level <= AMR_DEBUG) printf("%s: " fmt "\n", __func__ , ##args);} while(0)
6787599Sobrien# define debug_called(level)		do {if (level <= AMR_DEBUG) printf("%s: called\n", __func__);} while(0)
6865245Smsmith#else
69210570Smdf# define debug(level, fmt, args...)	do {} while (0)
70210570Smdf# define debug_called(level)		do {} while (0)
7165245Smsmith#endif
7287599Sobrien#define xdebug(fmt, args...)	printf("%s: " fmt "\n", __func__ , ##args)
7351974Smsmith
7451974Smsmith/*
7551974Smsmith * Per-logical-drive datastructure
7651974Smsmith */
7751974Smsmithstruct amr_logdrive
7851974Smsmith{
7951974Smsmith    u_int32_t	al_size;
8051974Smsmith    int		al_state;
8151974Smsmith    int		al_properties;
8251974Smsmith
8351974Smsmith    /* synthetic geometry */
8451974Smsmith    int		al_cylinders;
8551974Smsmith    int		al_heads;
8651974Smsmith    int		al_sectors;
8751974Smsmith
8851974Smsmith    /* driver */
8951974Smsmith    device_t	al_disk;
9051974Smsmith};
9151974Smsmith
9265245Smsmith/*
9365245Smsmith * Due to the difficulty of using the zone allocator to create a new
9465245Smsmith * zone from within a module, we use our own clustering to reduce
9565245Smsmith * memory wastage due to allocating lots of these small structures.
9665245Smsmith *
9765245Smsmith * 16k gives us a little under 200 command structures, which should
9865245Smsmith * normally be plenty.  We will grab more if we need them.
9965245Smsmith */
10051974Smsmith
10165245Smsmith#define AMR_CMD_CLUSTERSIZE	(16 * 1024)
10265245Smsmith
103175622Sscottltypedef STAILQ_HEAD(, amr_command)	ac_qhead_t;
104175622Sscottltypedef STAILQ_ENTRY(amr_command)	ac_link_t;
105175622Sscottl
106174544Sscottlunion amr_ccb {
107174544Sscottl    struct amr_passthrough	ccb_pthru;
108174544Sscottl    struct amr_ext_passthrough	ccb_epthru;
109174544Sscottl    uint8_t			bytes[128];
110174544Sscottl};
111174544Sscottl
11251974Smsmith/*
11351974Smsmith * Per-command control structure.
11451974Smsmith */
11551974Smsmithstruct amr_command
11651974Smsmith{
117175622Sscottl    ac_link_t			ac_link;
11851974Smsmith
11951974Smsmith    struct amr_softc		*ac_sc;
12051974Smsmith    u_int8_t			ac_slot;
12165245Smsmith    int				ac_status;	/* command completion status */
122153409Sscottl    union {
123153409Sscottl	struct amr_sgentry	*sg32;
124153409Sscottl	struct amr_sg64entry	*sg64;
125153409Sscottl    } ac_sg;
126153409Sscottl    u_int32_t			ac_sgbusaddr;
127153409Sscottl    u_int32_t			ac_sg64_lo;
128153409Sscottl    u_int32_t			ac_sg64_hi;
12951974Smsmith    struct amr_mailbox		ac_mailbox;
13051974Smsmith    int				ac_flags;
13151974Smsmith#define AMR_CMD_DATAIN		(1<<0)
13251974Smsmith#define AMR_CMD_DATAOUT		(1<<1)
133174544Sscottl#define AMR_CMD_CCB		(1<<2)
13465245Smsmith#define AMR_CMD_PRIORITY	(1<<4)
13565245Smsmith#define AMR_CMD_MAPPED		(1<<5)
13665245Smsmith#define AMR_CMD_SLEEP		(1<<6)
13765245Smsmith#define AMR_CMD_BUSY		(1<<7)
138153409Sscottl#define AMR_CMD_SG64		(1<<8)
139153409Sscottl#define AC_IS_SG64(ac)		((ac)->ac_flags & AMR_CMD_SG64)
140175622Sscottl    u_int			ac_retries;
14151974Smsmith
14265245Smsmith    struct bio			*ac_bio;
143153409Sscottl    void			(* ac_complete)(struct amr_command *ac);
144153409Sscottl    void			*ac_private;
14565245Smsmith
14651974Smsmith    void			*ac_data;
14751974Smsmith    size_t			ac_length;
14851974Smsmith    bus_dmamap_t		ac_dmamap;
149153409Sscottl    bus_dmamap_t		ac_dma64map;
15051974Smsmith
151174544Sscottl    bus_dma_tag_t		ac_tag;
152174544Sscottl    bus_dmamap_t		ac_datamap;
153174544Sscottl    int				ac_nsegments;
154174544Sscottl    uint32_t			ac_mb_physaddr;
15565245Smsmith
156174544Sscottl    union amr_ccb		*ac_ccb;
157174544Sscottl    uint32_t			ac_ccb_busaddr;
15851974Smsmith};
15951974Smsmith
16065245Smsmithstruct amr_command_cluster
16165245Smsmith{
16265245Smsmith    TAILQ_ENTRY(amr_command_cluster)	acc_link;
16365245Smsmith    struct amr_command		acc_command[0];
16465245Smsmith};
16565245Smsmith
16665245Smsmith#define AMR_CMD_CLUSTERCOUNT	((AMR_CMD_CLUSTERSIZE - sizeof(struct amr_command_cluster)) /	\
16765245Smsmith				 sizeof(struct amr_command))
16865245Smsmith
16965245Smsmith/*
17065245Smsmith * Per-controller-instance data
17165245Smsmith */
17251974Smsmithstruct amr_softc
17351974Smsmith{
17451974Smsmith    /* bus attachments */
17551974Smsmith    device_t			amr_dev;
17651974Smsmith    struct resource		*amr_reg;		/* control registers */
17751974Smsmith    bus_space_handle_t		amr_bhandle;
17851974Smsmith    bus_space_tag_t		amr_btag;
17951974Smsmith    bus_dma_tag_t		amr_parent_dmat;	/* parent DMA tag */
18051974Smsmith    bus_dma_tag_t		amr_buffer_dmat;	/* data buffer DMA tag */
181153409Sscottl    bus_dma_tag_t		amr_buffer64_dmat;
18251974Smsmith    struct resource		*amr_irq;		/* interrupt */
18351974Smsmith    void			*amr_intr;
18451974Smsmith
18551974Smsmith    /* mailbox */
18658496Smsmith    volatile struct amr_mailbox		*amr_mailbox;
18758496Smsmith    volatile struct amr_mailbox64	*amr_mailbox64;
18851974Smsmith    u_int32_t			amr_mailboxphys;
18951974Smsmith    bus_dma_tag_t		amr_mailbox_dmat;
19051974Smsmith    bus_dmamap_t		amr_mailbox_dmamap;
19151974Smsmith
19251974Smsmith    /* scatter/gather lists and their controller-visible mappings */
19351974Smsmith    struct amr_sgentry		*amr_sgtable;		/* s/g lists */
194153409Sscottl    struct amr_sg64entry	*amr_sg64table;		/* 64bit s/g lists */
19551974Smsmith    u_int32_t			amr_sgbusaddr;		/* s/g table base address in bus space */
19651974Smsmith    bus_dma_tag_t		amr_sg_dmat;		/* s/g buffer DMA tag */
19751974Smsmith    bus_dmamap_t		amr_sg_dmamap;		/* map for s/g buffers */
19851974Smsmith
199174544Sscottl    union amr_ccb		*amr_ccb;
200174544Sscottl    uint32_t			amr_ccb_busaddr;
201174544Sscottl    bus_dma_tag_t		amr_ccb_dmat;
202174544Sscottl    bus_dmamap_t		amr_ccb_dmamap;
203174544Sscottl
20451974Smsmith    /* controller limits and features */
205140340Sscottl    int				amr_nextslot;		/* Next slot to use for newly allocated commands */
20651974Smsmith    int				amr_maxio;		/* maximum number of I/O transactions */
20751974Smsmith    int				amr_maxdrives;		/* max number of logical drives */
20865245Smsmith    int				amr_maxchan;		/* count of SCSI channels */
20951974Smsmith
21051974Smsmith    /* connected logical drives */
21151974Smsmith    struct amr_logdrive		amr_drive[AMR_MAXLD];
21251974Smsmith
21365245Smsmith    /* controller state */
21451974Smsmith    int				amr_state;
21551974Smsmith#define AMR_STATE_OPEN		(1<<0)
21651974Smsmith#define AMR_STATE_SUSPEND	(1<<1)
21751974Smsmith#define AMR_STATE_INTEN		(1<<2)
21851974Smsmith#define AMR_STATE_SHUTDOWN	(1<<3)
219131394Sps#define AMR_STATE_CRASHDUMP	(1<<4)
220138422Sscottl#define AMR_STATE_QUEUE_FRZN	(1<<5)
221153409Sscottl#define AMR_STATE_LD_DELETE	(1<<6)
222153409Sscottl#define AMR_STATE_REMAP_LD	(1<<7)
22351974Smsmith
22451974Smsmith    /* per-controller queues */
22565245Smsmith    struct bio_queue_head 	amr_bioq;		/* pending I/O with no commands */
226175622Sscottl    ac_qhead_t			amr_ready;		/* commands ready to be submitted */
22751974Smsmith    struct amr_command		*amr_busycmd[AMR_MAXCMD];
22865245Smsmith    int				amr_busyslots;
229175622Sscottl    ac_qhead_t			amr_freecmds;
23065245Smsmith    TAILQ_HEAD(,amr_command_cluster)	amr_cmd_clusters;
23151974Smsmith
23265245Smsmith    /* CAM attachments for passthrough */
23365245Smsmith    struct cam_sim		*amr_cam_sim[AMR_MAX_CHANNELS];
23465245Smsmith    TAILQ_HEAD(, ccb_hdr)	amr_cam_ccbq;
235139952Sdwhite    struct cam_devq		*amr_cam_devq;
23658883Smsmith
23765245Smsmith    /* control device */
238153409Sscottl    struct cdev			*amr_dev_t;
239153409Sscottl    struct mtx			amr_list_lock;
24065245Smsmith
24151974Smsmith    /* controller type-specific support */
24251974Smsmith    int				amr_type;
24365245Smsmith#define AMR_TYPE_QUARTZ		(1<<0)
24465245Smsmith#define AMR_IS_QUARTZ(sc)	((sc)->amr_type & AMR_TYPE_QUARTZ)
24565245Smsmith#define AMR_TYPE_40LD		(1<<1)
24665245Smsmith#define AMR_IS_40LD(sc)		((sc)->amr_type & AMR_TYPE_40LD)
247153409Sscottl#define AMR_TYPE_SG64		(1<<2)
248153409Sscottl#define AMR_IS_SG64(sc)		((sc)->amr_type & AMR_TYPE_SG64)
249155222Sps    int				(* amr_submit_command)(struct amr_command *ac);
25051974Smsmith    int				(* amr_get_work)(struct amr_softc *sc, struct amr_mailbox *mbsave);
251107756Semoore    int				(*amr_poll_command)(struct amr_command *ac);
252138422Sscottl    int				(*amr_poll_command1)(struct amr_softc *sc, struct amr_command *ac);
253107756Semoore    int 			support_ext_cdb;	/* greater than 10 byte cdb support */
25465245Smsmith
25565245Smsmith    /* misc glue */
256184573Sscottl    device_t			amr_pass;
257184573Sscottl    int				(*amr_cam_command)(struct amr_softc *sc, struct amr_command **acp);
25865245Smsmith    struct intr_config_hook	amr_ich;		/* wait-for-interrupts probe hook */
259153409Sscottl    int				amr_allow_vol_config;
260153409Sscottl    int				amr_linux_no_adapters;
261153409Sscottl    int				amr_ld_del_supported;
262153409Sscottl    struct mtx			amr_hw_lock;
26351974Smsmith};
26451974Smsmith
26551974Smsmith/*
26665245Smsmith * Interface between bus connections and driver core.
26758883Smsmith */
26865245Smsmithextern int              amr_attach(struct amr_softc *sc);
26965245Smsmithextern void		amr_free(struct amr_softc *sc);
27065245Smsmithextern int		amr_flush(struct amr_softc *sc);
27165245Smsmithextern int		amr_done(struct amr_softc *sc);
27265245Smsmithextern void		amr_startio(struct amr_softc *sc);
27358883Smsmith
27458883Smsmith/*
27565245Smsmith * Command buffer allocation.
27651974Smsmith */
27765245Smsmithextern struct amr_command	*amr_alloccmd(struct amr_softc *sc);
27865245Smsmithextern void			amr_releasecmd(struct amr_command *ac);
27951974Smsmith
28051974Smsmith/*
28151974Smsmith * MegaRAID logical disk driver
28251974Smsmith */
28351974Smsmithstruct amrd_softc
28451974Smsmith{
28551974Smsmith    device_t		amrd_dev;
28651974Smsmith    struct amr_softc	*amrd_controller;
28751974Smsmith    struct amr_logdrive	*amrd_drive;
288125975Sphk    struct disk		*amrd_disk;
28951974Smsmith    int			amrd_unit;
29051974Smsmith};
29151974Smsmith
29251974Smsmith/*
29351974Smsmith * Interface between driver core and disk driver (should be using a bus?)
29451974Smsmith */
29565245Smsmithextern int	amr_submit_bio(struct amr_softc *sc, struct bio *bio);
296120988Spsextern int 	amr_dump_blocks(struct amr_softc *sc, int unit, u_int32_t lba, void *data, int blks);
29751974Smsmithextern void	amrd_intr(void *data);
29851974Smsmith
29965245Smsmith/********************************************************************************
30065245Smsmith * Enqueue/dequeue functions
30165245Smsmith */
30265245Smsmithstatic __inline void
30365245Smsmithamr_enqueue_bio(struct amr_softc *sc, struct bio *bio)
30465245Smsmith{
30565245Smsmith
30665245Smsmith    bioq_insert_tail(&sc->amr_bioq, bio);
30765245Smsmith}
30865245Smsmith
30965245Smsmithstatic __inline struct bio *
31065245Smsmithamr_dequeue_bio(struct amr_softc *sc)
31165245Smsmith{
31265245Smsmith    struct bio	*bio;
31365245Smsmith
31465245Smsmith    if ((bio = bioq_first(&sc->amr_bioq)) != NULL)
31565245Smsmith	bioq_remove(&sc->amr_bioq, bio);
31665245Smsmith    return(bio);
31765245Smsmith}
31865245Smsmith
31965245Smsmithstatic __inline void
320175622Sscottlamr_init_qhead(ac_qhead_t *head)
321175622Sscottl{
322175622Sscottl
323175622Sscottl	STAILQ_INIT(head);
324175622Sscottl}
325175622Sscottl
326175622Sscottlstatic __inline void
32765245Smsmithamr_enqueue_ready(struct amr_command *ac)
32865245Smsmith{
32965245Smsmith
330175622Sscottl    STAILQ_INSERT_TAIL(&ac->ac_sc->amr_ready, ac, ac_link);
33165245Smsmith}
33265245Smsmith
33365245Smsmithstatic __inline void
33465245Smsmithamr_requeue_ready(struct amr_command *ac)
33565245Smsmith{
33665245Smsmith
337175622Sscottl    STAILQ_INSERT_HEAD(&ac->ac_sc->amr_ready, ac, ac_link);
33865245Smsmith}
33965245Smsmith
34065245Smsmithstatic __inline struct amr_command *
34165245Smsmithamr_dequeue_ready(struct amr_softc *sc)
34265245Smsmith{
34365245Smsmith    struct amr_command	*ac;
34465245Smsmith
345175622Sscottl    if ((ac = STAILQ_FIRST(&sc->amr_ready)) != NULL)
346175622Sscottl	STAILQ_REMOVE_HEAD(&sc->amr_ready, ac_link);
34765245Smsmith    return(ac);
34865245Smsmith}
34965245Smsmith
35065245Smsmithstatic __inline void
351175622Sscottlamr_enqueue_completed(struct amr_command *ac, ac_qhead_t *head)
35265245Smsmith{
35365245Smsmith
354175622Sscottl    STAILQ_INSERT_TAIL(head, ac, ac_link);
35565245Smsmith}
35665245Smsmith
35765245Smsmithstatic __inline struct amr_command *
358175622Sscottlamr_dequeue_completed(struct amr_softc *sc, ac_qhead_t *head)
35965245Smsmith{
36065245Smsmith    struct amr_command	*ac;
36165245Smsmith
362175622Sscottl    if ((ac = STAILQ_FIRST(head)) != NULL)
363175622Sscottl	STAILQ_REMOVE_HEAD(head, ac_link);
36465245Smsmith    return(ac);
36565245Smsmith}
36665245Smsmith
36765245Smsmithstatic __inline void
36865245Smsmithamr_enqueue_free(struct amr_command *ac)
36965245Smsmith{
37065245Smsmith
371175622Sscottl    STAILQ_INSERT_HEAD(&ac->ac_sc->amr_freecmds, ac, ac_link);
37265245Smsmith}
37365245Smsmith
37465245Smsmithstatic __inline struct amr_command *
37565245Smsmithamr_dequeue_free(struct amr_softc *sc)
37665245Smsmith{
37765245Smsmith    struct amr_command	*ac;
37865245Smsmith
379175622Sscottl    if ((ac = STAILQ_FIRST(&sc->amr_freecmds)) != NULL)
380175622Sscottl	STAILQ_REMOVE_HEAD(&sc->amr_freecmds, ac_link);
38165245Smsmith    return(ac);
38265245Smsmith}
383