summaryrefslogtreecommitdiff
path: root/sys/dev/ic/siopvar_common.h
blob: da286cd0926d64d5e4bbc5caad90187d73d58aea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
/*	$OpenBSD: siopvar_common.h,v 1.7 2001/08/26 02:39:05 krw Exp $ */
/*	$NetBSD: siopvar_common.h,v 1.10 2001/01/26 21:58:56 bouyer Exp $	*/

/*
 * Copyright (c) 2000 Manuel Bouyer.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by Manuel Bouyer
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,     
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

/* common struct and routines used by siop and esiop */

#ifndef SIOP_DEFAULT_TARGET
#define SIOP_DEFAULT_TARGET 7
#endif

/* tables used by SCRIPT */
typedef struct scr_table {
	u_int32_t count;
	u_int32_t addr;
} scr_table_t ;

/* Number of scatter/gather entries */
#define SIOP_NSG	(MAXPHYS/NBPG + 1)	/* XXX NBPG */

/* Number of tags, also number of openings if tags are used */
#define SIOP_NTAG 16

/* Number of openings if tags are not used */
#define SIOP_OPENINGS 2

/*
 * This structure interfaces the SCRIPT with the driver; it describes a full
 * transfer. 
 */
struct siop_xfer_common {
	u_int8_t msg_out[16];	    /*  0 */
	u_int8_t msg_in[16];	    /* 16 */
	u_int32_t status;	    /* 32 */
	u_int32_t pad1;		    /* 36 */
	u_int32_t id;		    /* 40 */
	u_int32_t pad2;		    /* 44 */
	scr_table_t t_msgin;	    /* 48 */
	scr_table_t t_extmsgin;	    /* 56 */
	scr_table_t t_extmsgdata;   /* 64 */
	scr_table_t t_msgout;	    /* 72 */
	scr_table_t cmd;	    /* 80 */
	scr_table_t t_status;	    /* 88 */
	scr_table_t data[SIOP_NSG]; /* 96 */
} __attribute__((__packed__));

/* status can hold the SCSI_* status values, and 2 additional values: */
#define SCSI_SIOP_NOCHECK	0xfe	/* don't check the scsi status */
#define SCSI_SIOP_NOSTATUS	0xff	/* device didn't report status */

/* xfer description of the script: tables and reselect script */
struct siop_xfer {
	struct siop_xfer_common tables;
	/* u_int32_t resel[sizeof(load_dsa) / sizeof(load_dsa[0])]; */
	u_int32_t resel[25];
} __attribute__((__packed__));

/*
 * This describes a command handled by the SCSI controller.
 * These are chained in either a free list or a active list.
 * We have one queue per target.
 */
struct siop_cmd {
	TAILQ_ENTRY (siop_cmd) next;
	struct siop_softc *siop_sc; /* points back to our adapter */
	struct siop_target *siop_target; /* pointer to our target def */
	struct scsi_xfer *xs; /* xfer from the upper level */
	struct siop_xfer *siop_xfer; /* tables dealing with this xfer */
#define siop_tables siop_xfer->tables
	struct siop_cbd *siop_cbdp; /* pointer to our siop_cbd */
	bus_addr_t	dsa; /* DSA value to load */
	bus_dmamap_t	dmamap_cmd;
	bus_dmamap_t	dmamap_data;
	struct scsi_sense rs_cmd; /* request sense command buffer */
	int status;
	int flags;
	int reselslot; /* the reselect slot used */
	int tag;	/* tag used for tagged command queuing */
};

/* command block descriptors: an array of siop_cmd + an array of siop_xfer */

struct siop_cbd {
	TAILQ_ENTRY (siop_cbd) next;
	struct siop_cmd *cmds;
	struct siop_xfer *xfers;
	bus_dmamap_t xferdma; /* DMA map for this block of xfers */
};

/* status defs */
#define CMDST_FREE		0 /* cmd slot is free */
#define CMDST_READY		1 /* cmd slot is waiting for processing */
#define CMDST_ACTIVE		2 /* cmd slot is being processed */
#define CMDST_SENSE		3 /* cmd slot is requesting sense */
#define CMDST_SENSE_ACTIVE	4 /* request sense active */
#define CMDST_SENSE_DONE 	5 /* request sense done */
#define CMDST_DONE		6 /* cmd slot has been processed */
/* flags defs */
#define CMDFL_TIMEOUT	0x0001 /* cmd timed out */
#define CMDFL_TAG	0x0002 /* tagged cmd */

/* per-tag struct */
struct siop_tag {
	struct siop_cmd *active; /* active command */
	u_int reseloff; /* XXX */
};

/* per lun struct */
struct siop_lun {
	struct siop_tag siop_tag[SIOP_NTAG]; /* tag array */
	int lun_flags; /* per-lun flags, see below */
	u_int reseloff; /* XXX */
};

#define SIOP_LUNF_FULL 0x01 /* queue full message */

/* per-target struct */
struct siop_target {
	int status;	/* target status, see below */
	int flags;	/* target flags, see below */
	u_int32_t id;	/* for SELECT FROM
			 * 31-24 == SCNTL3
			 * 23-16 == SCSI id
			 * 15- 8 == SXFER
			 *  7- 0 == SCNTL4
			 */
	struct siop_lun *siop_lun[8]; /* per-lun state */
	u_int reseloff; /* XXX */
	struct siop_lunsw *lunsw; /* XXX */
};

/* target status */
#define TARST_PROBING	0 /* target is being probed */
#define TARST_ASYNC	1 /* target needs sync/wide negotiation */
#define TARST_WIDE_NEG	2 /* target is doing wide negotiation */
#define TARST_SYNC_NEG	3 /* target is doing sync negotiation */
#define TARST_PPR_NEG	4 /* target is doing PPR (Parallel Protocol Request) */
#define TARST_OK	5 /* sync/wide agreement is valid */

/* target flags */
#define TARF_SYNC	0x01 /* target can do sync xfers      */
#define TARF_WIDE	0x02 /* target can do wide xfers      */
#define TARF_TAG	0x04 /* target can do taggged queuing */
#define TARF_PPR	0x08 /* target can do PPR negotiation */

#define TARF_ISWIDE	0x10 /* target is using wide xfers    */
#define TARF_ISIUS	0x20 /* target is using IUS           */
#define TARF_ISDT	0x40 /* target is using DT            */
#define TARF_ISQAS	0x80 /* target is using QAS           */

struct siop_lunsw {
	TAILQ_ENTRY (siop_lunsw) next;
	u_int32_t lunsw_off; /* offset of this lun sw, from sc_scriptaddr*/
	u_int32_t lunsw_size; /* size of this lun sw */
};

#ifdef __HAS_NEW_BUS_DMAMAP_SYNC
#define	siop_bus_dmamap_sync(tag, map, off, len, op)	\
    bus_dmamap_sync((tag), (map), (off), (len), (op))
#else
#define	siop_bus_dmamap_sync(tag, map, off, len, op)	\
    bus_dmamap_sync((tag), (map), (op))
#endif

static __inline__ void siop_table_sync __P((struct siop_cmd *, int));
static __inline__ void
siop_table_sync(siop_cmd, ops)
	struct siop_cmd *siop_cmd;
	int ops;
{
	struct siop_softc *sc = siop_cmd->siop_sc;
        bus_addr_t offset;
        
        offset = siop_cmd->dsa -
		siop_cmd->siop_cbdp->xferdma->dm_segs[0].ds_addr;
	siop_bus_dmamap_sync(sc->sc_dmat, siop_cmd->siop_cbdp->xferdma, offset,
            sizeof(struct siop_xfer), ops);
}

void	siop_common_reset __P((struct siop_softc *));
void	siop_setuptables __P((struct siop_cmd *));
int	siop_modechange __P((struct siop_softc *));

int	siop_wdtr_neg __P((struct siop_cmd *));
int	siop_sdtr_neg __P((struct siop_cmd *));
int     siop_ppr_neg  __P((struct siop_cmd *));
void	siop_sdtr_msg __P((struct siop_cmd *, int, int, int));
void	siop_wdtr_msg __P((struct siop_cmd *, int, int));
void    siop_ppr_msg  __P((struct siop_cmd *, int, int, int));

/* actions to take at return of siop_<xxx>_neg() */
#define SIOP_NEG_NOP	0x0
#define SIOP_NEG_MSGOUT	0x1
#define SIOP_NEG_ACK	0x2
#define SIOP_NEG_MSGREJ	0x3

void	siop_print_info __P((struct siop_softc *, int));
void	siop_minphys __P((struct buf *));
void 	siop_sdp __P((struct siop_cmd *));
void	siop_clearfifo __P((struct siop_softc *));
void	siop_resetbus __P((struct siop_softc *));

int     siop_period_factor_to_scf __P((struct siop_softc *, int, int));
int     siop_scf_to_period_factor __P((struct siop_softc *, int, int));

/* XXXX should be  callbacks */
void	siop_add_dev __P((struct siop_softc *, int, int));
void	siop_del_dev __P((struct siop_softc *, int, int));