amrvar.h revision 111250
1133359Sobrien/*-
2133359Sobrien * Copyright (c) 1999,2000 Michael Smith
3133359Sobrien * Copyright (c) 2000 BSDi
4133359Sobrien * All rights reserved.
5133359Sobrien *
6133359Sobrien * Redistribution and use in source and binary forms, with or without
7133359Sobrien * modification, are permitted provided that the following conditions
8133359Sobrien * are met:
9133359Sobrien * 1. Redistributions of source code must retain the above copyright
10133359Sobrien *    notice, this list of conditions and the following disclaimer.
11133359Sobrien * 2. Redistributions in binary form must reproduce the above copyright
12133359Sobrien *    notice, this list of conditions and the following disclaimer in the
13133359Sobrien *    documentation and/or other materials provided with the distribution.
14133359Sobrien *
15133359Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16133359Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17133359Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18133359Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19133359Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20133359Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21133359Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22133359Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23133359Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24133359Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25133359Sobrien * SUCH DAMAGE.
26133359Sobrien *
2768349Sobrien * Copyright (c) 2002 Eric Moore
2868349Sobrien * Copyright (c) 2002 LSI Logic Corporation
2968349Sobrien * All rights reserved.
3068349Sobrien *
3168349Sobrien * Redistribution and use in source and binary forms, with or without
3268349Sobrien * modification, are permitted provided that the following conditions
3368349Sobrien * are met:
3468349Sobrien * 1. Redistributions of source code must retain the above copyright
3568349Sobrien *    notice, this list of conditions and the following disclaimer.
3668349Sobrien * 2. Redistributions in binary form must reproduce the above copyright
3768349Sobrien *    notice, this list of conditions and the following disclaimer in the
38186690Sobrien *    documentation and/or other materials provided with the distribution.
3968349Sobrien * 3. The party using or redistributing the source code and binary forms
4068349Sobrien *    agrees to the disclaimer below and the terms and conditions set forth
41186690Sobrien *    herein.
4268349Sobrien *
4368349Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
4468349Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45169942Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46169942Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4768349Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48169942Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49186690Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50186690Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51186690Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52186690Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53159764Sobrien * SUCH DAMAGE.
5468349Sobrien *
55133359Sobrien *
5668349Sobrien *      $FreeBSD: head/sys/dev/amr/amrvar.h 111250 2003-02-22 10:10:12Z phk $
57159764Sobrien */
58159764Sobrien
59133359Sobrien#if __FreeBSD_version >= 500005
60133359Sobrien# include <sys/taskqueue.h>
61133359Sobrien#endif
62133359Sobrien
63133359Sobrien#ifdef AMR_DEBUG
64103373Sobrien# define debug(level, fmt, args...)	do {if (level <= AMR_DEBUG) printf("%s: " fmt "\n", __func__ , ##args);} while(0)
6568349Sobrien# define debug_called(level)		do {if (level <= AMR_DEBUG) printf("%s: called\n", __func__);} while(0)
6668349Sobrien#else
6768349Sobrien# define debug(level, fmt, args...)
6868349Sobrien# define debug_called(level)
6968349Sobrien#endif
7068349Sobrien#define xdebug(fmt, args...)	printf("%s: " fmt "\n", __func__ , ##args)
7168349Sobrien
7268349Sobrien/*
7368349Sobrien * Per-logical-drive datastructure
7468349Sobrien */
7568349Sobrienstruct amr_logdrive
7668349Sobrien{
7768349Sobrien    u_int32_t	al_size;
7868349Sobrien    int		al_state;
7968349Sobrien    int		al_properties;
8068349Sobrien
8168349Sobrien    /* synthetic geometry */
82133359Sobrien    int		al_cylinders;
83103373Sobrien    int		al_heads;
8468349Sobrien    int		al_sectors;
8568349Sobrien
8668349Sobrien    /* driver */
8768349Sobrien    device_t	al_disk;
8868349Sobrien};
8968349Sobrien
9068349Sobrien/*
9168349Sobrien * Due to the difficulty of using the zone allocator to create a new
9268349Sobrien * zone from within a module, we use our own clustering to reduce
9368349Sobrien * memory wastage due to allocating lots of these small structures.
9468349Sobrien *
9568349Sobrien * 16k gives us a little under 200 command structures, which should
9668349Sobrien * normally be plenty.  We will grab more if we need them.
9768349Sobrien */
9868349Sobrien
9968349Sobrien#define AMR_CMD_CLUSTERSIZE	(16 * 1024)
10068349Sobrien
10168349Sobrien/*
10268349Sobrien * Per-command control structure.
103133359Sobrien */
104103373Sobrienstruct amr_command
10568349Sobrien{
10668349Sobrien    TAILQ_ENTRY(amr_command)	ac_link;
10768349Sobrien
10868349Sobrien    struct amr_softc		*ac_sc;
10968349Sobrien    u_int8_t			ac_slot;
11068349Sobrien    int				ac_status;	/* command completion status */
11168349Sobrien    struct amr_mailbox		ac_mailbox;
11268349Sobrien    int				ac_flags;
11368349Sobrien#define AMR_CMD_DATAIN		(1<<0)
11468349Sobrien#define AMR_CMD_DATAOUT		(1<<1)
11568349Sobrien#define AMR_CMD_CCB_DATAIN	(1<<2)
11668349Sobrien#define AMR_CMD_CCB_DATAOUT	(1<<3)
11768349Sobrien#define AMR_CMD_PRIORITY	(1<<4)
11868349Sobrien#define AMR_CMD_MAPPED		(1<<5)
11968349Sobrien#define AMR_CMD_SLEEP		(1<<6)
12068349Sobrien#define AMR_CMD_BUSY		(1<<7)
12168349Sobrien
12268349Sobrien    struct bio			*ac_bio;
12368349Sobrien
12468349Sobrien    void			*ac_data;
12568349Sobrien    size_t			ac_length;
12668349Sobrien    bus_dmamap_t		ac_dmamap;
12768349Sobrien    u_int32_t			ac_dataphys;
128186690Sobrien
129186690Sobrien    void			*ac_ccb_data;
130159764Sobrien    size_t			ac_ccb_length;
131159764Sobrien    bus_dmamap_t		ac_ccb_dmamap;
132186690Sobrien    u_int32_t			ac_ccb_dataphys;
133186690Sobrien
134159764Sobrien    void			(* ac_complete)(struct amr_command *ac);
135159764Sobrien    void			*ac_private;
136159764Sobrien};
137159764Sobrien
138186690Sobrienstruct amr_command_cluster
139186690Sobrien{
14068349Sobrien    TAILQ_ENTRY(amr_command_cluster)	acc_link;
141186690Sobrien    struct amr_command		acc_command[0];
142186690Sobrien};
143111658Sobrien
144186690Sobrien#define AMR_CMD_CLUSTERCOUNT	((AMR_CMD_CLUSTERSIZE - sizeof(struct amr_command_cluster)) /	\
145186690Sobrien				 sizeof(struct amr_command))
146186690Sobrien
147186690Sobrien/*
148186690Sobrien * Per-controller-instance data
149186690Sobrien */
150186690Sobrienstruct amr_softc
151186690Sobrien{
152186690Sobrien    /* bus attachments */
153186690Sobrien    device_t			amr_dev;
154186690Sobrien    struct resource		*amr_reg;		/* control registers */
15568349Sobrien    bus_space_handle_t		amr_bhandle;
156186690Sobrien    bus_space_tag_t		amr_btag;
157186690Sobrien    bus_dma_tag_t		amr_parent_dmat;	/* parent DMA tag */
158111658Sobrien    bus_dma_tag_t		amr_buffer_dmat;	/* data buffer DMA tag */
159186690Sobrien    struct resource		*amr_irq;		/* interrupt */
160186690Sobrien    void			*amr_intr;
161186690Sobrien
162186690Sobrien    /* mailbox */
163186690Sobrien    volatile struct amr_mailbox		*amr_mailbox;
164186690Sobrien    volatile struct amr_mailbox64	*amr_mailbox64;
165186690Sobrien    u_int32_t			amr_mailboxphys;
166186690Sobrien    bus_dma_tag_t		amr_mailbox_dmat;
167186690Sobrien    bus_dmamap_t		amr_mailbox_dmamap;
168186690Sobrien
169186690Sobrien    /* scatter/gather lists and their controller-visible mappings */
170186690Sobrien    struct amr_sgentry		*amr_sgtable;		/* s/g lists */
171186690Sobrien    u_int32_t			amr_sgbusaddr;		/* s/g table base address in bus space */
172186690Sobrien    bus_dma_tag_t		amr_sg_dmat;		/* s/g buffer DMA tag */
173186690Sobrien    bus_dmamap_t		amr_sg_dmamap;		/* map for s/g buffers */
174186690Sobrien
175159764Sobrien    /* controller limits and features */
176186690Sobrien    int				amr_maxio;		/* maximum number of I/O transactions */
177186690Sobrien    int				amr_maxdrives;		/* max number of logical drives */
178186690Sobrien    int				amr_maxchan;		/* count of SCSI channels */
179186690Sobrien
180186690Sobrien    /* connected logical drives */
181133359Sobrien    struct amr_logdrive		amr_drive[AMR_MAXLD];
182186690Sobrien
183186690Sobrien    /* controller state */
184186690Sobrien    int				amr_state;
185186690Sobrien#define AMR_STATE_OPEN		(1<<0)
186186690Sobrien#define AMR_STATE_SUSPEND	(1<<1)
187186690Sobrien#define AMR_STATE_INTEN		(1<<2)
188186690Sobrien#define AMR_STATE_SHUTDOWN	(1<<3)
189186690Sobrien
190186690Sobrien    /* per-controller queues */
191186690Sobrien    struct bio_queue_head 	amr_bioq;		/* pending I/O with no commands */
192186690Sobrien    TAILQ_HEAD(,amr_command)	amr_ready;		/* commands ready to be submitted */
19368349Sobrien    struct amr_command		*amr_busycmd[AMR_MAXCMD];
194186690Sobrien    int				amr_busyslots;
195186690Sobrien    TAILQ_HEAD(,amr_command)	amr_completed;
196186690Sobrien    TAILQ_HEAD(,amr_command)	amr_freecmds;
197186690Sobrien    TAILQ_HEAD(,amr_command_cluster)	amr_cmd_clusters;
198186690Sobrien
199186690Sobrien    /* CAM attachments for passthrough */
200186690Sobrien    struct cam_sim		*amr_cam_sim[AMR_MAX_CHANNELS];
201186690Sobrien    TAILQ_HEAD(, ccb_hdr)	amr_cam_ccbq;
202186690Sobrien
203186690Sobrien    /* control device */
204186690Sobrien    dev_t			amr_dev_t;
205186690Sobrien
20668349Sobrien    /* controller type-specific support */
20768349Sobrien    int				amr_type;
208186690Sobrien#define AMR_TYPE_QUARTZ		(1<<0)
209186690Sobrien#define AMR_IS_QUARTZ(sc)	((sc)->amr_type & AMR_TYPE_QUARTZ)
210186690Sobrien#define AMR_TYPE_40LD		(1<<1)
211186690Sobrien#define AMR_IS_40LD(sc)		((sc)->amr_type & AMR_TYPE_40LD)
212186690Sobrien    int				(* amr_submit_command)(struct amr_softc *sc);
213186690Sobrien    int				(* amr_get_work)(struct amr_softc *sc, struct amr_mailbox *mbsave);
214186690Sobrien    int				(*amr_poll_command)(struct amr_command *ac);
215186690Sobrien    int 			support_ext_cdb;	/* greater than 10 byte cdb support */
216186690Sobrien
217186690Sobrien    /* misc glue */
218186690Sobrien    struct intr_config_hook	amr_ich;		/* wait-for-interrupts probe hook */
219186690Sobrien    struct callout_handle	amr_timeout;		/* periodic status check */
220186690Sobrien#if __FreeBSD_version >= 500005
221186690Sobrien    struct task			amr_task_complete;	/* deferred-completion task */
222186690Sobrien#endif
223186690Sobrien};
22468349Sobrien
22568349Sobrien/*
22668349Sobrien * Interface between bus connections and driver core.
227186690Sobrien */
228186690Sobrienextern int              amr_attach(struct amr_softc *sc);
229186690Sobrienextern void		amr_free(struct amr_softc *sc);
230186690Sobrienextern int		amr_flush(struct amr_softc *sc);
231186690Sobrienextern int		amr_done(struct amr_softc *sc);
232186690Sobrienextern void		amr_startio(struct amr_softc *sc);
233186690Sobrien
234186690Sobrien/*
235186690Sobrien * Command buffer allocation.
236186690Sobrien */
237186690Sobrienextern struct amr_command	*amr_alloccmd(struct amr_softc *sc);
238186690Sobrienextern void			amr_releasecmd(struct amr_command *ac);
239159764Sobrien
24068349Sobrien/*
24168349Sobrien * CAM interface
24268349Sobrien */
24368349Sobrienextern int		amr_cam_attach(struct amr_softc *sc);
24468349Sobrienextern void		amr_cam_detach(struct amr_softc *sc);
245186690Sobrienextern int		amr_cam_command(struct amr_softc *sc, struct amr_command **acp);
24668349Sobrien
24768349Sobrien/*
24868349Sobrien * MegaRAID logical disk driver
24968349Sobrien */
25068349Sobrienstruct amrd_softc
25168349Sobrien{
25268349Sobrien    device_t		amrd_dev;
25368349Sobrien    dev_t		amrd_dev_t;
25468349Sobrien    struct amr_softc	*amrd_controller;
25568349Sobrien    struct amr_logdrive	*amrd_drive;
25668349Sobrien    struct disk		amrd_disk;
25768349Sobrien    struct devstat	amrd_stats;
25868349Sobrien    int			amrd_unit;
259186690Sobrien};
260186690Sobrien
261186690Sobrien/*
262186690Sobrien * Interface between driver core and disk driver (should be using a bus?)
263186690Sobrien */
264186690Sobrienextern int	amr_submit_bio(struct amr_softc *sc, struct bio *bio);
265186690Sobrienextern void	amrd_intr(void *data);
266186690Sobrien
26768349Sobrien/********************************************************************************
26868349Sobrien * Enqueue/dequeue functions
26968349Sobrien */
27068349Sobrienstatic __inline void
27168349Sobrienamr_enqueue_bio(struct amr_softc *sc, struct bio *bio)
27268349Sobrien{
27368349Sobrien    int		s;
27468349Sobrien
275103373Sobrien    s = splbio();
276103373Sobrien    bioq_insert_tail(&sc->amr_bioq, bio);
277103373Sobrien    splx(s);
278103373Sobrien}
279103373Sobrien
280186690Sobrienstatic __inline struct bio *
281103373Sobrienamr_dequeue_bio(struct amr_softc *sc)
282103373Sobrien{
283103373Sobrien    struct bio	*bio;
284103373Sobrien    int		s;
285103373Sobrien
286159764Sobrien    s = splbio();
287169942Sobrien    if ((bio = bioq_first(&sc->amr_bioq)) != NULL)
288175296Sobrien	bioq_remove(&sc->amr_bioq, bio);
289159764Sobrien    splx(s);
290133359Sobrien    return(bio);
291186690Sobrien}
292169942Sobrien
29368349Sobrienstatic __inline void
29468349Sobrienamr_enqueue_ready(struct amr_command *ac)
29568349Sobrien{
296133359Sobrien    int		s;
297133359Sobrien
298133359Sobrien    s = splbio();
299169942Sobrien    TAILQ_INSERT_TAIL(&ac->ac_sc->amr_ready, ac, ac_link);
300169942Sobrien    splx(s);
30168349Sobrien}
302169942Sobrien
303169942Sobrienstatic __inline void
304169942Sobrienamr_requeue_ready(struct amr_command *ac)
305169942Sobrien{
306169942Sobrien    int		s;
307159764Sobrien
308133359Sobrien    s = splbio();
309133359Sobrien    TAILQ_INSERT_HEAD(&ac->ac_sc->amr_ready, ac, ac_link);
310133359Sobrien    splx(s);
311133359Sobrien}
312159764Sobrien
31368349Sobrienstatic __inline struct amr_command *
31468349Sobrienamr_dequeue_ready(struct amr_softc *sc)
31568349Sobrien{
31668349Sobrien    struct amr_command	*ac;
317169942Sobrien    int			s;
318133359Sobrien
319133359Sobrien    s = splbio();
320133359Sobrien    if ((ac = TAILQ_FIRST(&sc->amr_ready)) != NULL)
321159764Sobrien	TAILQ_REMOVE(&sc->amr_ready, ac, ac_link);
322133359Sobrien    splx(s);
323133359Sobrien    return(ac);
324133359Sobrien}
325169942Sobrien
326169942Sobrienstatic __inline void
327169942Sobrienamr_enqueue_completed(struct amr_command *ac)
328169942Sobrien{
329169942Sobrien    int		s;
330169942Sobrien
331169942Sobrien    s = splbio();
332169942Sobrien    TAILQ_INSERT_TAIL(&ac->ac_sc->amr_completed, ac, ac_link);
33368349Sobrien    splx(s);
334159764Sobrien}
33568349Sobrien
33668349Sobrienstatic __inline struct amr_command *
33768349Sobrienamr_dequeue_completed(struct amr_softc *sc)
33868349Sobrien{
33968349Sobrien    struct amr_command	*ac;
34068349Sobrien    int			s;
341169962Sobrien
342133359Sobrien    s = splbio();
343133359Sobrien    if ((ac = TAILQ_FIRST(&sc->amr_completed)) != NULL)
344133359Sobrien	TAILQ_REMOVE(&sc->amr_completed, ac, ac_link);
345139368Sobrien    splx(s);
346159764Sobrien    return(ac);
347133359Sobrien}
348133359Sobrien
349133359Sobrienstatic __inline void
350133359Sobrienamr_enqueue_free(struct amr_command *ac)
35168349Sobrien{
35268349Sobrien    int		s;
353133359Sobrien
35468349Sobrien    s = splbio();
355133359Sobrien    TAILQ_INSERT_TAIL(&ac->ac_sc->amr_freecmds, ac, ac_link);
356186690Sobrien    splx(s);
357133359Sobrien}
358133359Sobrien
35968349Sobrienstatic __inline struct amr_command *
360133359Sobrienamr_dequeue_free(struct amr_softc *sc)
361133359Sobrien{
362133359Sobrien    struct amr_command	*ac;
363133359Sobrien    int			s;
364133359Sobrien
365133359Sobrien    s = splbio();
366133359Sobrien    if ((ac = TAILQ_FIRST(&sc->amr_freecmds)) != NULL)
367186690Sobrien	TAILQ_REMOVE(&sc->amr_freecmds, ac, ac_link);
368186690Sobrien    splx(s);
369133359Sobrien    return(ac);
370133359Sobrien}
371133359Sobrien