summaryrefslogtreecommitdiff
path: root/sys/dev/ic/sunscpalvar.h
blob: 00dfa29d40480c77001df4e58bc36d0785a71717 (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
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
/*	$NetBSD: sunscpalvar.h,v 1.10 2023/01/23 22:16:44 andvar Exp $	*/

/*
 * Copyright (c) 2001 Matthew Fredette
 * Copyright (c) 1995 David Jones, Gordon W. Ross
 * Copyright (c) 1994 Jarle Greipsland
 * All rights reserved.
 *
 * 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. The name of the authors may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 * 4. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by
 *      David Jones and Gordon Ross
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.
 */

/*
 * This file defines the interface between the machine-dependent
 * module and the machine-independent sunscpal.c module.
 */

/*
 * The sun2 and sparc use real bus_space.
 */
#if defined(sun2) || defined(__sparc__)
# define SUNSCPAL_USE_BUS_SPACE
#endif
/*
 * The sun2 and sparc use real bus_dma.
 */
#if defined(sun2) || defined(__sparc__)
#define SUNSCPAL_USE_BUS_DMA
#endif

/*
 * Handy read/write macros
 */
#ifdef SUNSCPAL_USE_BUS_SPACE
# include <sys/bus.h>
/* bus_space() variety */
#define SUNSCPAL_READ_1(sc, reg)	bus_space_read_1(sc->sunscpal_regt, \
						sc->sunscpal_regh, sc->reg)
#define SUNSCPAL_WRITE_1(sc, reg, val)	bus_space_write_1(sc->sunscpal_regt, \
						sc->sunscpal_regh, sc->reg, val)
#define SUNSCPAL_READ_2(sc, reg)	bus_space_read_2(sc->sunscpal_regt, \
						sc->sunscpal_regh, sc->reg)
#define SUNSCPAL_WRITE_2(sc, reg, val)	bus_space_write_2(sc->sunscpal_regt, \
						sc->sunscpal_regh, sc->reg, val)
#else
/* legacy memory-mapped variety */
# define SUNSCPAL_READ_1(sc, reg)	(*sc->reg)
# define SUNSCPAL_WRITE_1(sc, reg, val)	do { *(sc->reg) = val; } while(0)
# define SUNSCPAL_READ_2 SUNSCPAL_READ_1
# define SUNSCPAL_WRITE_2 SUNSCPAL_WRITE_1
#endif

#define SUNSCPAL_CLR_INTR(sc)	do { SUNSCPAL_READ_2(sc, sunscpal_dma_count); SUNSCPAL_READ_2(sc, sunscpal_icr); } while(0)
#define	SUNSCPAL_BUSY(sc)	(SUNSCPAL_READ_2(sc, sunscpal_icr) & SUNSCPAL_ICR_BUSY)

/* These are NOT artibtrary, but map to bits in sunscpal_icr */
#define SUNSCPAL_PHASE_DATA_IN	(SUNSCPAL_ICR_INPUT_OUTPUT)
#define SUNSCPAL_PHASE_DATA_OUT	(0)
#define SUNSCPAL_PHASE_COMMAND	(SUNSCPAL_ICR_COMMAND_DATA)
#define SUNSCPAL_PHASE_STATUS	(SUNSCPAL_ICR_COMMAND_DATA | \
				 SUNSCPAL_ICR_INPUT_OUTPUT)
#define SUNSCPAL_PHASE_MSG_IN	(SUNSCPAL_ICR_MESSAGE | \
				 SUNSCPAL_ICR_COMMAND_DATA | \
				 SUNSCPAL_ICR_INPUT_OUTPUT)
#define SUNSCPAL_PHASE_MSG_OUT	(SUNSCPAL_ICR_MESSAGE | \
				 SUNSCPAL_ICR_COMMAND_DATA)
#define SUNSCPAL_PHASE_UNSPEC1	(SUNSCPAL_ICR_MESSAGE | \
				 SUNSCPAL_ICR_INPUT_OUTPUT)
#define SUNSCPAL_PHASE_UNSPEC2	(SUNSCPAL_ICR_MESSAGE)
#define SUNSCPAL_BYTE_READ(sc, phase)	(((phase) & SUNSCPAL_ICR_COMMAND_DATA) ? \
					 SUNSCPAL_READ_1(sc, sunscpal_cmd_stat) : \
					 SUNSCPAL_READ_1(sc, sunscpal_data))
#define SUNSCPAL_BYTE_WRITE(sc, phase, b)	do { \
							if ((phase) & SUNSCPAL_ICR_COMMAND_DATA) { \
								SUNSCPAL_WRITE_1(sc, sunscpal_cmd_stat, b); \
							} else { \
								SUNSCPAL_WRITE_1(sc, sunscpal_data, b); \
							} \
						} while(0)
/*
 * A mask and a macro for getting the current bus phase.
 */
#define SUNSCPAL_ICR_PHASE_MASK	(SUNSCPAL_ICR_MESSAGE | \
				 SUNSCPAL_ICR_COMMAND_DATA | \
				 SUNSCPAL_ICR_INPUT_OUTPUT)
#define SUNSCPAL_BUS_PHASE(icr)	((icr) & SUNSCPAL_ICR_PHASE_MASK)

/*
 * This illegal phase is used to prevent the PAL from having
 * a phase-match condition when we don't want one, such as
 * when setting up the DMA engine or whatever...
 */
#define SUNSCPAL_PHASE_INVALID	SUNSCPAL_PHASE_UNSPEC1

/*
 * Transfers larger than 65535 bytes need to be split-up.
 * (The DMA count register is only 16 bits.)
 * Make the size an integer multiple of the page size
 * to avoid buf/cluster remap problems.  (paranoid?)
 */
#define	SUNSCPAL_MAX_DMA_LEN 0xE000

#ifdef SUNSCPAL_USE_BUS_DMA
/*
 * This structure is used to keep track of mapped DMA requests.
 */
struct sunscpal_dma_handle {
	int		dh_flags;
#define	SUNSCDH_BUSY	0x01		/* This DH is in use */
	uint8_t *	dh_mapaddr;	/* Original data pointer */
	int		dh_maplen;	/* Original data length */
	bus_dmamap_t	dh_dmamap;
#define	dh_dvma dh_dmamap->dm_segs[0].ds_addr /* VA of buffer in DVMA space */
};
typedef struct sunscpal_dma_handle *sunscpal_dma_handle_t;
#else
typedef void *sunscpal_dma_handle_t;
#endif

/* Per-request state.  This is required in order to support reselection. */
struct sunscpal_req {
	struct		scsipi_xfer *sr_xs;	/* Pointer to xfer struct, NULL=unused */
	int		sr_target, sr_lun;	/* For fast access */
	sunscpal_dma_handle_t sr_dma_hand;	/* Current DMA handle */
	uint8_t		*sr_dataptr;		/* Saved data pointer */
	int		sr_datalen;
	int		sr_flags;		/* Internal error code */
#define	SR_IMMED			1	/* Immediate command */
#define	SR_OVERDUE			2	/* Timeout while not current */
#define	SR_ERROR			4	/* Error occurred */
	int		sr_status;		/* Status code from last cmd */
};
#define	SUNSCPAL_OPENINGS	16		/* How many commands we can enqueue. */


struct sunscpal_softc {
	device_t		sc_dev;
	struct scsipi_adapter	sc_adapter;
	struct scsipi_channel	sc_channel;

#ifdef SUNSCPAL_USE_BUS_SPACE
	/* Pointers to bus_space */
	bus_space_tag_t 	sunscpal_regt;
	bus_space_handle_t 	sunscpal_regh;

	/* Pointers to PAL registers.  */
	bus_size_t	sunscpal_data;
	bus_size_t	sunscpal_cmd_stat;
	bus_size_t	sunscpal_icr;
	bus_size_t	sunscpal_dma_addr_h;
	bus_size_t	sunscpal_dma_addr_l;
	bus_size_t	sunscpal_dma_count;
	bus_size_t	sunscpal_intvec;
#else
	/* Pointers to PAL registers.  See sunscpalreg.h */
	volatile uint8_t	*sunscpal_data;
	volatile uint8_t	*sunscpal_cmd_stat;
	volatile uint16_t	*sunscpal_icr;
	volatile uint16_t	*sunscpal_dma_addr_h;
	volatile uint16_t	*sunscpal_dma_addr_l;
	volatile uint16_t	*sunscpal_dma_count;
	volatile uint8_t	*sunscpal_intvec;
#endif

	/* Pointers to DMA-related structures */
#ifdef	SUNSCPAL_USE_BUS_DMA
	bus_dma_tag_t	sunscpal_dmat;
#endif
	sunscpal_dma_handle_t	sc_dma_handles;

	/* Functions set from MD code */
#ifndef	SUNSCPAL_USE_BUS_DMA
	void		(*sc_dma_alloc)(struct sunscpal_softc *);
	void		(*sc_dma_free)(struct sunscpal_softc *);

	void		(*sc_dma_setup)(struct sunscpal_softc *);
#endif

	void		(*sc_intr_on)(struct sunscpal_softc *);
	void		(*sc_intr_off)(struct sunscpal_softc *);

	int		sc_flags;	/* Misc. flags and capabilities */
#define	SUNSCPAL_DISABLE_DMA	1	/* Do not use DMA. */

	/* Set bits in this to disable parity for some target. */
	int		sc_parity_disable;

	int 	sc_min_dma_len;	/* Smaller than this is done with PIO */

	/* Begin MI shared data */

	int		sc_state;
#define	SUNSCPAL_IDLE		   0	/* Ready for new work. */
#define SUNSCPAL_WORKING 	0x01	/* Some command is in progress. */
#define	SUNSCPAL_ABORTING	0x02	/* Bailing out */
#define SUNSCPAL_DOINGDMA	0x04	/* The FIFO data path is active! */
#define SUNSCPAL_DROP_MSGIN	0x10	/* Discard all msgs (parity err detected) */

	/* The request that has the bus now. */
	struct		sunscpal_req *sc_current;

	/* Active data pointer for current SCSI command. */
	uint8_t		*sc_dataptr;
	int		sc_datalen;
	int		sc_reqlen;

	/* Begin MI private data */

	/* The number of operations in progress on the bus */
	volatile int	sc_ncmds;

	/* Ring buffer of pending/active requests */
	struct		sunscpal_req sc_ring[SUNSCPAL_OPENINGS];
	int		sc_rr;		/* Round-robin scan pointer */

	/* Active requests, by target/LUN */
	struct		sunscpal_req *sc_matrix[8][8];

	/* Message stuff */
	int	sc_prevphase;

	u_int	sc_msgpriq;	/* Messages we want to send */
	u_int	sc_msgoutq;	/* Messages sent during last MESSAGE OUT */
	u_int	sc_msgout;	/* Message last transmitted */
#define SEND_DEV_RESET		0x01
#define SEND_PARITY_ERROR	0x02
#define SEND_ABORT		0x04
#define SEND_REJECT		0x08
#define SEND_INIT_DET_ERR	0x10
#define SEND_IDENTIFY  		0x20
#define SEND_SDTR		0x40
#define	SEND_WDTR		0x80
#define SUNSCPAL_MAX_MSG_LEN 8
	uint8_t	sc_omess[SUNSCPAL_MAX_MSG_LEN];
	uint8_t	*sc_omp;		/* Outgoing message pointer */
	uint8_t	sc_imess[SUNSCPAL_MAX_MSG_LEN];
	uint8_t	*sc_imp;		/* Incoming message pointer */
	int	sc_rev;			/* Chip revision */
#define SUNSCPAL_VARIANT_501_1006	0
#define SUNSCPAL_VARIANT_501_1045	1

};

void	sunscpal_attach(struct sunscpal_softc *, int);
int	sunscpal_detach(struct sunscpal_softc *, int);
int 	sunscpal_intr(void *);
void 	sunscpal_scsipi_request(struct scsipi_channel *,
		scsipi_adapter_req_t, void *);
int 	sunscpal_pio_in(struct sunscpal_softc *, int, int, uint8_t *);
int 	sunscpal_pio_out(struct sunscpal_softc *, int, int, uint8_t *);
void	sunscpal_init(struct sunscpal_softc *);

/* Options for no-parity, DMA, and interrupts. */
#define SUNSCPAL_OPT_NO_PARITY_CHK  0xff
#define SUNSCPAL_OPT_FORCE_POLLING 0x100
#define SUNSCPAL_OPT_DISABLE_DMA   0x200

#ifdef	SUNSCPAL_DEBUG
struct sunscpal_softc *sunscpal_debug_sc;
void sunscpal_trace(char *msg, long val);
#define	SUNSCPAL_TRACE(msg, val) sunscpal_trace(msg, val)
#else	/* SUNSCPAL_DEBUG */
#define	SUNSCPAL_TRACE(msg, val)	/* nada */
#endif	/* SUNSCPAL_DEBUG */