amrvar.h revision 60938
114075Spsandoz/*-
214075Spsandoz * Copyright (c) 1999 Michael Smith
314075Spsandoz * All rights reserved.
414075Spsandoz *
514075Spsandoz * Redistribution and use in source and binary forms, with or without
614075Spsandoz * modification, are permitted provided that the following conditions
714075Spsandoz * are met:
814075Spsandoz * 1. Redistributions of source code must retain the above copyright
914075Spsandoz *    notice, this list of conditions and the following disclaimer.
1014075Spsandoz * 2. Redistributions in binary form must reproduce the above copyright
1114075Spsandoz *    notice, this list of conditions and the following disclaimer in the
1214075Spsandoz *    documentation and/or other materials provided with the distribution.
1314075Spsandoz *
1414075Spsandoz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1514075Spsandoz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1614075Spsandoz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1714075Spsandoz * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1814075Spsandoz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1914075Spsandoz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2014075Spsandoz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2114075Spsandoz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2214075Spsandoz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2314075Spsandoz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2414075Spsandoz * SUCH DAMAGE.
2514075Spsandoz *
2614296Spsandoz *      $FreeBSD: head/sys/dev/amr/amrvar.h 60938 2000-05-26 02:09:24Z jake $
2714075Spsandoz */
2814075Spsandoz
2914075Spsandoz/*
3014075Spsandoz * We could actually use all 17 segments, but using only 16 means that
3114075Spsandoz * each scatter/gather map is 128 bytes in size, and thus we don't have to worry about
3214075Spsandoz * maps crossing page boundaries.
3314075Spsandoz */
3414075Spsandoz#define AMR_NSEG	16
3514075Spsandoz
3614075Spsandoz#define AMR_CFG_BASE	0x10
3714075Spsandoz#define AMR_CFG_SIG	0xa0
3814075Spsandoz#define AMR_SIGNATURE	0x3344
3914075Spsandoz
4014075Spsandoz#define AMR_MAXCMD	255		/* ident = 0 not allowed */
4114075Spsandoz#define AMR_LIMITCMD	120		/* maximum count of outstanding commands */
4214075Spsandoz#define AMR_MAXLD      	40
4314075Spsandoz
4414075Spsandoz#define AMR_BLKSIZE	512
4514075Spsandoz
4614075Spsandozstruct amr_softc;
4714075Spsandoz
4814075Spsandoz/*
4914075Spsandoz * Per-logical-drive datastructure
5014075Spsandoz */
5114075Spsandozstruct amr_logdrive
5214075Spsandoz{
5314502Spsandoz    u_int32_t	al_size;
5414075Spsandoz    int		al_state;
5514075Spsandoz    int		al_properties;
5614075Spsandoz
5714075Spsandoz    /* synthetic geometry */
5814075Spsandoz    int		al_cylinders;
5914075Spsandoz    int		al_heads;
6014075Spsandoz    int		al_sectors;
6114296Spsandoz
6214296Spsandoz    /* driver */
6314296Spsandoz    device_t	al_disk;
6414075Spsandoz};
6514296Spsandoz
6614075Spsandoz
6714075Spsandoz/*
6814075Spsandoz * Per-command control structure.
6914075Spsandoz */
7014296Spsandozstruct amr_command
7114075Spsandoz{
7214075Spsandoz    TAILQ_ENTRY(amr_command)	ac_link;
7314075Spsandoz
7414075Spsandoz    struct amr_softc		*ac_sc;
7514075Spsandoz    u_int8_t			ac_slot;
7614075Spsandoz    int				ac_status;
7714075Spsandoz#define AMR_STATUS_BUSY		0xffff
7814075Spsandoz#define AMR_STATUS_WEDGED	0xdead
7914075Spsandoz#define AMR_STATUS_LATE		0xdeed
8014075Spsandoz    struct amr_mailbox		ac_mailbox;
8114156Spsandoz    u_int32_t			ac_sgphys;
8214156Spsandoz    int				ac_nsgent;
8314075Spsandoz    int				ac_flags;
8414156Spsandoz#define AMR_CMD_DATAIN		(1<<0)
8514156Spsandoz#define AMR_CMD_DATAOUT		(1<<1)
8614156Spsandoz#define AMR_CMD_PRIORITY	(1<<2)
8714156Spsandoz    time_t			ac_stamp;
8814156Spsandoz
8914156Spsandoz    void			*ac_data;
9014075Spsandoz    size_t			ac_length;
9114156Spsandoz    bus_dmamap_t		ac_dmamap;
9214958Spsandoz    u_int32_t			ac_dataphys;
9314156Spsandoz
9414156Spsandoz    void			(* ac_complete)(struct amr_command *ac);
9515541Spsandoz    void			*ac_private;
9614156Spsandoz};
9714156Spsandoz
9814156Spsandozstruct amr_softc
9914156Spsandoz{
10015539Spsandoz    /* bus attachments */
10115539Spsandoz    device_t			amr_dev;
10214075Spsandoz    struct resource		*amr_reg;		/* control registers */
10314156Spsandoz    bus_space_handle_t		amr_bhandle;
10415539Spsandoz    bus_space_tag_t		amr_btag;
10515539Spsandoz    bus_dma_tag_t		amr_parent_dmat;	/* parent DMA tag */
10615539Spsandoz    bus_dma_tag_t		amr_buffer_dmat;	/* data buffer DMA tag */
10715539Spsandoz    struct resource		*amr_irq;		/* interrupt */
10815539Spsandoz    void			*amr_intr;
10915539Spsandoz
11015539Spsandoz    /* mailbox */
11115539Spsandoz    volatile struct amr_mailbox		*amr_mailbox;
11215539Spsandoz    volatile struct amr_mailbox64	*amr_mailbox64;
11315539Spsandoz    u_int32_t			amr_mailboxphys;
11415539Spsandoz    bus_dma_tag_t		amr_mailbox_dmat;
11515539Spsandoz    bus_dmamap_t		amr_mailbox_dmamap;
11614075Spsandoz
11714075Spsandoz    /* scatter/gather lists and their controller-visible mappings */
11814075Spsandoz    struct amr_sgentry		*amr_sgtable;		/* s/g lists */
11914075Spsandoz    u_int32_t			amr_sgbusaddr;		/* s/g table base address in bus space */
12014075Spsandoz    bus_dma_tag_t		amr_sg_dmat;		/* s/g buffer DMA tag */
12114075Spsandoz    bus_dmamap_t		amr_sg_dmamap;		/* map for s/g buffers */
12214075Spsandoz
12314075Spsandoz    /* controller limits and features */
12414075Spsandoz    int				amr_maxio;		/* maximum number of I/O transactions */
12514075Spsandoz    int				amr_maxdrives;		/* max number of logical drives */
12614075Spsandoz
12714075Spsandoz    /* connected logical drives */
12814075Spsandoz    struct amr_logdrive		amr_drive[AMR_MAXLD];
12914075Spsandoz
13014075Spsandoz    /* controller status */
13114075Spsandoz    int				amr_state;
13214075Spsandoz#define AMR_STATE_OPEN		(1<<0)
13314075Spsandoz#define AMR_STATE_SUSPEND	(1<<1)
13414075Spsandoz#define AMR_STATE_INTEN		(1<<2)
13514075Spsandoz#define AMR_STATE_SHUTDOWN	(1<<3)
13614075Spsandoz    struct callout_handle	amr_timeout;		/* periodic status check */
13714075Spsandoz
13814075Spsandoz    /* per-controller queues */
13914075Spsandoz    struct bio_queue_head 	amr_bioq;		/* pending I/O */
14014075Spsandoz    int				amr_waitbufs;
14114075Spsandoz    struct amr_command		*amr_busycmd[AMR_MAXCMD];
14214075Spsandoz    int				amr_busycmdcount;
14314075Spsandoz    TAILQ_HEAD(,amr_command)	amr_work;
14414075Spsandoz    int				amr_workcount;
14514075Spsandoz    TAILQ_HEAD(,amr_command)	amr_freecmds;
14614075Spsandoz
14714075Spsandoz    int				amr_locks;		/* reentrancy avoidance */
14814075Spsandoz
14914075Spsandoz    /* controller type-specific support */
15014075Spsandoz    int				amr_type;
15114075Spsandoz#define AMR_TYPE_STD		0
15214075Spsandoz#define AMR_TYPE_QUARTZ		1
15314075Spsandoz    void			(* amr_submit_command)(struct amr_softc *sc);
15414075Spsandoz    int				(* amr_get_work)(struct amr_softc *sc, struct amr_mailbox *mbsave);
15514075Spsandoz    void			(* amr_attach_mailbox)(struct amr_softc *sc);
15614075Spsandoz};
15714075Spsandoz
15814075Spsandoz/*
15914075Spsandoz * Simple (stupid) locks.
16014075Spsandoz *
16114075Spsandoz * Note that these are designed to avoid reentrancy, not concurrency, and will
16214075Spsandoz * need to be replaced with something better.
16314075Spsandoz */
16414075Spsandoz#define AMR_LOCK_COMPLETING     (1<<0)
16514075Spsandoz#define AMR_LOCK_STARTING       (1<<1)
16614075Spsandoz
16714075Spsandozstatic __inline int
16814075Spsandozamr_lock_tas(struct amr_softc *sc, int lock)
16914075Spsandoz{
17014075Spsandoz    if ((sc)->amr_locks & (lock))
17114075Spsandoz        return(1);
17214075Spsandoz    atomic_set_int(&sc->amr_locks, lock);
17314075Spsandoz    return(0);
17414075Spsandoz}
17514075Spsandoz
17614075Spsandozstatic __inline void
17714075Spsandozamr_lock_clr(struct amr_softc *sc, int lock)
17814075Spsandoz{
17914075Spsandoz    atomic_clear_int(&sc->amr_locks, lock);
18014075Spsandoz}
18114075Spsandoz
18214075Spsandoz/*
18314075Spsandoz * I/O primitives
18414075Spsandoz */
18514075Spsandoz/* Quartz */
18614075Spsandoz#define AMR_QPUT_IDB(sc, val)	bus_space_write_4(sc->amr_btag, sc->amr_bhandle, AMR_QIDB, val)
18714075Spsandoz#define AMR_QGET_IDB(sc)	bus_space_read_4 (sc->amr_btag, sc->amr_bhandle, AMR_QIDB)
18814075Spsandoz#define AMR_QPUT_ODB(sc, val)	bus_space_write_4(sc->amr_btag, sc->amr_bhandle, AMR_QODB, val)
18914075Spsandoz#define AMR_QGET_ODB(sc)	bus_space_read_4 (sc->amr_btag, sc->amr_bhandle, AMR_QODB)
19014075Spsandoz
19114075Spsandoz/* Standard */
19214075Spsandoz#define AMR_SPUT_ISTAT(sc, val)	bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_SINTR, val)
19314075Spsandoz#define AMR_SGET_ISTAT(sc)	bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SINTR)
19414075Spsandoz#define AMR_SACK_INTERRUPT(sc)	bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_SCMD, AMR_SCMD_ACKINTR)
19514075Spsandoz#define AMR_SPOST_COMMAND(sc)	bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_SCMD, AMR_SCMD_POST)
19614075Spsandoz#define AMR_SGET_MBSTAT(sc)	bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SMBOX_BUSY)
19714075Spsandoz#define AMR_SENABLE_INTR(sc)											\
19814075Spsandoz	bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE, 						\
19914075Spsandoz			  bus_space_read_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE) | AMR_STOGL_IENABLE)
20014075Spsandoz#define AMR_SDISABLE_INTR(sc)											\
20114075Spsandoz	bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE, 						\
20214075Spsandoz			  bus_space_read_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE) & ~AMR_STOGL_IENABLE)
20314075Spsandoz#define AMR_SBYTE_SET(sc, reg, val)	bus_space_write_1(sc->amr_btag, sc->amr_bhandle, reg, val)
20414075Spsandoz
20514075Spsandoz/*
20615539Spsandoz * Interface between bus connections and driver core.
20715539Spsandoz */
20815539Spsandozextern void             amr_free(struct amr_softc *sc);
20915539Spsandozextern int              amr_attach(struct amr_softc *sc);
21015539Spsandozextern void             amr_startup(struct amr_softc *sc);
21115539Spsandozextern void             amr_intr(void *data);
21215539Spsandozextern int              amr_detach(device_t dev);
21315539Spsandozextern int              amr_shutdown(device_t dev);
21415539Spsandozextern int              amr_suspend(device_t dev);
21515539Spsandozextern int              amr_resume(device_t dev);
21615539Spsandozextern d_open_t         amr_open;
21715539Spsandozextern d_close_t        amr_close;
21815539Spsandozextern d_ioctl_t        amr_ioctl;
21915539Spsandoz
22015539Spsandozextern devclass_t       amr_devclass;
22115539Spsandoz
22215539Spsandoz/*
22315539Spsandoz * MegaRAID logical disk driver
22415539Spsandoz */
22515539Spsandozstruct amrd_softc
22615539Spsandoz{
22715539Spsandoz    device_t		amrd_dev;
22815539Spsandoz    dev_t		amrd_dev_t;
22915539Spsandoz    struct amr_softc	*amrd_controller;
23015539Spsandoz    struct amr_logdrive	*amrd_drive;
23115539Spsandoz    struct disk		amrd_disk;
23215539Spsandoz    struct devstat	amrd_stats;
23315539Spsandoz    struct disklabel	amrd_label;
23415539Spsandoz    int			amrd_unit;
23515539Spsandoz    int			amrd_flags;
23615539Spsandoz#define AMRD_OPEN	(1<<0)		/* drive is open (can't shut down) */
23715539Spsandoz};
23815539Spsandoz
23915539Spsandoz/*
24015539Spsandoz * Interface between driver core and disk driver (should be using a bus?)
24115539Spsandoz */
24215539Spsandozextern int	amr_submit_buf(struct amr_softc *sc, struct bio *bp);
24315539Spsandozextern int	amr_submit_ioctl(struct amr_softc *sc, struct amr_logdrive *drive, u_long cmd,
24415539Spsandoz				 caddr_t addr, int32_t flag, struct proc *p);
24515539Spsandozextern void	amrd_intr(void *data);
24615539Spsandoz
24715539Spsandozextern void	amr_report(void);
24814075Spsandoz