amrvar.h revision 158267
1166124Srafan/*-
250276Speter * Copyright (c) 1999,2000 Michael Smith
3166124Srafan * Copyright (c) 2000 BSDi
450276Speter * All rights reserved.
550276Speter *
650276Speter * Redistribution and use in source and binary forms, with or without
750276Speter * modification, are permitted provided that the following conditions
850276Speter * are met:
950276Speter * 1. Redistributions of source code must retain the above copyright
1050276Speter *    notice, this list of conditions and the following disclaimer.
1150276Speter * 2. Redistributions in binary form must reproduce the above copyright
1250276Speter *    notice, this list of conditions and the following disclaimer in the
1350276Speter *    documentation and/or other materials provided with the distribution.
1450276Speter *
1550276Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1650276Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1750276Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1850276Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1950276Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2050276Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2150276Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2250276Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2350276Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2450276Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2550276Speter * SUCH DAMAGE.
2650276Speter *
2750276Speter * Copyright (c) 2002 Eric Moore
2850276Speter * Copyright (c) 2002 LSI Logic Corporation
2950276Speter * All rights reserved.
3050276Speter *
3150276Speter * Redistribution and use in source and binary forms, with or without
3250276Speter * modification, are permitted provided that the following conditions
3350276Speter * are met:
3450276Speter * 1. Redistributions of source code must retain the above copyright
3550276Speter *    notice, this list of conditions and the following disclaimer.
3650276Speter * 2. Redistributions in binary form must reproduce the above copyright
3750276Speter *    notice, this list of conditions and the following disclaimer in the
3850276Speter *    documentation and/or other materials provided with the distribution.
3950276Speter * 3. The party using or redistributing the source code and binary forms
4050276Speter *    agrees to the disclaimer below and the terms and conditions set forth
4150276Speter *    herein.
4250276Speter *
4350276Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
4450276Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4550276Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4650276Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4750276Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48166124Srafan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49166124Srafan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50166124Srafan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5150276Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5266963Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5350276Speter * SUCH DAMAGE.
5450276Speter *
5550276Speter *
5697049Speter *      $FreeBSD: head/sys/dev/amr/amrvar.h 158267 2006-05-03 16:45:15Z ambrisko $
5750276Speter */
5850276Speter
5950276Speter#include <geom/geom_disk.h>
6076726Speter#include <sys/lock.h>
61166124Srafan#include <sys/mutex.h>
62166124Srafan
63166124Srafan#define LSI_DESC_PCI "LSILogic MegaRAID 1.53"
64166124Srafan
65166124Srafan#ifdef AMR_DEBUG
6676726Speter# define debug(level, fmt, args...)	do {if (level <= AMR_DEBUG) printf("%s: " fmt "\n", __func__ , ##args);} while(0)
6750276Speter# define debug_called(level)		do {if (level <= AMR_DEBUG) printf("%s: called\n", __func__);} while(0)
6850276Speter#else
69166124Srafan# define debug(level, fmt, args...)
7050276Speter# define debug_called(level)
7150276Speter#endif
7250276Speter#define xdebug(fmt, args...)	printf("%s: " fmt "\n", __func__ , ##args)
7350276Speter
7450276Speter/*
7550276Speter * Per-logical-drive datastructure
7650276Speter */
7750276Speterstruct amr_logdrive
7850276Speter{
7962449Speter    u_int32_t	al_size;
8050276Speter    int		al_state;
8150276Speter    int		al_properties;
82166124Srafan
8350276Speter    /* synthetic geometry */
8450276Speter    int		al_cylinders;
8550276Speter    int		al_heads;
8676726Speter    int		al_sectors;
8750276Speter
8850276Speter    /* driver */
8950276Speter    device_t	al_disk;
9050276Speter};
9150276Speter
9250276Speter/*
9350276Speter * Due to the difficulty of using the zone allocator to create a new
94166124Srafan * zone from within a module, we use our own clustering to reduce
9550276Speter * memory wastage due to allocating lots of these small structures.
9650276Speter *
9797049Speter * 16k gives us a little under 200 command structures, which should
9862449Speter * normally be plenty.  We will grab more if we need them.
9950276Speter */
10050276Speter
10150276Speter#define AMR_CMD_CLUSTERSIZE	(16 * 1024)
10276726Speter
10376726Speter/*
10450276Speter * Per-command control structure.
10550276Speter */
10650276Speterstruct amr_command
107166124Srafan{
10850276Speter    TAILQ_ENTRY(amr_command)	ac_link;
10997049Speter
11097049Speter    struct amr_softc		*ac_sc;
11150276Speter    u_int8_t			ac_slot;
11250276Speter    int				ac_status;	/* command completion status */
11350276Speter    union {
11450276Speter	struct amr_sgentry	*sg32;
11550276Speter	struct amr_sg64entry	*sg64;
11650276Speter    } ac_sg;
11750276Speter    u_int32_t			ac_sgbusaddr;
11850276Speter    u_int32_t			ac_sg64_lo;
11950276Speter    u_int32_t			ac_sg64_hi;
12050276Speter    struct amr_mailbox		ac_mailbox;
12150276Speter    int				ac_flags;
12250276Speter#define AMR_CMD_DATAIN		(1<<0)
12350276Speter#define AMR_CMD_DATAOUT		(1<<1)
12462449Speter#define AMR_CMD_CCB_DATAIN	(1<<2)
12550276Speter#define AMR_CMD_CCB_DATAOUT	(1<<3)
12650276Speter#define AMR_CMD_PRIORITY	(1<<4)
12750276Speter#define AMR_CMD_MAPPED		(1<<5)
12850276Speter#define AMR_CMD_SLEEP		(1<<6)
12997049Speter#define AMR_CMD_BUSY		(1<<7)
13066963Speter#define AMR_CMD_SG64		(1<<8)
13197049Speter#define AC_IS_SG64(ac)		((ac)->ac_flags & AMR_CMD_SG64)
13250276Speter
13350276Speter    struct bio			*ac_bio;
13450276Speter    void			(* ac_complete)(struct amr_command *ac);
13550276Speter    void			*ac_private;
13650276Speter
13750276Speter    void			*ac_data;
13850276Speter    size_t			ac_length;
13950276Speter    bus_dmamap_t		ac_dmamap;
14050276Speter    bus_dmamap_t		ac_dma64map;
14150276Speter
14250276Speter    void			*ac_ccb_data;
14350276Speter    size_t			ac_ccb_length;
14450276Speter    bus_dmamap_t		ac_ccb_dmamap;
14550276Speter    bus_dmamap_t		ac_ccb_dma64map;
14650276Speter
14750276Speter};
14850276Speter
14950276Speterstruct amr_command_cluster
15050276Speter{
15150276Speter    TAILQ_ENTRY(amr_command_cluster)	acc_link;
15250276Speter    struct amr_command		acc_command[0];
15366963Speter};
15466963Speter
15550276Speter#define AMR_CMD_CLUSTERCOUNT	((AMR_CMD_CLUSTERSIZE - sizeof(struct amr_command_cluster)) /	\
15650276Speter				 sizeof(struct amr_command))
15797049Speter
15850276Speter/*
15950276Speter * Per-controller-instance data
16050276Speter */
16150276Speterstruct amr_softc
16250276Speter{
16350276Speter    /* bus attachments */
16450276Speter    device_t			amr_dev;
16550276Speter    struct resource		*amr_reg;		/* control registers */
16650276Speter    bus_space_handle_t		amr_bhandle;
16750276Speter    bus_space_tag_t		amr_btag;
16850276Speter    bus_dma_tag_t		amr_parent_dmat;	/* parent DMA tag */
16950276Speter    bus_dma_tag_t		amr_buffer_dmat;	/* data buffer DMA tag */
170    bus_dma_tag_t		amr_buffer64_dmat;
171    struct resource		*amr_irq;		/* interrupt */
172    void			*amr_intr;
173
174    /* mailbox */
175    volatile struct amr_mailbox		*amr_mailbox;
176    volatile struct amr_mailbox64	*amr_mailbox64;
177    u_int32_t			amr_mailboxphys;
178    bus_dma_tag_t		amr_mailbox_dmat;
179    bus_dmamap_t		amr_mailbox_dmamap;
180
181    /* scatter/gather lists and their controller-visible mappings */
182    struct amr_sgentry		*amr_sgtable;		/* s/g lists */
183    struct amr_sg64entry	*amr_sg64table;		/* 64bit s/g lists */
184    u_int32_t			amr_sgbusaddr;		/* s/g table base address in bus space */
185    bus_dma_tag_t		amr_sg_dmat;		/* s/g buffer DMA tag */
186    bus_dmamap_t		amr_sg_dmamap;		/* map for s/g buffers */
187
188    /* controller limits and features */
189    int				amr_nextslot;		/* Next slot to use for newly allocated commands */
190    int				amr_maxio;		/* maximum number of I/O transactions */
191    int				amr_maxdrives;		/* max number of logical drives */
192    int				amr_maxchan;		/* count of SCSI channels */
193
194    /* connected logical drives */
195    struct amr_logdrive		amr_drive[AMR_MAXLD];
196
197    /* controller state */
198    int				amr_state;
199#define AMR_STATE_OPEN		(1<<0)
200#define AMR_STATE_SUSPEND	(1<<1)
201#define AMR_STATE_INTEN		(1<<2)
202#define AMR_STATE_SHUTDOWN	(1<<3)
203#define AMR_STATE_CRASHDUMP	(1<<4)
204#define AMR_STATE_QUEUE_FRZN	(1<<5)
205#define AMR_STATE_LD_DELETE	(1<<6)
206#define AMR_STATE_REMAP_LD	(1<<7)
207
208    /* per-controller queues */
209    struct bio_queue_head 	amr_bioq;		/* pending I/O with no commands */
210    TAILQ_HEAD(,amr_command)	amr_ready;		/* commands ready to be submitted */
211    struct amr_command		*amr_busycmd[AMR_MAXCMD];
212    int				amr_busyslots;
213    TAILQ_HEAD(,amr_command)	amr_completed;
214    TAILQ_HEAD(,amr_command)	amr_freecmds;
215    TAILQ_HEAD(,amr_command_cluster)	amr_cmd_clusters;
216
217    /* CAM attachments for passthrough */
218    struct cam_sim		*amr_cam_sim[AMR_MAX_CHANNELS];
219    TAILQ_HEAD(, ccb_hdr)	amr_cam_ccbq;
220    struct cam_devq		*amr_cam_devq;
221
222    /* control device */
223    struct cdev			*amr_dev_t;
224    struct mtx			amr_list_lock;
225
226    /* controller type-specific support */
227    int				amr_type;
228#define AMR_TYPE_QUARTZ		(1<<0)
229#define AMR_IS_QUARTZ(sc)	((sc)->amr_type & AMR_TYPE_QUARTZ)
230#define AMR_TYPE_40LD		(1<<1)
231#define AMR_IS_40LD(sc)		((sc)->amr_type & AMR_TYPE_40LD)
232#define AMR_TYPE_SG64		(1<<2)
233#define AMR_IS_SG64(sc)		((sc)->amr_type & AMR_TYPE_SG64)
234    int				(* amr_submit_command)(struct amr_command *ac);
235    int				(* amr_get_work)(struct amr_softc *sc, struct amr_mailbox *mbsave);
236    int				(*amr_poll_command)(struct amr_command *ac);
237    int				(*amr_poll_command1)(struct amr_softc *sc, struct amr_command *ac);
238    int 			support_ext_cdb;	/* greater than 10 byte cdb support */
239
240    /* misc glue */
241    struct intr_config_hook	amr_ich;		/* wait-for-interrupts probe hook */
242    struct callout_handle	amr_timeout;		/* periodic status check */
243    int				amr_allow_vol_config;
244    int				amr_linux_no_adapters;
245    int				amr_ld_del_supported;
246    struct mtx			amr_hw_lock;
247};
248
249/*
250 * Interface between bus connections and driver core.
251 */
252extern int              amr_attach(struct amr_softc *sc);
253extern void		amr_free(struct amr_softc *sc);
254extern int		amr_flush(struct amr_softc *sc);
255extern int		amr_done(struct amr_softc *sc);
256extern void		amr_startio(struct amr_softc *sc);
257
258/*
259 * Command buffer allocation.
260 */
261extern struct amr_command	*amr_alloccmd(struct amr_softc *sc);
262extern void			amr_releasecmd(struct amr_command *ac);
263
264/*
265 * CAM interface
266 */
267extern int		amr_cam_attach(struct amr_softc *sc);
268extern void		amr_cam_detach(struct amr_softc *sc);
269extern int		amr_cam_command(struct amr_softc *sc, struct amr_command **acp);
270
271/*
272 * MegaRAID logical disk driver
273 */
274struct amrd_softc
275{
276    device_t		amrd_dev;
277    struct amr_softc	*amrd_controller;
278    struct amr_logdrive	*amrd_drive;
279    struct disk		*amrd_disk;
280    int			amrd_unit;
281};
282
283/*
284 * Interface between driver core and disk driver (should be using a bus?)
285 */
286extern int	amr_submit_bio(struct amr_softc *sc, struct bio *bio);
287extern int 	amr_dump_blocks(struct amr_softc *sc, int unit, u_int32_t lba, void *data, int blks);
288extern void	amrd_intr(void *data);
289
290/********************************************************************************
291 * Enqueue/dequeue functions
292 */
293static __inline void
294amr_enqueue_bio(struct amr_softc *sc, struct bio *bio)
295{
296
297    bioq_insert_tail(&sc->amr_bioq, bio);
298}
299
300static __inline struct bio *
301amr_dequeue_bio(struct amr_softc *sc)
302{
303    struct bio	*bio;
304
305    if ((bio = bioq_first(&sc->amr_bioq)) != NULL)
306	bioq_remove(&sc->amr_bioq, bio);
307    return(bio);
308}
309
310static __inline void
311amr_enqueue_ready(struct amr_command *ac)
312{
313
314    TAILQ_INSERT_TAIL(&ac->ac_sc->amr_ready, ac, ac_link);
315}
316
317static __inline void
318amr_requeue_ready(struct amr_command *ac)
319{
320
321    TAILQ_INSERT_HEAD(&ac->ac_sc->amr_ready, ac, ac_link);
322}
323
324static __inline struct amr_command *
325amr_dequeue_ready(struct amr_softc *sc)
326{
327    struct amr_command	*ac;
328
329    if ((ac = TAILQ_FIRST(&sc->amr_ready)) != NULL)
330	TAILQ_REMOVE(&sc->amr_ready, ac, ac_link);
331    return(ac);
332}
333
334static __inline void
335amr_enqueue_completed(struct amr_command *ac)
336{
337
338    TAILQ_INSERT_TAIL(&ac->ac_sc->amr_completed, ac, ac_link);
339}
340
341static __inline struct amr_command *
342amr_dequeue_completed(struct amr_softc *sc)
343{
344    struct amr_command	*ac;
345
346    if ((ac = TAILQ_FIRST(&sc->amr_completed)) != NULL)
347	TAILQ_REMOVE(&sc->amr_completed, ac, ac_link);
348    return(ac);
349}
350
351static __inline void
352amr_enqueue_free(struct amr_command *ac)
353{
354
355    TAILQ_INSERT_TAIL(&ac->ac_sc->amr_freecmds, ac, ac_link);
356}
357
358static __inline struct amr_command *
359amr_dequeue_free(struct amr_softc *sc)
360{
361    struct amr_command	*ac;
362
363    if ((ac = TAILQ_FIRST(&sc->amr_freecmds)) != NULL)
364	TAILQ_REMOVE(&sc->amr_freecmds, ac, ac_link);
365    return(ac);
366}
367