1/*-
2 * Copyright (c) 1999,2000 Jonathan Lemon
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29/*
30 * software structures for the Compaq RAID controller
31 */
32
33#ifndef _IDAVAR_H
34#define	_IDAVAR_H
35
36#define	ida_inb(ida, port) \
37	bus_read_1((ida)->regs, port)
38#define	ida_inw(ida, port) \
39	bus_read_2((ida)->regs, port)
40#define	ida_inl(ida, port) \
41	bus_read_4((ida)->regs, port)
42
43#define	ida_outb(ida, port, val) \
44	bus_write_1((ida)->regs, port, val)
45#define	ida_outw(ida, port, val) \
46	bus_write_2((ida)->regs, port, val)
47#define	ida_outl(ida, port, val) \
48	bus_write_4((ida)->regs, port, val)
49
50struct ida_hdr {
51	u_int8_t	drive;		/* logical drive */
52	u_int8_t	priority;	/* block priority */
53	u_int16_t	size;		/* size of request, in words */
54};
55
56struct ida_req {
57	u_int16_t	next;		/* offset of next request */
58	u_int8_t	command;	/* command */
59	u_int8_t	error;		/* return error code */
60	u_int32_t	blkno;		/* block number */
61	u_int16_t	bcount;		/* block count */
62	u_int8_t	sgcount;	/* number of scatter/gather entries */
63	u_int8_t	spare;		/* reserved */
64};
65
66struct ida_sgb {
67	u_int32_t	length;		/* length of S/G segment */
68	u_int32_t	addr;		/* physical address of block */
69};
70
71#define	IDA_NSEG	32		/* maximum number of segments */
72
73/*
74 * right now, this structure totals 276 bytes.
75 */
76struct ida_hardware_qcb {
77	struct 	ida_hdr hdr;			/*   4 */
78	struct 	ida_req req;			/*  12 */
79	struct 	ida_sgb seg[IDA_NSEG];		/* 256 */
80	struct	ida_qcb *qcb;			/*   4 - qcb backpointer */
81};
82
83typedef enum {
84	QCB_FREE		= 0x0000,
85	QCB_ACTIVE		= 0x0001,	/* waiting for completion */
86	QCB_TIMEDOUT		= 0x0002,
87} qcb_state;
88
89#define	DMA_DATA_IN	0x0001
90#define	DMA_DATA_OUT	0x0002
91#define	IDA_COMMAND	0x0004
92#define	DMA_DATA_TRANSFER	(DMA_DATA_IN | DMA_DATA_OUT)
93
94#define	IDA_QCB_MAX	256
95#define	IDA_CONTROLLER	0		/* drive "number" for controller */
96
97struct ida_softc;
98
99struct ida_qcb {
100	struct		ida_hardware_qcb *hwqcb;
101	struct		ida_softc *ida;
102	qcb_state	state;
103	short		flags;
104	union {
105		STAILQ_ENTRY(ida_qcb) stqe;
106		SLIST_ENTRY(ida_qcb) sle;
107	} link;
108	bus_dmamap_t	dmamap;
109	bus_addr_t	hwqcb_busaddr;
110	struct		bio *buf;		/* bio associated with qcb */
111	int		error;
112};
113
114struct ida_access {
115	int		(*fifo_full)(struct ida_softc *);
116	void		(*submit)(struct ida_softc *, struct ida_qcb *);
117	bus_addr_t	(*done)(struct ida_softc *);
118	int		(*int_pending)(struct ida_softc *);
119	void		(*int_enable)(struct ida_softc *, int);
120};
121
122/*
123 * flags for the controller
124 */
125#define	IDA_ATTACHED	0x01		/* attached */
126#define	IDA_FIRMWARE	0x02		/* firmware must be started */
127#define	IDA_INTERRUPTS	0x04		/* interrupts enabled */
128#define	IDA_QFROZEN	0x08		/* request queue frozen */
129
130struct ida_softc {
131	device_t	dev;
132
133	struct callout	ch;
134	struct cdev *ida_dev_t;
135
136	int		regs_res_type;
137	int		regs_res_id;
138	struct 		resource *regs;
139
140	int		irq_res_type;
141	struct		resource *irq;
142	void		*ih;
143
144	struct mtx	lock;
145	struct intr_config_hook ich;
146
147	/* various DMA tags */
148	bus_dma_tag_t	parent_dmat;
149	bus_dma_tag_t	buffer_dmat;
150
151	bus_dma_tag_t	hwqcb_dmat;
152	bus_dmamap_t	hwqcb_dmamap;
153	bus_addr_t	hwqcb_busaddr;
154
155	bus_dma_tag_t	sg_dmat;
156
157	int		flags;
158
159	int		qactive;
160
161	struct		ida_hardware_qcb *hwqcbs;	/* HW QCB array */
162	struct		ida_qcb *qcbs;			/* kernel QCB array */
163	SLIST_HEAD(, ida_qcb)	free_qcbs;
164	STAILQ_HEAD(, ida_qcb) 	qcb_queue;
165	struct		bio_queue_head bio_queue;
166
167	struct		ida_access cmd;
168};
169
170/*
171 * drive flags
172 */
173#define	DRV_WRITEPROT		0x0001
174
175struct idad_softc {
176	device_t	dev;
177	struct 		ida_softc *controller;
178	struct		disk *disk;
179	int		drive;			/* per controller */
180	int		unit;			/* global */
181	int		cylinders;
182	int		heads;
183	int		sectors;
184	int		secsize;
185	int		secperunit;
186	int		flags;
187};
188
189struct ida_board {
190	u_int32_t	board;
191	char 		*desc;
192	struct		ida_access *accessor;
193	int		flags;
194};
195
196extern int ida_detach(device_t dev);
197extern struct ida_softc *ida_alloc(device_t dev, struct resource *regs,
198	int regs_type, int regs_id, bus_dma_tag_t parent_dmat);
199extern void ida_free(struct ida_softc *ida);
200extern int ida_init(struct ida_softc *ida);
201extern int ida_command(struct ida_softc *ida, int command, void *data,
202	int datasize, int drive, u_int32_t pblkno, int flags);
203extern void ida_submit_buf(struct ida_softc *ida, struct bio *bp);
204extern void ida_intr(void *data);
205
206extern void idad_intr(struct bio *bp);
207
208#endif /* _IDAVAR_H */
209