amrvar.h revision 60833
1214571Sdim/*-
2214571Sdim * Copyright (c) 1999 Michael Smith
3214571Sdim * All rights reserved.
4214571Sdim *
5214571Sdim * Redistribution and use in source and binary forms, with or without
6214571Sdim * modification, are permitted provided that the following conditions
7214571Sdim * are met:
8214571Sdim * 1. Redistributions of source code must retain the above copyright
9214571Sdim *    notice, this list of conditions and the following disclaimer.
10214571Sdim * 2. Redistributions in binary form must reproduce the above copyright
11214571Sdim *    notice, this list of conditions and the following disclaimer in the
12214571Sdim *    documentation and/or other materials provided with the distribution.
13214571Sdim *
14214571Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15214571Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16214571Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17214571Sdim * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18214571Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19214571Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20214571Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21214571Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22214571Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23214571Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24214571Sdim * SUCH DAMAGE.
25214571Sdim *
26214571Sdim *      $FreeBSD: head/sys/dev/amr/amrvar.h 60833 2000-05-23 20:41:01Z jake $
27214571Sdim */
28214571Sdim
29214571Sdim/*
30214571Sdim * We could actually use all 17 segments, but using only 16 means that
31214571Sdim * each scatter/gather map is 128 bytes in size, and thus we don't have to worry about
32214571Sdim * maps crossing page boundaries.
33214571Sdim */
34214571Sdim#define AMR_NSEG	16
35214571Sdim
36214571Sdim#define AMR_CFG_BASE	0x10
37214571Sdim#define AMR_CFG_SIG	0xa0
38214571Sdim#define AMR_SIGNATURE	0x3344
39214571Sdim
40214571Sdim#define AMR_MAXCMD	255		/* ident = 0 not allowed */
41214571Sdim#define AMR_LIMITCMD	120		/* maximum count of outstanding commands */
42214571Sdim#define AMR_MAXLD      	40
43214571Sdim
44214571Sdim#define AMR_BLKSIZE	512
45214571Sdim
46214571Sdimstruct amr_softc;
47214571Sdim
48214571Sdim/*
49214571Sdim * Per-logical-drive datastructure
50214571Sdim */
51214571Sdimstruct amr_logdrive
52214571Sdim{
53214571Sdim    u_int32_t	al_size;
54214571Sdim    int		al_state;
55214571Sdim    int		al_properties;
56214571Sdim
57214571Sdim    /* synthetic geometry */
58214571Sdim    int		al_cylinders;
59214571Sdim    int		al_heads;
60214571Sdim    int		al_sectors;
61214571Sdim
62214571Sdim    /* driver */
63214571Sdim    device_t	al_disk;
64214571Sdim};
65214571Sdim
66214571Sdim
67214571Sdim/*
68214571Sdim * Per-command control structure.
69214571Sdim */
70214571Sdimstruct amr_command
71214571Sdim{
72214571Sdim    TAILQ_ENTRY(struct amr_command)	ac_link;
73214571Sdim
74214571Sdim    struct amr_softc		*ac_sc;
75214571Sdim    u_int8_t			ac_slot;
76214571Sdim    int				ac_status;
77214571Sdim#define AMR_STATUS_BUSY		0xffff
78214571Sdim#define AMR_STATUS_WEDGED	0xdead
79214571Sdim#define AMR_STATUS_LATE		0xdeed
80214571Sdim    struct amr_mailbox		ac_mailbox;
81214571Sdim    u_int32_t			ac_sgphys;
82214571Sdim    int				ac_nsgent;
83214571Sdim    int				ac_flags;
84214571Sdim#define AMR_CMD_DATAIN		(1<<0)
85214571Sdim#define AMR_CMD_DATAOUT		(1<<1)
86214571Sdim#define AMR_CMD_PRIORITY	(1<<2)
87214571Sdim    time_t			ac_stamp;
88214571Sdim
89214571Sdim    void			*ac_data;
90214571Sdim    size_t			ac_length;
91214571Sdim    bus_dmamap_t		ac_dmamap;
92214571Sdim    u_int32_t			ac_dataphys;
93214571Sdim
94214571Sdim    void			(* ac_complete)(struct amr_command *ac);
95214571Sdim    void			*ac_private;
96214571Sdim};
97214571Sdim
98214571Sdimstruct amr_softc
99214571Sdim{
100214571Sdim    /* bus attachments */
101214571Sdim    device_t			amr_dev;
102214571Sdim    struct resource		*amr_reg;		/* control registers */
103214571Sdim    bus_space_handle_t		amr_bhandle;
104214571Sdim    bus_space_tag_t		amr_btag;
105214571Sdim    bus_dma_tag_t		amr_parent_dmat;	/* parent DMA tag */
106214571Sdim    bus_dma_tag_t		amr_buffer_dmat;	/* data buffer DMA tag */
107214571Sdim    struct resource		*amr_irq;		/* interrupt */
108214571Sdim    void			*amr_intr;
109214571Sdim
110214571Sdim    /* mailbox */
111214571Sdim    volatile struct amr_mailbox		*amr_mailbox;
112214571Sdim    volatile struct amr_mailbox64	*amr_mailbox64;
113214571Sdim    u_int32_t			amr_mailboxphys;
114214571Sdim    bus_dma_tag_t		amr_mailbox_dmat;
115214571Sdim    bus_dmamap_t		amr_mailbox_dmamap;
116214571Sdim
117214571Sdim    /* scatter/gather lists and their controller-visible mappings */
118214571Sdim    struct amr_sgentry		*amr_sgtable;		/* s/g lists */
119214571Sdim    u_int32_t			amr_sgbusaddr;		/* s/g table base address in bus space */
120214571Sdim    bus_dma_tag_t		amr_sg_dmat;		/* s/g buffer DMA tag */
121214571Sdim    bus_dmamap_t		amr_sg_dmamap;		/* map for s/g buffers */
122214571Sdim
123214571Sdim    /* controller limits and features */
124214571Sdim    int				amr_maxio;		/* maximum number of I/O transactions */
125214571Sdim    int				amr_maxdrives;		/* max number of logical drives */
126214571Sdim
127214571Sdim    /* connected logical drives */
128214571Sdim    struct amr_logdrive		amr_drive[AMR_MAXLD];
129214571Sdim
130214571Sdim    /* controller status */
131214571Sdim    int				amr_state;
132214571Sdim#define AMR_STATE_OPEN		(1<<0)
133214571Sdim#define AMR_STATE_SUSPEND	(1<<1)
134214571Sdim#define AMR_STATE_INTEN		(1<<2)
135214571Sdim#define AMR_STATE_SHUTDOWN	(1<<3)
136214571Sdim    struct callout_handle	amr_timeout;		/* periodic status check */
137214571Sdim
138214571Sdim    /* per-controller queues */
139214571Sdim    struct bio_queue_head 	amr_bioq;		/* pending I/O */
140214571Sdim    int				amr_waitbufs;
141214571Sdim    struct amr_command		*amr_busycmd[AMR_MAXCMD];
142214571Sdim    int				amr_busycmdcount;
143214571Sdim    TAILQ_HEAD(, struct amr_command)	amr_work;
144214571Sdim    int				amr_workcount;
145214571Sdim    TAILQ_HEAD(, struct amr_command)	amr_freecmds;
146214571Sdim
147214571Sdim    int				amr_locks;		/* reentrancy avoidance */
148214571Sdim
149214571Sdim    /* controller type-specific support */
150214571Sdim    int				amr_type;
151214571Sdim#define AMR_TYPE_STD		0
152214571Sdim#define AMR_TYPE_QUARTZ		1
153214571Sdim    void			(* amr_submit_command)(struct amr_softc *sc);
154214571Sdim    int				(* amr_get_work)(struct amr_softc *sc, struct amr_mailbox *mbsave);
155214571Sdim    void			(* amr_attach_mailbox)(struct amr_softc *sc);
156214571Sdim};
157214571Sdim
158214571Sdim/*
159214571Sdim * Simple (stupid) locks.
160214571Sdim *
161214571Sdim * Note that these are designed to avoid reentrancy, not concurrency, and will
162214571Sdim * need to be replaced with something better.
163214571Sdim */
164214571Sdim#define AMR_LOCK_COMPLETING     (1<<0)
165214571Sdim#define AMR_LOCK_STARTING       (1<<1)
166214571Sdim
167214571Sdimstatic __inline int
168214571Sdimamr_lock_tas(struct amr_softc *sc, int lock)
169214571Sdim{
170214571Sdim    if ((sc)->amr_locks & (lock))
171214571Sdim        return(1);
172214571Sdim    atomic_set_int(&sc->amr_locks, lock);
173214571Sdim    return(0);
174214571Sdim}
175
176static __inline void
177amr_lock_clr(struct amr_softc *sc, int lock)
178{
179    atomic_clear_int(&sc->amr_locks, lock);
180}
181
182/*
183 * I/O primitives
184 */
185/* Quartz */
186#define AMR_QPUT_IDB(sc, val)	bus_space_write_4(sc->amr_btag, sc->amr_bhandle, AMR_QIDB, val)
187#define AMR_QGET_IDB(sc)	bus_space_read_4 (sc->amr_btag, sc->amr_bhandle, AMR_QIDB)
188#define AMR_QPUT_ODB(sc, val)	bus_space_write_4(sc->amr_btag, sc->amr_bhandle, AMR_QODB, val)
189#define AMR_QGET_ODB(sc)	bus_space_read_4 (sc->amr_btag, sc->amr_bhandle, AMR_QODB)
190
191/* Standard */
192#define AMR_SPUT_ISTAT(sc, val)	bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_SINTR, val)
193#define AMR_SGET_ISTAT(sc)	bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SINTR)
194#define AMR_SACK_INTERRUPT(sc)	bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_SCMD, AMR_SCMD_ACKINTR)
195#define AMR_SPOST_COMMAND(sc)	bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_SCMD, AMR_SCMD_POST)
196#define AMR_SGET_MBSTAT(sc)	bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SMBOX_BUSY)
197#define AMR_SENABLE_INTR(sc)											\
198	bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE, 						\
199			  bus_space_read_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE) | AMR_STOGL_IENABLE)
200#define AMR_SDISABLE_INTR(sc)											\
201	bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE, 						\
202			  bus_space_read_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE) & ~AMR_STOGL_IENABLE)
203#define AMR_SBYTE_SET(sc, reg, val)	bus_space_write_1(sc->amr_btag, sc->amr_bhandle, reg, val)
204
205/*
206 * Interface between bus connections and driver core.
207 */
208extern void             amr_free(struct amr_softc *sc);
209extern int              amr_attach(struct amr_softc *sc);
210extern void             amr_startup(struct amr_softc *sc);
211extern void             amr_intr(void *data);
212extern int              amr_detach(device_t dev);
213extern int              amr_shutdown(device_t dev);
214extern int              amr_suspend(device_t dev);
215extern int              amr_resume(device_t dev);
216extern d_open_t         amr_open;
217extern d_close_t        amr_close;
218extern d_ioctl_t        amr_ioctl;
219
220extern devclass_t       amr_devclass;
221
222/*
223 * MegaRAID logical disk driver
224 */
225struct amrd_softc
226{
227    device_t		amrd_dev;
228    dev_t		amrd_dev_t;
229    struct amr_softc	*amrd_controller;
230    struct amr_logdrive	*amrd_drive;
231    struct disk		amrd_disk;
232    struct devstat	amrd_stats;
233    struct disklabel	amrd_label;
234    int			amrd_unit;
235    int			amrd_flags;
236#define AMRD_OPEN	(1<<0)		/* drive is open (can't shut down) */
237};
238
239/*
240 * Interface between driver core and disk driver (should be using a bus?)
241 */
242extern int	amr_submit_buf(struct amr_softc *sc, struct bio *bp);
243extern int	amr_submit_ioctl(struct amr_softc *sc, struct amr_logdrive *drive, u_long cmd,
244				 caddr_t addr, int32_t flag, struct proc *p);
245extern void	amrd_intr(void *data);
246
247extern void	amr_report(void);
248