asc.c revision 1.1.2.4 1 1.1.2.4 bouyer /* $NetBSD: asc.c,v 1.1.2.4 2001/04/05 16:52:07 bouyer Exp $ */
2 1.1.2.2 bouyer /* $OpenBSD: asc.c,v 1.9 1998/03/16 09:38:39 pefo Exp $ */
3 1.1.2.2 bouyer /* NetBSD: asc.c,v 1.10 1994/12/05 19:11:12 dean Exp */
4 1.1.2.2 bouyer
5 1.1.2.2 bouyer /*-
6 1.1.2.2 bouyer * Copyright (c) 1992, 1993
7 1.1.2.2 bouyer * The Regents of the University of California. All rights reserved.
8 1.1.2.2 bouyer *
9 1.1.2.2 bouyer * This code is derived from software contributed to Berkeley by
10 1.1.2.2 bouyer * Ralph Campbell and Rick Macklem.
11 1.1.2.2 bouyer *
12 1.1.2.2 bouyer * Redistribution and use in source and binary forms, with or without
13 1.1.2.2 bouyer * modification, are permitted provided that the following conditions
14 1.1.2.2 bouyer * are met:
15 1.1.2.2 bouyer * 1. Redistributions of source code must retain the above copyright
16 1.1.2.2 bouyer * notice, this list of conditions and the following disclaimer.
17 1.1.2.2 bouyer * 2. Redistributions in binary form must reproduce the above copyright
18 1.1.2.2 bouyer * notice, this list of conditions and the following disclaimer in the
19 1.1.2.2 bouyer * documentation and/or other materials provided with the distribution.
20 1.1.2.2 bouyer * 3. All advertising materials mentioning features or use of this software
21 1.1.2.2 bouyer * must display the following acknowledgement:
22 1.1.2.2 bouyer * This product includes software developed by the University of
23 1.1.2.2 bouyer * California, Berkeley and its contributors.
24 1.1.2.2 bouyer * 4. Neither the name of the University nor the names of its contributors
25 1.1.2.2 bouyer * may be used to endorse or promote products derived from this software
26 1.1.2.2 bouyer * without specific prior written permission.
27 1.1.2.2 bouyer *
28 1.1.2.2 bouyer * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 1.1.2.2 bouyer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 1.1.2.2 bouyer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 1.1.2.2 bouyer * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 1.1.2.2 bouyer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 1.1.2.2 bouyer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 1.1.2.2 bouyer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 1.1.2.2 bouyer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 1.1.2.2 bouyer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 1.1.2.2 bouyer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 1.1.2.2 bouyer * SUCH DAMAGE.
39 1.1.2.2 bouyer *
40 1.1.2.2 bouyer * @(#)asc.c 8.3 (Berkeley) 7/3/94
41 1.1.2.2 bouyer */
42 1.1.2.2 bouyer
43 1.1.2.2 bouyer /*
44 1.1.2.2 bouyer * Mach Operating System
45 1.1.2.2 bouyer * Copyright (c) 1991,1990,1989 Carnegie Mellon University
46 1.1.2.2 bouyer * All Rights Reserved.
47 1.1.2.2 bouyer *
48 1.1.2.2 bouyer * Permission to use, copy, modify and distribute this software and its
49 1.1.2.2 bouyer * documentation is hereby granted, provided that both the copyright
50 1.1.2.2 bouyer * notice and this permission notice appear in all copies of the
51 1.1.2.2 bouyer * software, derivative works or modified versions, and any portions
52 1.1.2.2 bouyer * thereof, and that both notices appear in supporting documentation.
53 1.1.2.2 bouyer *
54 1.1.2.2 bouyer * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
55 1.1.2.2 bouyer * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
56 1.1.2.2 bouyer * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
57 1.1.2.2 bouyer *
58 1.1.2.2 bouyer * Carnegie Mellon requests users of this software to return to
59 1.1.2.2 bouyer *
60 1.1.2.2 bouyer * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
61 1.1.2.2 bouyer * School of Computer Science
62 1.1.2.2 bouyer * Carnegie Mellon University
63 1.1.2.2 bouyer * Pittsburgh PA 15213-3890
64 1.1.2.2 bouyer *
65 1.1.2.2 bouyer * any improvements or extensions that they make and grant Carnegie the
66 1.1.2.2 bouyer * rights to redistribute these changes.
67 1.1.2.2 bouyer */
68 1.1.2.2 bouyer
69 1.1.2.2 bouyer /*
70 1.1.2.2 bouyer * HISTORY
71 1.1.2.2 bouyer * Log: scsi_53C94_hdw.c,v
72 1.1.2.2 bouyer * Revision 2.5 91/02/05 17:45:07 mrt
73 1.1.2.2 bouyer * Added author notices
74 1.1.2.2 bouyer * [91/02/04 11:18:43 mrt]
75 1.1.2.2 bouyer *
76 1.1.2.2 bouyer * Changed to use new Mach copyright
77 1.1.2.2 bouyer * [91/02/02 12:17:20 mrt]
78 1.1.2.2 bouyer *
79 1.1.2.2 bouyer * Revision 2.4 91/01/08 15:48:24 rpd
80 1.1.2.2 bouyer * Added continuation argument to thread_block.
81 1.1.2.2 bouyer * [90/12/27 rpd]
82 1.1.2.2 bouyer *
83 1.1.2.2 bouyer * Revision 2.3 90/12/05 23:34:48 af
84 1.1.2.2 bouyer * Recovered from pmax merge.. and from the destruction of a disk.
85 1.1.2.2 bouyer * [90/12/03 23:40:40 af]
86 1.1.2.2 bouyer *
87 1.1.2.2 bouyer * Revision 2.1.1.1 90/11/01 03:39:09 af
88 1.1.2.2 bouyer * Created, from the DEC specs:
89 1.1.2.2 bouyer * "PMAZ-AA TURBOchannel SCSI Module Functional Specification"
90 1.1.2.2 bouyer * Workstation Systems Engineering, Palo Alto, CA. Aug 27, 1990.
91 1.1.2.2 bouyer * And from the NCR data sheets
92 1.1.2.2 bouyer * "NCR 53C94, 53C95, 53C96 Advances SCSI Controller"
93 1.1.2.2 bouyer * [90/09/03 af]
94 1.1.2.2 bouyer */
95 1.1.2.2 bouyer
96 1.1.2.2 bouyer /*
97 1.1.2.2 bouyer * File: scsi_53C94_hdw.h
98 1.1.2.2 bouyer * Author: Alessandro Forin, Carnegie Mellon University
99 1.1.2.2 bouyer * Date: 9/90
100 1.1.2.2 bouyer *
101 1.1.2.2 bouyer * Bottom layer of the SCSI driver: chip-dependent functions
102 1.1.2.2 bouyer *
103 1.1.2.2 bouyer * This file contains the code that is specific to the NCR 53C94
104 1.1.2.2 bouyer * SCSI chip (Host Bus Adapter in SCSI parlance): probing, start
105 1.1.2.2 bouyer * operation, and interrupt routine.
106 1.1.2.2 bouyer */
107 1.1.2.2 bouyer
108 1.1.2.2 bouyer /*
109 1.1.2.2 bouyer * This layer works based on small simple 'scripts' that are installed
110 1.1.2.2 bouyer * at the start of the command and drive the chip to completion.
111 1.1.2.2 bouyer * The idea comes from the specs of the NCR 53C700 'script' processor.
112 1.1.2.2 bouyer *
113 1.1.2.2 bouyer * There are various reasons for this, mainly
114 1.1.2.2 bouyer * - Performance: identify the common (successful) path, and follow it;
115 1.1.2.2 bouyer * at interrupt time no code is needed to find the current status
116 1.1.2.2 bouyer * - Code size: it should be easy to compact common operations
117 1.1.2.2 bouyer * - Adaptability: the code skeleton should adapt to different chips without
118 1.1.2.2 bouyer * terrible complications.
119 1.1.2.2 bouyer * - Error handling: and it is easy to modify the actions performed
120 1.1.2.2 bouyer * by the scripts to cope with strange but well identified sequences
121 1.1.2.2 bouyer *
122 1.1.2.2 bouyer */
123 1.1.2.2 bouyer
124 1.1.2.2 bouyer #include <sys/param.h>
125 1.1.2.2 bouyer #include <sys/systm.h>
126 1.1.2.2 bouyer #include <sys/dkstat.h>
127 1.1.2.2 bouyer #include <sys/buf.h>
128 1.1.2.2 bouyer #include <sys/proc.h>
129 1.1.2.2 bouyer #include <sys/conf.h>
130 1.1.2.2 bouyer #include <sys/errno.h>
131 1.1.2.2 bouyer #include <sys/device.h>
132 1.1.2.2 bouyer #include <uvm/uvm_extern.h>
133 1.1.2.2 bouyer
134 1.1.2.2 bouyer #include <dev/scsipi/scsi_all.h>
135 1.1.2.2 bouyer #include <dev/scsipi/scsipi_all.h>
136 1.1.2.2 bouyer #include <dev/scsipi/scsiconf.h>
137 1.1.2.2 bouyer
138 1.1.2.2 bouyer #include <mips/locore.h> /* for mips3_HitFlushDCache() */
139 1.1.2.2 bouyer #include <machine/cpu.h>
140 1.1.2.2 bouyer #include <machine/autoconf.h>
141 1.1.2.2 bouyer #include <machine/bus.h>
142 1.1.2.2 bouyer
143 1.1.2.2 bouyer #include <arc/jazz/jazziovar.h>
144 1.1.2.2 bouyer #include <arc/jazz/jazzdmatlbreg.h>
145 1.1.2.2 bouyer #include <arc/jazz/dma.h>
146 1.1.2.2 bouyer #include <arc/jazz/scsi.h>
147 1.1.2.2 bouyer #include <arc/jazz/ascreg.h>
148 1.1.2.2 bouyer
149 1.1.2.2 bouyer #include <arc/jazz/pica.h>
150 1.1.2.2 bouyer #include <arc/arc/arctype.h>
151 1.1.2.2 bouyer
152 1.1.2.2 bouyer
153 1.1.2.2 bouyer #define readback(a) { register int foo; foo = (a); }
154 1.1.2.2 bouyer
155 1.1.2.2 bouyer /*
156 1.1.2.2 bouyer * In 4ns ticks.
157 1.1.2.2 bouyer */
158 1.1.2.2 bouyer int asc_to_scsi_period[] = {
159 1.1.2.2 bouyer 32,
160 1.1.2.2 bouyer 33,
161 1.1.2.2 bouyer 34,
162 1.1.2.2 bouyer 35,
163 1.1.2.2 bouyer 5,
164 1.1.2.2 bouyer 5,
165 1.1.2.2 bouyer 6,
166 1.1.2.2 bouyer 7,
167 1.1.2.2 bouyer 8,
168 1.1.2.2 bouyer 9,
169 1.1.2.2 bouyer 10,
170 1.1.2.2 bouyer 11,
171 1.1.2.2 bouyer 12,
172 1.1.2.2 bouyer 13,
173 1.1.2.2 bouyer 14,
174 1.1.2.2 bouyer 15,
175 1.1.2.2 bouyer 16,
176 1.1.2.2 bouyer 17,
177 1.1.2.2 bouyer 18,
178 1.1.2.2 bouyer 19,
179 1.1.2.2 bouyer 20,
180 1.1.2.2 bouyer 21,
181 1.1.2.2 bouyer 22,
182 1.1.2.2 bouyer 23,
183 1.1.2.2 bouyer 24,
184 1.1.2.2 bouyer 25,
185 1.1.2.2 bouyer 26,
186 1.1.2.2 bouyer 27,
187 1.1.2.2 bouyer 28,
188 1.1.2.2 bouyer 29,
189 1.1.2.2 bouyer 30,
190 1.1.2.2 bouyer 31,
191 1.1.2.2 bouyer };
192 1.1.2.2 bouyer
193 1.1.2.2 bouyer /*
194 1.1.2.2 bouyer * Internal forward declarations.
195 1.1.2.2 bouyer */
196 1.1.2.2 bouyer struct asc_softc;
197 1.1.2.2 bouyer static void asc_reset __P((struct asc_softc *, asc_regmap_t *));
198 1.1.2.2 bouyer static void asc_startcmd __P((struct asc_softc *, int));
199 1.1.2.2 bouyer
200 1.1.2.2 bouyer #ifdef DEBUG
201 1.1.2.2 bouyer int asc_debug = 1;
202 1.1.2.2 bouyer int asc_debug_cmd;
203 1.1.2.2 bouyer int asc_debug_bn;
204 1.1.2.2 bouyer int asc_debug_sz;
205 1.1.2.2 bouyer #define NLOG 16
206 1.1.2.2 bouyer struct asc_log {
207 1.1.2.2 bouyer u_int status;
208 1.1.2.2 bouyer u_char state;
209 1.1.2.2 bouyer u_char msg;
210 1.1.2.2 bouyer int target;
211 1.1.2.2 bouyer int resid;
212 1.1.2.2 bouyer } asc_log[NLOG], *asc_logp = asc_log;
213 1.1.2.2 bouyer #define PACK(unit, status, ss, ir) \
214 1.1.2.2 bouyer ((unit << 24) | (status << 16) | (ss << 8) | ir)
215 1.1.2.2 bouyer #endif
216 1.1.2.2 bouyer
217 1.1.2.2 bouyer /*
218 1.1.2.2 bouyer * Scripts are entries in a state machine table.
219 1.1.2.2 bouyer * A script has four parts: a pre-condition, an action, a command to the chip,
220 1.1.2.2 bouyer * and an index into asc_scripts for the next state. The first triggers error
221 1.1.2.2 bouyer * handling if not satisfied and in our case it is formed by the
222 1.1.2.2 bouyer * values of the interrupt register and status register, this
223 1.1.2.2 bouyer * basically captures the phase of the bus and the TC and BS
224 1.1.2.2 bouyer * bits. The action part is just a function pointer, and the
225 1.1.2.2 bouyer * command is what the 53C94 should be told to do at the end
226 1.1.2.2 bouyer * of the action processing. This command is only issued and the
227 1.1.2.2 bouyer * script proceeds if the action routine returns TRUE.
228 1.1.2.2 bouyer * See asc_intr() for how and where this is all done.
229 1.1.2.2 bouyer */
230 1.1.2.2 bouyer typedef struct script {
231 1.1.2.2 bouyer int condition; /* expected state at interrupt time */
232 1.1.2.2 bouyer int (*action)(struct asc_softc *, int, int, int);
233 1.1.2.2 bouyer /* extra operations */
234 1.1.2.2 bouyer int command; /* command to the chip */
235 1.1.2.2 bouyer struct script *next; /* index into asc_scripts for next state */
236 1.1.2.2 bouyer } script_t;
237 1.1.2.2 bouyer
238 1.1.2.2 bouyer /* Matching on the condition value */
239 1.1.2.2 bouyer #define SCRIPT_MATCH(ir, csr) ((ir) | (((csr) & 0x67) << 8))
240 1.1.2.2 bouyer
241 1.1.2.2 bouyer
242 1.1.2.2 bouyer /* forward decls of script actions */
243 1.1.2.2 bouyer /* when nothing needed */
244 1.1.2.2 bouyer static int script_nop __P((struct asc_softc *, int, int, int));
245 1.1.2.2 bouyer /* all come to an end */
246 1.1.2.2 bouyer static int asc_end __P((struct asc_softc *, int, int, int));
247 1.1.2.2 bouyer /* get status from target */
248 1.1.2.2 bouyer static int asc_get_status __P((struct asc_softc *, int, int, int));
249 1.1.2.2 bouyer /* start reading data from target */
250 1.1.2.2 bouyer static int asc_dma_in __P((struct asc_softc *, int, int, int));
251 1.1.2.2 bouyer /* cleanup after all data is read */
252 1.1.2.2 bouyer static int asc_last_dma_in __P((struct asc_softc *, int, int, int));
253 1.1.2.2 bouyer /* resume data in after a message */
254 1.1.2.2 bouyer static int asc_resume_in __P((struct asc_softc *, int, int, int));
255 1.1.2.2 bouyer /* resume DMA after a disconnect */
256 1.1.2.2 bouyer static int asc_resume_dma_in __P((struct asc_softc *, int, int, int));
257 1.1.2.2 bouyer /* send data to target via dma */
258 1.1.2.2 bouyer static int asc_dma_out __P((struct asc_softc *, int, int, int));
259 1.1.2.2 bouyer /* cleanup after all data is written */
260 1.1.2.2 bouyer static int asc_last_dma_out __P((struct asc_softc *, int, int, int));
261 1.1.2.2 bouyer /* resume data out after a message */
262 1.1.2.2 bouyer static int asc_resume_out __P((struct asc_softc *, int, int, int));
263 1.1.2.2 bouyer /* resume DMA after a disconnect */
264 1.1.2.2 bouyer static int asc_resume_dma_out __P((struct asc_softc *, int, int, int));
265 1.1.2.2 bouyer /* negotiate sync xfer */
266 1.1.2.2 bouyer static int asc_sendsync __P((struct asc_softc *, int, int, int));
267 1.1.2.2 bouyer /* negotiate sync xfer */
268 1.1.2.2 bouyer static int asc_replysync __P((struct asc_softc *, int, int, int));
269 1.1.2.2 bouyer /* process a message byte */
270 1.1.2.2 bouyer static int asc_msg_in __P((struct asc_softc *, int, int, int));
271 1.1.2.2 bouyer /* process an expected disconnect */
272 1.1.2.2 bouyer static int asc_disconnect __P((struct asc_softc *, int, int, int));
273 1.1.2.2 bouyer
274 1.1.2.2 bouyer /* Define the index into asc_scripts for various state transitions */
275 1.1.2.2 bouyer #define SCRIPT_DATA_IN 0
276 1.1.2.2 bouyer #define SCRIPT_CONTINUE_IN 2
277 1.1.2.2 bouyer #define SCRIPT_DATA_OUT 3
278 1.1.2.2 bouyer #define SCRIPT_CONTINUE_OUT 5
279 1.1.2.2 bouyer #define SCRIPT_SIMPLE 6
280 1.1.2.2 bouyer #define SCRIPT_GET_STATUS 7
281 1.1.2.2 bouyer #define SCRIPT_DONE 8
282 1.1.2.2 bouyer #define SCRIPT_MSG_IN 9
283 1.1.2.2 bouyer #define SCRIPT_REPLY_SYNC 11
284 1.1.2.2 bouyer #define SCRIPT_TRY_SYNC 12
285 1.1.2.2 bouyer #define SCRIPT_DISCONNECT 15
286 1.1.2.2 bouyer #define SCRIPT_RESEL 16
287 1.1.2.2 bouyer #define SCRIPT_RESUME_IN 17
288 1.1.2.2 bouyer #define SCRIPT_RESUME_DMA_IN 18
289 1.1.2.2 bouyer #define SCRIPT_RESUME_OUT 19
290 1.1.2.2 bouyer #define SCRIPT_RESUME_DMA_OUT 20
291 1.1.2.2 bouyer #define SCRIPT_RESUME_NO_DATA 21
292 1.1.2.2 bouyer
293 1.1.2.2 bouyer /*
294 1.1.2.2 bouyer * Scripts
295 1.1.2.2 bouyer */
296 1.1.2.2 bouyer script_t asc_scripts[] = {
297 1.1.2.2 bouyer /* start data in */
298 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_DATAI), /* 0 */
299 1.1.2.2 bouyer asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
300 1.1.2.2 bouyer &asc_scripts[SCRIPT_DATA_IN + 1]},
301 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS), /* 1 */
302 1.1.2.2 bouyer asc_last_dma_in, ASC_CMD_I_COMPLETE,
303 1.1.2.2 bouyer &asc_scripts[SCRIPT_GET_STATUS]},
304 1.1.2.2 bouyer
305 1.1.2.2 bouyer /* continue data in after a chunk is finished */
306 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI), /* 2 */
307 1.1.2.2 bouyer asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
308 1.1.2.2 bouyer &asc_scripts[SCRIPT_DATA_IN + 1]},
309 1.1.2.2 bouyer
310 1.1.2.2 bouyer /* start data out */
311 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_DATAO), /* 3 */
312 1.1.2.2 bouyer asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
313 1.1.2.2 bouyer &asc_scripts[SCRIPT_DATA_OUT + 1]},
314 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS), /* 4 */
315 1.1.2.2 bouyer asc_last_dma_out, ASC_CMD_I_COMPLETE,
316 1.1.2.2 bouyer &asc_scripts[SCRIPT_GET_STATUS]},
317 1.1.2.2 bouyer
318 1.1.2.2 bouyer /* continue data out after a chunk is finished */
319 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO), /* 5 */
320 1.1.2.2 bouyer asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
321 1.1.2.2 bouyer &asc_scripts[SCRIPT_DATA_OUT + 1]},
322 1.1.2.2 bouyer
323 1.1.2.2 bouyer /* simple command with no data transfer */
324 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_STATUS), /* 6 */
325 1.1.2.2 bouyer script_nop, ASC_CMD_I_COMPLETE,
326 1.1.2.2 bouyer &asc_scripts[SCRIPT_GET_STATUS]},
327 1.1.2.2 bouyer
328 1.1.2.2 bouyer /* get status and finish command */
329 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_FC, ASC_PHASE_MSG_IN), /* 7 */
330 1.1.2.2 bouyer asc_get_status, ASC_CMD_MSG_ACPT,
331 1.1.2.2 bouyer &asc_scripts[SCRIPT_DONE]},
332 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_DISC, 0), /* 8 */
333 1.1.2.2 bouyer asc_end, ASC_CMD_NOP,
334 1.1.2.2 bouyer &asc_scripts[SCRIPT_DONE]},
335 1.1.2.2 bouyer
336 1.1.2.2 bouyer /* message in */
337 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_FC, ASC_PHASE_MSG_IN), /* 9 */
338 1.1.2.2 bouyer asc_msg_in, ASC_CMD_MSG_ACPT,
339 1.1.2.2 bouyer &asc_scripts[SCRIPT_MSG_IN + 1]},
340 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_IN), /* 10 */
341 1.1.2.2 bouyer script_nop, ASC_CMD_XFER_INFO,
342 1.1.2.2 bouyer &asc_scripts[SCRIPT_MSG_IN]},
343 1.1.2.2 bouyer
344 1.1.2.2 bouyer /* send synchonous negotiation reply */
345 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_OUT), /* 11 */
346 1.1.2.2 bouyer asc_replysync, ASC_CMD_XFER_INFO,
347 1.1.2.2 bouyer &asc_scripts[SCRIPT_REPLY_SYNC]},
348 1.1.2.2 bouyer
349 1.1.2.2 bouyer /* try to negotiate synchonous transfer parameters */
350 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_MSG_OUT), /* 12 */
351 1.1.2.2 bouyer asc_sendsync, ASC_CMD_XFER_INFO,
352 1.1.2.2 bouyer &asc_scripts[SCRIPT_TRY_SYNC + 1]},
353 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_IN), /* 13 */
354 1.1.2.2 bouyer script_nop, ASC_CMD_XFER_INFO,
355 1.1.2.2 bouyer &asc_scripts[SCRIPT_MSG_IN]},
356 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_COMMAND), /* 14 */
357 1.1.2.2 bouyer script_nop, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
358 1.1.2.2 bouyer &asc_scripts[SCRIPT_RESUME_NO_DATA]},
359 1.1.2.2 bouyer
360 1.1.2.2 bouyer /* handle a disconnect */
361 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_DISC, ASC_PHASE_DATAO), /* 15 */
362 1.1.2.2 bouyer asc_disconnect, ASC_CMD_ENABLE_SEL,
363 1.1.2.2 bouyer &asc_scripts[SCRIPT_RESEL]},
364 1.1.2.2 bouyer
365 1.1.2.2 bouyer /* reselect sequence: this is just a placeholder so match fails */
366 1.1.2.2 bouyer {SCRIPT_MATCH(0, ASC_PHASE_MSG_IN), /* 16 */
367 1.1.2.2 bouyer script_nop, ASC_CMD_MSG_ACPT,
368 1.1.2.2 bouyer &asc_scripts[SCRIPT_RESEL]},
369 1.1.2.2 bouyer
370 1.1.2.2 bouyer /* resume data in after a message */
371 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI), /* 17 */
372 1.1.2.2 bouyer asc_resume_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
373 1.1.2.2 bouyer &asc_scripts[SCRIPT_DATA_IN + 1]},
374 1.1.2.2 bouyer
375 1.1.2.2 bouyer /* resume partial DMA data in after a message */
376 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI), /* 18 */
377 1.1.2.2 bouyer asc_resume_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
378 1.1.2.2 bouyer &asc_scripts[SCRIPT_DATA_IN + 1]},
379 1.1.2.2 bouyer
380 1.1.2.2 bouyer /* resume data out after a message */
381 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO), /* 19 */
382 1.1.2.2 bouyer asc_resume_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
383 1.1.2.2 bouyer &asc_scripts[SCRIPT_DATA_OUT + 1]},
384 1.1.2.2 bouyer
385 1.1.2.2 bouyer /* resume partial DMA data out after a message */
386 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO), /* 20 */
387 1.1.2.2 bouyer asc_resume_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
388 1.1.2.2 bouyer &asc_scripts[SCRIPT_DATA_OUT + 1]},
389 1.1.2.2 bouyer
390 1.1.2.2 bouyer /* resume after a message when there is no more data */
391 1.1.2.2 bouyer {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS), /* 21 */
392 1.1.2.2 bouyer script_nop, ASC_CMD_I_COMPLETE,
393 1.1.2.2 bouyer &asc_scripts[SCRIPT_GET_STATUS]},
394 1.1.2.2 bouyer };
395 1.1.2.2 bouyer
396 1.1.2.2 bouyer /*
397 1.1.2.2 bouyer * State kept for each active SCSI device.
398 1.1.2.2 bouyer */
399 1.1.2.2 bouyer typedef struct scsi_state {
400 1.1.2.2 bouyer script_t *script; /* saved script while processing error */
401 1.1.2.2 bouyer struct scsi_generic cmd;/* storage for scsi command */
402 1.1.2.2 bouyer int statusByte; /* status byte returned during STATUS_PHASE */
403 1.1.2.2 bouyer u_int dmaBufSize; /* DMA buffer size */
404 1.1.2.2 bouyer int dmalen; /* amount to transfer in this chunk */
405 1.1.2.2 bouyer int dmaresid; /* amount not transfered if chunk suspended */
406 1.1.2.2 bouyer int cmdlen; /* length of command in cmd */
407 1.1.2.2 bouyer int buflen; /* total remaining amount of data to transfer */
408 1.1.2.2 bouyer vaddr_t buf; /* current pointer within scsicmd->buf */
409 1.1.2.2 bouyer int flags; /* see below */
410 1.1.2.2 bouyer int msglen; /* number of message bytes to read */
411 1.1.2.2 bouyer int msgcnt; /* number of message bytes received */
412 1.1.2.2 bouyer u_char sync_period; /* DMA synchronous period */
413 1.1.2.2 bouyer u_char sync_offset; /* DMA synchronous xfer offset or 0 if async */
414 1.1.2.2 bouyer u_char msg_out; /* next MSG_OUT byte to send */
415 1.1.2.2 bouyer u_char msg_in[16]; /* buffer for multibyte messages */
416 1.1.2.2 bouyer } State;
417 1.1.2.2 bouyer
418 1.1.2.2 bouyer /* state flags */
419 1.1.2.2 bouyer #define DISCONN 0x001 /* true if currently disconnected from bus */
420 1.1.2.2 bouyer #define DMA_IN_PROGRESS 0x002 /* true if data DMA started */
421 1.1.2.2 bouyer #define DMA_IN 0x004 /* true if reading from SCSI device */
422 1.1.2.2 bouyer #define DMA_OUT 0x010 /* true if writing to SCSI device */
423 1.1.2.2 bouyer #define DID_SYNC 0x020 /* true if synchronous offset was negotiated */
424 1.1.2.2 bouyer #define TRY_SYNC 0x040 /* true if try neg. synchronous offset */
425 1.1.2.2 bouyer #define PARITY_ERR 0x080 /* true if parity error seen */
426 1.1.2.2 bouyer
427 1.1.2.2 bouyer /*
428 1.1.2.2 bouyer * State kept for each active SCSI host interface (53C94).
429 1.1.2.2 bouyer */
430 1.1.2.2 bouyer struct asc_softc {
431 1.1.2.2 bouyer struct device sc_dev; /* use as a device */
432 1.1.2.2 bouyer asc_regmap_t *regs; /* chip address */
433 1.1.2.2 bouyer dma_softc_t __dma; /* stupid macro..... */
434 1.1.2.2 bouyer dma_softc_t *dma; /* dma control structure */
435 1.1.2.2 bouyer int sc_id; /* SCSI ID of this interface */
436 1.1.2.2 bouyer int myidmask; /* ~(1 << myid) */
437 1.1.2.2 bouyer int state; /* current SCSI connection state */
438 1.1.2.2 bouyer int target; /* target SCSI ID if busy */
439 1.1.2.2 bouyer script_t *script; /* next expected interrupt & action */
440 1.1.2.2 bouyer struct scsipi_xfer *cmdq[ASC_NCMD];/* Pointer to queued commands */
441 1.1.2.2 bouyer struct scsipi_xfer *cmd[ASC_NCMD];/* Pointer to current active command */
442 1.1.2.2 bouyer State st[ASC_NCMD]; /* state info for each active command */
443 1.1.2.2 bouyer int min_period; /* Min transfer period clk/byte */
444 1.1.2.2 bouyer int max_period; /* Max transfer period clk/byte */
445 1.1.2.2 bouyer int ccf; /* CCF, whatever that really is? */
446 1.1.2.2 bouyer int timeout_250; /* 250ms timeout */
447 1.1.2.2 bouyer int tb_ticks; /* 4ns. ticks/tb channel ticks */
448 1.1.2.2 bouyer int is24bit; /* if 53CF94/96-2, 24bit address */
449 1.1.2.3 bouyer struct scsipi_channel sc_channel;
450 1.1.2.2 bouyer struct scsipi_adapter sc_adapter;
451 1.1.2.2 bouyer };
452 1.1.2.2 bouyer
453 1.1.2.2 bouyer #define ASC_STATE_IDLE 0 /* idle state */
454 1.1.2.2 bouyer #define ASC_STATE_BUSY 1 /* selecting or currently connected */
455 1.1.2.2 bouyer #define ASC_STATE_TARGET 2 /* currently selected as target */
456 1.1.2.2 bouyer #define ASC_STATE_RESEL 3 /* currently waiting for reselect */
457 1.1.2.2 bouyer
458 1.1.2.2 bouyer typedef struct asc_softc *asc_softc_t;
459 1.1.2.2 bouyer
460 1.1.2.2 bouyer /*
461 1.1.2.2 bouyer * Autoconfiguration data for config.
462 1.1.2.2 bouyer */
463 1.1.2.2 bouyer int ascmatch __P((struct device *, struct cfdata *, void *));
464 1.1.2.2 bouyer void ascattach __P((struct device *, struct device *, void *));
465 1.1.2.2 bouyer
466 1.1.2.2 bouyer int asc_doprobe __P((void *, int, int, struct device *));
467 1.1.2.2 bouyer
468 1.1.2.2 bouyer struct cfattach asc_ca = {
469 1.1.2.2 bouyer sizeof(struct asc_softc), ascmatch, ascattach
470 1.1.2.2 bouyer };
471 1.1.2.2 bouyer
472 1.1.2.2 bouyer /*
473 1.1.2.2 bouyer * Glue to the machine dependent scsi
474 1.1.2.2 bouyer */
475 1.1.2.4 bouyer void asc_scsipi_request __P((struct scsipi_channel *,
476 1.1.2.3 bouyer scsipi_adapter_req_t, void *));
477 1.1.2.2 bouyer
478 1.1.2.2 bouyer static int asc_intr __P((void *));
479 1.1.2.4 bouyer static void asc_poll __P((struct asc_softc *, int));
480 1.1.2.2 bouyer #ifdef DEBUG
481 1.1.2.2 bouyer static void asc_DumpLog __P((char *));
482 1.1.2.2 bouyer #endif
483 1.1.2.2 bouyer
484 1.1.2.2 bouyer /*
485 1.1.2.2 bouyer * Match driver based on name
486 1.1.2.2 bouyer */
487 1.1.2.2 bouyer int
488 1.1.2.2 bouyer ascmatch(parent, match, aux)
489 1.1.2.2 bouyer struct device *parent;
490 1.1.2.2 bouyer struct cfdata *match;
491 1.1.2.2 bouyer void *aux;
492 1.1.2.2 bouyer {
493 1.1.2.2 bouyer struct jazzio_attach_args *ja = aux;
494 1.1.2.2 bouyer
495 1.1.2.2 bouyer if(strcmp(ja->ja_name, "asc") != 0)
496 1.1.2.2 bouyer return (0);
497 1.1.2.2 bouyer return (1);
498 1.1.2.2 bouyer }
499 1.1.2.2 bouyer
500 1.1.2.2 bouyer void
501 1.1.2.2 bouyer ascattach(parent, self, aux)
502 1.1.2.2 bouyer struct device *parent;
503 1.1.2.2 bouyer struct device *self;
504 1.1.2.2 bouyer void *aux;
505 1.1.2.2 bouyer {
506 1.1.2.2 bouyer struct jazzio_attach_args *ja = aux;
507 1.1.2.2 bouyer asc_softc_t asc = (void *)self;
508 1.1.2.2 bouyer asc_regmap_t *regs;
509 1.1.2.2 bouyer int id, s, i;
510 1.1.2.2 bouyer int bufsiz;
511 1.1.2.2 bouyer
512 1.1.2.2 bouyer /*
513 1.1.2.2 bouyer * Initialize hw descriptor, cache some pointers
514 1.1.2.2 bouyer */
515 1.1.2.2 bouyer asc->regs = (asc_regmap_t *)ja->ja_addr; /* XXX */
516 1.1.2.2 bouyer
517 1.1.2.2 bouyer /*
518 1.1.2.2 bouyer * Set up machine dependencies.
519 1.1.2.2 bouyer * 1) how to do dma
520 1.1.2.2 bouyer * 2) timing based on chip clock frequency
521 1.1.2.2 bouyer */
522 1.1.2.2 bouyer switch (cputype) {
523 1.1.2.2 bouyer case ACER_PICA_61:
524 1.1.2.2 bouyer case MAGNUM:
525 1.1.2.2 bouyer bufsiz = 63 * 1024; /*XXX check if code handles 0 as 64k */
526 1.1.2.2 bouyer asc->dma = &asc->__dma;
527 1.1.2.2 bouyer asc_dma_init(asc->dma);
528 1.1.2.2 bouyer break;
529 1.1.2.2 bouyer default:
530 1.1.2.2 bouyer bufsiz = 64 * 1024;
531 1.1.2.2 bouyer };
532 1.1.2.2 bouyer /*
533 1.1.2.2 bouyer * Now for timing. The pica has a 25Mhz, NEC M403 has a 40MHz.
534 1.1.2.2 bouyer */
535 1.1.2.2 bouyer switch (cputype) {
536 1.1.2.2 bouyer case MAGNUM: /* XXX - NEC M403 */
537 1.1.2.2 bouyer asc->min_period = ASC_MIN_PERIOD40;
538 1.1.2.2 bouyer asc->max_period = ASC_MAX_PERIOD40;
539 1.1.2.2 bouyer asc->ccf = ASC_CCF(40);
540 1.1.2.2 bouyer asc->timeout_250 = ASC_TIMEOUT_250(40,
541 1.1.2.2 bouyer asc->ccf != 0 ? asc->ccf : 8);
542 1.1.2.2 bouyer asc->tb_ticks = 6; /* 6.25 */
543 1.1.2.2 bouyer break;
544 1.1.2.2 bouyer case ACER_PICA_61:
545 1.1.2.2 bouyer asc->min_period = ASC_MIN_PERIOD25;
546 1.1.2.2 bouyer asc->max_period = ASC_MAX_PERIOD25;
547 1.1.2.2 bouyer asc->ccf = ASC_CCF(25);
548 1.1.2.2 bouyer asc->timeout_250 = ASC_TIMEOUT_250(25, asc->ccf);
549 1.1.2.2 bouyer asc->tb_ticks = 10;
550 1.1.2.2 bouyer break;
551 1.1.2.2 bouyer default:
552 1.1.2.2 bouyer asc->min_period = ASC_MIN_PERIOD12;
553 1.1.2.2 bouyer asc->max_period = ASC_MAX_PERIOD12;
554 1.1.2.2 bouyer asc->ccf = ASC_CCF(13);
555 1.1.2.2 bouyer asc->timeout_250 = ASC_TIMEOUT_250(13, asc->ccf);
556 1.1.2.2 bouyer asc->tb_ticks = 20;
557 1.1.2.2 bouyer break;
558 1.1.2.2 bouyer };
559 1.1.2.2 bouyer
560 1.1.2.2 bouyer asc->state = ASC_STATE_IDLE;
561 1.1.2.2 bouyer asc->target = -1;
562 1.1.2.2 bouyer
563 1.1.2.2 bouyer regs = asc->regs;
564 1.1.2.2 bouyer
565 1.1.2.2 bouyer /*
566 1.1.2.2 bouyer * Reset chip, fully. Note that interrupts are already enabled.
567 1.1.2.2 bouyer */
568 1.1.2.2 bouyer s = splbio();
569 1.1.2.2 bouyer
570 1.1.2.2 bouyer /* preserve our ID for now */
571 1.1.2.2 bouyer asc->sc_id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID;
572 1.1.2.2 bouyer asc->myidmask = ~(1 << asc->sc_id);
573 1.1.2.2 bouyer
574 1.1.2.2 bouyer /* identify 53CF9x-2 or not */
575 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_RESET;
576 1.1.2.2 bouyer wbflush(); DELAY(25);
577 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_DMA | ASC_CMD_NOP;
578 1.1.2.2 bouyer wbflush(); DELAY(25);
579 1.1.2.2 bouyer regs->asc_cnfg2 = ASC_CNFG2_FE;
580 1.1.2.2 bouyer wbflush(); DELAY(25);
581 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_DMA | ASC_CMD_NOP;
582 1.1.2.2 bouyer wbflush(); DELAY(25);
583 1.1.2.2 bouyer asc->is24bit = regs->asc_id == ASC_ID_53CF94;
584 1.1.2.2 bouyer
585 1.1.2.2 bouyer asc_reset(asc, regs);
586 1.1.2.2 bouyer
587 1.1.2.2 bouyer /*
588 1.1.2.2 bouyer * Our SCSI id on the bus.
589 1.1.2.2 bouyer * The user can set this via the prom on 3maxen/picaen.
590 1.1.2.2 bouyer * If this changes it is easy to fix: make a default that
591 1.1.2.2 bouyer * can be changed as boot arg.
592 1.1.2.2 bouyer */
593 1.1.2.2 bouyer #ifdef unneeded
594 1.1.2.2 bouyer regs->asc_cnfg1 = (regs->asc_cnfg1 & ~ASC_CNFG1_MY_BUS_ID) |
595 1.1.2.2 bouyer (scsi_initiator_id[unit] & 0x7);
596 1.1.2.2 bouyer asc->sc_id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID;
597 1.1.2.2 bouyer #endif
598 1.1.2.2 bouyer id = asc->sc_id;
599 1.1.2.2 bouyer splx(s);
600 1.1.2.2 bouyer
601 1.1.2.2 bouyer /*
602 1.1.2.2 bouyer * Give each target its DMA buffer region.
603 1.1.2.2 bouyer * The buffer address is the same for all targets,
604 1.1.2.2 bouyer * the allocated dma viritual scatter/gather space.
605 1.1.2.2 bouyer */
606 1.1.2.2 bouyer for (i = 0; i < ASC_NCMD; i++) {
607 1.1.2.2 bouyer asc->st[i].dmaBufSize = bufsiz;
608 1.1.2.2 bouyer }
609 1.1.2.2 bouyer
610 1.1.2.2 bouyer /*
611 1.1.2.2 bouyer * Set up interrupt handler.
612 1.1.2.2 bouyer */
613 1.1.2.2 bouyer jazzio_intr_establish(ja->ja_intr, asc_intr, (void *)asc);
614 1.1.2.2 bouyer
615 1.1.2.2 bouyer printf(": %s, target %d\n", asc->is24bit ? "NCR53CF9X-2" : "NCR53C94",
616 1.1.2.2 bouyer id);
617 1.1.2.2 bouyer
618 1.1.2.3 bouyer asc->sc_adapter.adapt_dev = &asc->sc_dev;
619 1.1.2.3 bouyer asc->sc_adapter.adapt_nchannels = 1;
620 1.1.2.3 bouyer asc->sc_adapter.adapt_openings = 7;
621 1.1.2.3 bouyer asc->sc_adapter.adapt_max_periph = 1;
622 1.1.2.3 bouyer asc->sc_adapter.adapt_ioctl = NULL;
623 1.1.2.3 bouyer asc->sc_adapter.adapt_minphys = minphys;
624 1.1.2.3 bouyer asc->sc_adapter.adapt_request = asc_scsipi_request;
625 1.1.2.3 bouyer
626 1.1.2.3 bouyer memset(&asc->sc_channel, 0, sizeof(asc->sc_channel));
627 1.1.2.4 bouyer asc->sc_channel.chan_adapter = &asc->sc_adapter;
628 1.1.2.3 bouyer asc->sc_channel.chan_bustype = &scsi_bustype;
629 1.1.2.3 bouyer asc->sc_channel.chan_channel = 0;
630 1.1.2.3 bouyer asc->sc_channel.chan_ntargets = 8;
631 1.1.2.3 bouyer asc->sc_channel.chan_nluns = 8;
632 1.1.2.3 bouyer asc->sc_channel.chan_id = asc->sc_id;
633 1.1.2.2 bouyer
634 1.1.2.2 bouyer /*
635 1.1.2.2 bouyer * Now try to attach all the sub devices.
636 1.1.2.2 bouyer */
637 1.1.2.3 bouyer config_found(self, &asc->sc_channel, scsiprint);
638 1.1.2.2 bouyer }
639 1.1.2.2 bouyer
640 1.1.2.2 bouyer /*
641 1.1.2.2 bouyer * Start activity on a SCSI device.
642 1.1.2.2 bouyer * We maintain information on each device separately since devices can
643 1.1.2.2 bouyer * connect/disconnect during an operation.
644 1.1.2.2 bouyer */
645 1.1.2.4 bouyer void
646 1.1.2.3 bouyer asc_scsipi_request(chan, req, arg)
647 1.1.2.3 bouyer struct scsipi_channel *chan;
648 1.1.2.3 bouyer scsipi_adapter_req_t req;
649 1.1.2.3 bouyer void *arg;
650 1.1.2.2 bouyer {
651 1.1.2.3 bouyer struct scsipi_xfer *xs;
652 1.1.2.3 bouyer struct scsipi_periph *periph;
653 1.1.2.3 bouyer struct asc_softc *asc = (void *)chan->chan_adapter->adapt_dev;
654 1.1.2.3 bouyer int dontqueue, s;
655 1.1.2.3 bouyer
656 1.1.2.3 bouyer switch (req) {
657 1.1.2.3 bouyer case ADAPTER_REQ_RUN_XFER:
658 1.1.2.3 bouyer xs = arg;
659 1.1.2.3 bouyer periph = xs->xs_periph;
660 1.1.2.2 bouyer
661 1.1.2.3 bouyer dontqueue = xs->xs_control & XS_CTL_POLL;
662 1.1.2.2 bouyer
663 1.1.2.3 bouyer /*
664 1.1.2.3 bouyer * Flush caches for any data buffer
665 1.1.2.3 bouyer */
666 1.1.2.3 bouyer if(xs->datalen != 0) {
667 1.1.2.3 bouyer mips3_HitFlushDCache((vaddr_t)xs->data, xs->datalen);
668 1.1.2.3 bouyer }
669 1.1.2.3 bouyer /*
670 1.1.2.3 bouyer * The hack on the next few lines are to avoid buffers
671 1.1.2.3 bouyer * mapped to UADDR. Realloc to the kva uarea address.
672 1.1.2.3 bouyer */
673 1.1.2.3 bouyer if((u_int)(xs->data) >= UADDR) {
674 1.1.2.3 bouyer xs->data = ((u_int)(xs->data) & ~UADDR) + (u_char *)(curproc->p_addr);
675 1.1.2.2 bouyer }
676 1.1.2.2 bouyer
677 1.1.2.3 bouyer s = splbio();
678 1.1.2.3 bouyer asc->cmd[periph->periph_target] = xs;
679 1.1.2.2 bouyer
680 1.1.2.3 bouyer /*
681 1.1.2.3 bouyer * Going to launch.
682 1.1.2.3 bouyer * Make a local copy of the command and some pointers.
683 1.1.2.3 bouyer */
684 1.1.2.3 bouyer asc_startcmd(asc, periph->periph_target);
685 1.1.2.3 bouyer
686 1.1.2.3 bouyer /*
687 1.1.2.3 bouyer * If in startup, interrupts not usable yet.
688 1.1.2.3 bouyer */
689 1.1.2.3 bouyer if(dontqueue) {
690 1.1.2.3 bouyer asc_poll(asc,periph->periph_target);
691 1.1.2.3 bouyer }
692 1.1.2.3 bouyer splx(s);
693 1.1.2.3 bouyer return;
694 1.1.2.3 bouyer case ADAPTER_REQ_GROW_RESOURCES:
695 1.1.2.3 bouyer /* XXX Not supported. */
696 1.1.2.3 bouyer return;
697 1.1.2.3 bouyer case ADAPTER_REQ_SET_XFER_MODE:
698 1.1.2.3 bouyer /* XXX Not supported. */
699 1.1.2.3 bouyer return;
700 1.1.2.2 bouyer }
701 1.1.2.2 bouyer }
702 1.1.2.2 bouyer
703 1.1.2.3 bouyer void
704 1.1.2.2 bouyer asc_poll(asc, target)
705 1.1.2.2 bouyer struct asc_softc *asc;
706 1.1.2.2 bouyer int target;
707 1.1.2.2 bouyer {
708 1.1.2.2 bouyer struct scsipi_xfer *scsicmd = asc->cmd[target];
709 1.1.2.2 bouyer int count = scsicmd->timeout * 10;
710 1.1.2.2 bouyer
711 1.1.2.2 bouyer while(count) {
712 1.1.2.2 bouyer if(asc->regs->asc_status &ASC_CSR_INT) {
713 1.1.2.2 bouyer asc_intr(asc);
714 1.1.2.2 bouyer }
715 1.1.2.2 bouyer if(scsicmd->xs_status & XS_STS_DONE)
716 1.1.2.2 bouyer break;
717 1.1.2.2 bouyer DELAY(5);
718 1.1.2.2 bouyer count--;
719 1.1.2.2 bouyer }
720 1.1.2.2 bouyer if(count == 0) {
721 1.1.2.2 bouyer scsicmd->error = XS_TIMEOUT;
722 1.1.2.2 bouyer asc_end(asc, 0, 0, 0);
723 1.1.2.2 bouyer }
724 1.1.2.2 bouyer }
725 1.1.2.2 bouyer
726 1.1.2.2 bouyer static void
727 1.1.2.2 bouyer asc_reset(asc, regs)
728 1.1.2.2 bouyer asc_softc_t asc;
729 1.1.2.2 bouyer asc_regmap_t *regs;
730 1.1.2.2 bouyer {
731 1.1.2.2 bouyer
732 1.1.2.2 bouyer /*
733 1.1.2.2 bouyer * Reset chip and wait till done
734 1.1.2.2 bouyer */
735 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_RESET;
736 1.1.2.2 bouyer wbflush(); DELAY(25);
737 1.1.2.2 bouyer
738 1.1.2.2 bouyer /* spec says this is needed after reset */
739 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_NOP;
740 1.1.2.2 bouyer wbflush(); DELAY(25);
741 1.1.2.2 bouyer
742 1.1.2.2 bouyer /*
743 1.1.2.2 bouyer * Set up various chip parameters
744 1.1.2.2 bouyer */
745 1.1.2.2 bouyer regs->asc_ccf = asc->ccf;
746 1.1.2.2 bouyer wbflush(); DELAY(25);
747 1.1.2.2 bouyer regs->asc_sel_timo = asc->timeout_250;
748 1.1.2.2 bouyer /* restore our ID */
749 1.1.2.2 bouyer regs->asc_cnfg1 = asc->sc_id | ASC_CNFG1_P_CHECK;
750 1.1.2.2 bouyer /* include ASC_CNFG2_SCSI2 if you want to allow SCSI II commands */
751 1.1.2.2 bouyer regs->asc_cnfg2 = /* ASC_CNFG2_RFB | ASC_CNFG2_SCSI2 | */ ASC_CNFG2_EPL;
752 1.1.2.2 bouyer switch (cputype) {
753 1.1.2.2 bouyer case MAGNUM: /* XXX - NEC M403 */
754 1.1.2.2 bouyer /* only if EPL is FE (Feature Enable bit for 53CF94) */
755 1.1.2.2 bouyer regs->asc_cnfg3 = ASC_CNFG3_FCLK; /* clock 40MHz */
756 1.1.2.2 bouyer break;
757 1.1.2.2 bouyer default:
758 1.1.2.2 bouyer regs->asc_cnfg3 = 0;
759 1.1.2.2 bouyer break;
760 1.1.2.2 bouyer }
761 1.1.2.2 bouyer /* zero anything else */
762 1.1.2.2 bouyer ASC_TC_PUT(regs, 0, asc->is24bit);
763 1.1.2.2 bouyer regs->asc_syn_p = asc->min_period;
764 1.1.2.2 bouyer regs->asc_syn_o = 0; /* async for now */
765 1.1.2.2 bouyer wbflush();
766 1.1.2.2 bouyer }
767 1.1.2.2 bouyer
768 1.1.2.2 bouyer /*
769 1.1.2.2 bouyer * Start a SCSI command on a target.
770 1.1.2.2 bouyer */
771 1.1.2.2 bouyer static void
772 1.1.2.2 bouyer asc_startcmd(asc, target)
773 1.1.2.2 bouyer asc_softc_t asc;
774 1.1.2.2 bouyer int target;
775 1.1.2.2 bouyer {
776 1.1.2.2 bouyer asc_regmap_t *regs;
777 1.1.2.2 bouyer State *state;
778 1.1.2.2 bouyer struct scsipi_xfer *scsicmd;
779 1.1.2.2 bouyer int i, len;
780 1.1.2.2 bouyer
781 1.1.2.2 bouyer /*
782 1.1.2.2 bouyer * See if another target is currently selected on this SCSI bus.
783 1.1.2.2 bouyer */
784 1.1.2.2 bouyer if (asc->target >= 0)
785 1.1.2.2 bouyer return;
786 1.1.2.2 bouyer
787 1.1.2.2 bouyer regs = asc->regs;
788 1.1.2.2 bouyer
789 1.1.2.2 bouyer /*
790 1.1.2.2 bouyer * If a reselection is in progress, it is Ok to ignore it since
791 1.1.2.2 bouyer * the ASC will automatically cancel the command and flush
792 1.1.2.2 bouyer * the FIFO if the ASC is reselected before the command starts.
793 1.1.2.2 bouyer * If we try to use ASC_CMD_DISABLE_SEL, we can hang the system if
794 1.1.2.2 bouyer * a reselect occurs before starting the command.
795 1.1.2.2 bouyer */
796 1.1.2.2 bouyer
797 1.1.2.2 bouyer asc->state = ASC_STATE_BUSY;
798 1.1.2.2 bouyer asc->target = target;
799 1.1.2.2 bouyer
800 1.1.2.2 bouyer /* cache some pointers */
801 1.1.2.2 bouyer scsicmd = asc->cmd[target];
802 1.1.2.2 bouyer state = &asc->st[target];
803 1.1.2.2 bouyer
804 1.1.2.2 bouyer /*
805 1.1.2.2 bouyer * Init the chip and target state.
806 1.1.2.2 bouyer */
807 1.1.2.3 bouyer state->flags = state->flags & DID_SYNC;
808 1.1.2.2 bouyer state->script = (script_t *)0;
809 1.1.2.2 bouyer state->msg_out = SCSI_NO_OP;
810 1.1.2.2 bouyer
811 1.1.2.2 bouyer /*
812 1.1.2.2 bouyer * Set up for DMA of command output. Also need to flush cache.
813 1.1.2.2 bouyer */
814 1.1.2.3 bouyer bcopy(scsicmd->cmd, &state->cmd, scsicmd->cmdlen);
815 1.1.2.3 bouyer state->cmdlen = scsicmd->cmdlen;
816 1.1.2.3 bouyer state->buf = (vaddr_t)scsicmd->data;
817 1.1.2.3 bouyer state->buflen = scsicmd->datalen;
818 1.1.2.2 bouyer len = state->cmdlen;
819 1.1.2.2 bouyer state->dmalen = len;
820 1.1.2.2 bouyer
821 1.1.2.2 bouyer #ifdef DEBUG
822 1.1.2.2 bouyer if (asc_debug > 1) {
823 1.1.2.2 bouyer printf("asc_startcmd: %s target %d cmd %x len %d\n",
824 1.1.2.2 bouyer asc->sc_dev.dv_xname, target,
825 1.1.2.2 bouyer state->cmd.opcode, state->buflen);
826 1.1.2.2 bouyer }
827 1.1.2.2 bouyer #endif
828 1.1.2.2 bouyer
829 1.1.2.2 bouyer /* check for simple SCSI command with no data transfer */
830 1.1.2.4 bouyer if (scsicmd->xs_control & XS_CTL_DATA_OUT) {
831 1.1.2.2 bouyer asc->script = &asc_scripts[SCRIPT_DATA_OUT];
832 1.1.2.2 bouyer state->flags |= DMA_OUT;
833 1.1.2.2 bouyer }
834 1.1.2.2 bouyer else if (scsicmd->xs_control & XS_CTL_DATA_IN) {
835 1.1.2.2 bouyer asc->script = &asc_scripts[SCRIPT_DATA_IN];
836 1.1.2.2 bouyer state->flags |= DMA_IN;
837 1.1.2.2 bouyer }
838 1.1.2.2 bouyer else if (state->buflen == 0) {
839 1.1.2.2 bouyer /* check for sync negotiation */
840 1.1.2.2 bouyer if ((scsicmd->xs_status & /* SCSICMD_USE_SYNC */ 0) &&
841 1.1.2.2 bouyer !(state->flags & DID_SYNC)) {
842 1.1.2.2 bouyer asc->script = &asc_scripts[SCRIPT_TRY_SYNC];
843 1.1.2.2 bouyer state->flags |= TRY_SYNC;
844 1.1.2.2 bouyer } else
845 1.1.2.2 bouyer asc->script = &asc_scripts[SCRIPT_SIMPLE];
846 1.1.2.2 bouyer state->buf = (vaddr_t)0;
847 1.1.2.2 bouyer }
848 1.1.2.2 bouyer
849 1.1.2.2 bouyer #ifdef DEBUG
850 1.1.2.2 bouyer asc_debug_cmd = state->cmd.opcode;
851 1.1.2.2 bouyer if (state->cmd.opcode == SCSI_READ_EXT) {
852 1.1.2.2 bouyer asc_debug_bn = (state->cmd.bytes[1] << 24) |
853 1.1.2.2 bouyer (state->cmd.bytes[2] << 16) |
854 1.1.2.2 bouyer (state->cmd.bytes[3] << 8) |
855 1.1.2.2 bouyer state->cmd.bytes[4];
856 1.1.2.2 bouyer asc_debug_sz = (state->cmd.bytes[6] << 8) | state->cmd.bytes[7];
857 1.1.2.2 bouyer }
858 1.1.2.2 bouyer asc_logp->status = PACK(asc->sc_dev.dv_unit, 0, 0, asc_debug_cmd);
859 1.1.2.2 bouyer asc_logp->target = asc->target;
860 1.1.2.2 bouyer asc_logp->state = asc->script - asc_scripts;
861 1.1.2.2 bouyer asc_logp->msg = SCSI_DIS_REC_IDENTIFY;
862 1.1.2.2 bouyer asc_logp->resid = scsicmd->datalen;
863 1.1.2.2 bouyer if (++asc_logp >= &asc_log[NLOG])
864 1.1.2.2 bouyer asc_logp = asc_log;
865 1.1.2.2 bouyer #endif
866 1.1.2.2 bouyer
867 1.1.2.2 bouyer /* preload the FIFO with the message and command to be sent */
868 1.1.2.2 bouyer regs->asc_fifo = SCSI_DIS_REC_IDENTIFY |
869 1.1.2.3 bouyer (scsicmd->xs_periph->periph_lun & 0x07);
870 1.1.2.2 bouyer
871 1.1.2.2 bouyer for( i = 0; i < len; i++ ) {
872 1.1.2.2 bouyer regs->asc_fifo = ((caddr_t)&state->cmd)[i];
873 1.1.2.2 bouyer }
874 1.1.2.2 bouyer ASC_TC_PUT(regs, 0, asc->is24bit);
875 1.1.2.2 bouyer readback(regs->asc_cmd);
876 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_DMA;
877 1.1.2.2 bouyer readback(regs->asc_cmd);
878 1.1.2.2 bouyer
879 1.1.2.2 bouyer regs->asc_dbus_id = target;
880 1.1.2.2 bouyer readback(regs->asc_dbus_id);
881 1.1.2.2 bouyer regs->asc_syn_p = state->sync_period;
882 1.1.2.2 bouyer readback(regs->asc_syn_p);
883 1.1.2.2 bouyer regs->asc_syn_o = state->sync_offset;
884 1.1.2.2 bouyer readback(regs->asc_syn_o);
885 1.1.2.2 bouyer
886 1.1.2.2 bouyer /*XXX PEFO */
887 1.1.2.2 bouyer /* we are not using sync transfer now, need to check this if we will */
888 1.1.2.2 bouyer
889 1.1.2.2 bouyer if (state->flags & TRY_SYNC)
890 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_SEL_ATN_STOP;
891 1.1.2.2 bouyer else
892 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_SEL_ATN;
893 1.1.2.2 bouyer readback(regs->asc_cmd);
894 1.1.2.2 bouyer }
895 1.1.2.2 bouyer
896 1.1.2.2 bouyer /*
897 1.1.2.2 bouyer * Interrupt routine
898 1.1.2.2 bouyer * Take interrupts from the chip
899 1.1.2.2 bouyer *
900 1.1.2.2 bouyer * Implementation:
901 1.1.2.2 bouyer * Move along the current command's script if
902 1.1.2.2 bouyer * all is well, invoke error handler if not.
903 1.1.2.2 bouyer */
904 1.1.2.2 bouyer int
905 1.1.2.2 bouyer asc_intr(sc)
906 1.1.2.2 bouyer void *sc;
907 1.1.2.2 bouyer {
908 1.1.2.2 bouyer asc_softc_t asc = sc;
909 1.1.2.2 bouyer asc_regmap_t *regs = asc->regs;
910 1.1.2.2 bouyer State *state;
911 1.1.2.2 bouyer script_t *scpt;
912 1.1.2.2 bouyer int ss, ir, status;
913 1.1.2.2 bouyer
914 1.1.2.2 bouyer /* collect ephemeral information */
915 1.1.2.2 bouyer status = regs->asc_status;
916 1.1.2.2 bouyer ss = regs->asc_ss;
917 1.1.2.2 bouyer
918 1.1.2.2 bouyer if ((status & ASC_CSR_INT) == 0) /* Make shure it's a real interrupt */
919 1.1.2.2 bouyer return(0);
920 1.1.2.2 bouyer
921 1.1.2.2 bouyer ir = regs->asc_intr; /* this resets the previous two */
922 1.1.2.2 bouyer scpt = asc->script;
923 1.1.2.2 bouyer
924 1.1.2.2 bouyer #ifdef DEBUG
925 1.1.2.2 bouyer asc_logp->status = PACK(asc->sc_dev.dv_unit, status, ss, ir);
926 1.1.2.2 bouyer asc_logp->target = (asc->state == ASC_STATE_BUSY) ? asc->target : -1;
927 1.1.2.2 bouyer asc_logp->state = scpt - asc_scripts;
928 1.1.2.2 bouyer asc_logp->msg = -1;
929 1.1.2.2 bouyer asc_logp->resid = 0;
930 1.1.2.2 bouyer if (++asc_logp >= &asc_log[NLOG])
931 1.1.2.2 bouyer asc_logp = asc_log;
932 1.1.2.2 bouyer if (asc_debug > 2)
933 1.1.2.2 bouyer printf("asc_intr: status %x ss %x ir %x cond %d:%x\n",
934 1.1.2.2 bouyer status, ss, ir, scpt - asc_scripts, scpt->condition);
935 1.1.2.2 bouyer #endif
936 1.1.2.2 bouyer
937 1.1.2.2 bouyer /* check the expected state */
938 1.1.2.2 bouyer if (SCRIPT_MATCH(ir, status) == scpt->condition) {
939 1.1.2.2 bouyer /*
940 1.1.2.2 bouyer * Perform the appropriate operation, then proceed.
941 1.1.2.2 bouyer */
942 1.1.2.2 bouyer if ((*scpt->action)(asc, status, ss, ir)) {
943 1.1.2.2 bouyer regs->asc_cmd = scpt->command;
944 1.1.2.2 bouyer readback(regs->asc_cmd);
945 1.1.2.2 bouyer asc->script = scpt->next;
946 1.1.2.2 bouyer }
947 1.1.2.2 bouyer goto done;
948 1.1.2.2 bouyer }
949 1.1.2.2 bouyer
950 1.1.2.2 bouyer /*
951 1.1.2.2 bouyer * Check for parity error.
952 1.1.2.2 bouyer * Hardware will automatically set ATN
953 1.1.2.2 bouyer * to request the device for a MSG_OUT phase.
954 1.1.2.2 bouyer */
955 1.1.2.2 bouyer if (status & ASC_CSR_PE) {
956 1.1.2.2 bouyer printf("%s: SCSI device %d: incomming parity error seen\n",
957 1.1.2.2 bouyer asc->sc_dev.dv_xname, asc->target);
958 1.1.2.2 bouyer asc->st[asc->target].flags |= PARITY_ERR;
959 1.1.2.2 bouyer }
960 1.1.2.2 bouyer
961 1.1.2.2 bouyer /*
962 1.1.2.2 bouyer * Check for gross error.
963 1.1.2.2 bouyer * Probably a bug in a device driver.
964 1.1.2.2 bouyer */
965 1.1.2.2 bouyer if (status & ASC_CSR_GE) {
966 1.1.2.2 bouyer printf("%s: SCSI device %d: gross error\n",
967 1.1.2.2 bouyer asc->sc_dev.dv_xname, asc->target);
968 1.1.2.2 bouyer goto abort;
969 1.1.2.2 bouyer }
970 1.1.2.2 bouyer
971 1.1.2.2 bouyer /* check for message in or out */
972 1.1.2.2 bouyer if ((ir & ~ASC_INT_FC) == ASC_INT_BS) {
973 1.1.2.2 bouyer register int len, fifo;
974 1.1.2.2 bouyer
975 1.1.2.2 bouyer state = &asc->st[asc->target];
976 1.1.2.2 bouyer switch (ASC_PHASE(status)) {
977 1.1.2.2 bouyer case ASC_PHASE_DATAI:
978 1.1.2.2 bouyer case ASC_PHASE_DATAO:
979 1.1.2.2 bouyer ASC_TC_GET(regs, len);
980 1.1.2.2 bouyer fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
981 1.1.2.2 bouyer printf("asc_intr: data overrun: buflen %d dmalen %d tc %d fifo %d\n",
982 1.1.2.2 bouyer state->buflen, state->dmalen, len, fifo);
983 1.1.2.2 bouyer goto abort;
984 1.1.2.2 bouyer
985 1.1.2.2 bouyer case ASC_PHASE_MSG_IN:
986 1.1.2.2 bouyer break;
987 1.1.2.2 bouyer
988 1.1.2.2 bouyer case ASC_PHASE_MSG_OUT:
989 1.1.2.2 bouyer /*
990 1.1.2.2 bouyer * Check for parity error.
991 1.1.2.2 bouyer * Hardware will automatically set ATN
992 1.1.2.2 bouyer * to request the device for a MSG_OUT phase.
993 1.1.2.2 bouyer */
994 1.1.2.2 bouyer if (state->flags & PARITY_ERR) {
995 1.1.2.2 bouyer state->flags &= ~PARITY_ERR;
996 1.1.2.2 bouyer state->msg_out = SCSI_MESSAGE_PARITY_ERROR;
997 1.1.2.2 bouyer /* reset message in counter */
998 1.1.2.2 bouyer state->msglen = 0;
999 1.1.2.2 bouyer } else
1000 1.1.2.2 bouyer state->msg_out = SCSI_NO_OP;
1001 1.1.2.2 bouyer regs->asc_fifo = state->msg_out;
1002 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_XFER_INFO;
1003 1.1.2.2 bouyer readback(regs->asc_cmd);
1004 1.1.2.2 bouyer goto done;
1005 1.1.2.2 bouyer
1006 1.1.2.2 bouyer case ASC_PHASE_STATUS:
1007 1.1.2.2 bouyer /* probably an error in the SCSI command */
1008 1.1.2.2 bouyer asc->script = &asc_scripts[SCRIPT_GET_STATUS];
1009 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_I_COMPLETE;
1010 1.1.2.2 bouyer readback(regs->asc_cmd);
1011 1.1.2.2 bouyer goto done;
1012 1.1.2.2 bouyer
1013 1.1.2.2 bouyer default:
1014 1.1.2.2 bouyer goto abort;
1015 1.1.2.2 bouyer }
1016 1.1.2.2 bouyer
1017 1.1.2.2 bouyer if (state->script)
1018 1.1.2.2 bouyer goto abort;
1019 1.1.2.2 bouyer
1020 1.1.2.2 bouyer /*
1021 1.1.2.2 bouyer * OK, message coming in clean up whatever is going on.
1022 1.1.2.2 bouyer * Get number of bytes left to transfered from byte counter
1023 1.1.2.2 bouyer * counter decrements when data is trf on the SCSI bus
1024 1.1.2.2 bouyer */
1025 1.1.2.2 bouyer ASC_TC_GET(regs, len);
1026 1.1.2.2 bouyer fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1027 1.1.2.2 bouyer /* flush any data in the FIFO */
1028 1.1.2.2 bouyer if (fifo && !(state->flags & DMA_IN_PROGRESS)) {
1029 1.1.2.2 bouyer printf("asc_intr: fifo flush %d len %d fifo %x\n", fifo, len, regs->asc_fifo);
1030 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_FLUSH;
1031 1.1.2.2 bouyer readback(regs->asc_cmd);
1032 1.1.2.2 bouyer DELAY(2);
1033 1.1.2.2 bouyer }
1034 1.1.2.2 bouyer else if (fifo && state->flags & DMA_IN_PROGRESS) {
1035 1.1.2.2 bouyer if (state->flags & DMA_OUT) {
1036 1.1.2.2 bouyer len += fifo; /* Bytes dma'ed but not sent */
1037 1.1.2.2 bouyer }
1038 1.1.2.2 bouyer else if (state->flags & DMA_IN) {
1039 1.1.2.2 bouyer printf("asc_intr: IN: dmalen %d len %d fifo %d\n",
1040 1.1.2.2 bouyer state->dmalen, len, fifo); /* XXX */
1041 1.1.2.2 bouyer }
1042 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_FLUSH;
1043 1.1.2.2 bouyer readback(regs->asc_cmd);
1044 1.1.2.2 bouyer DELAY(2);
1045 1.1.2.2 bouyer }
1046 1.1.2.2 bouyer if (len && (state->flags & DMA_IN_PROGRESS)) {
1047 1.1.2.2 bouyer /* save number of bytes still to be sent or received */
1048 1.1.2.2 bouyer state->dmaresid = len;
1049 1.1.2.2 bouyer state->flags &= ~DMA_IN_PROGRESS;
1050 1.1.2.2 bouyer ASC_TC_PUT(regs, 0, asc->is24bit);
1051 1.1.2.2 bouyer #ifdef DEBUG
1052 1.1.2.2 bouyer if (asc_logp == asc_log)
1053 1.1.2.2 bouyer asc_log[NLOG - 1].resid = len;
1054 1.1.2.2 bouyer else
1055 1.1.2.2 bouyer asc_logp[-1].resid = len;
1056 1.1.2.2 bouyer #endif
1057 1.1.2.2 bouyer /* setup state to resume to */
1058 1.1.2.2 bouyer if (state->flags & DMA_IN) {
1059 1.1.2.2 bouyer /*
1060 1.1.2.2 bouyer * Since the ASC_CNFG3_SRB bit of the
1061 1.1.2.2 bouyer * cnfg3 register bit is not set,
1062 1.1.2.2 bouyer * we just transferred an extra byte.
1063 1.1.2.2 bouyer * Since we can't resume on an odd byte
1064 1.1.2.2 bouyer * boundary, we copy the valid data out
1065 1.1.2.2 bouyer * and resume DMA at the start address.
1066 1.1.2.2 bouyer */
1067 1.1.2.2 bouyer if (len & 1) {
1068 1.1.2.2 bouyer printf("asc_intr: msg in len %d (fifo %d)\n",
1069 1.1.2.2 bouyer len, fifo); /* XXX */
1070 1.1.2.2 bouyer len = state->dmalen - len;
1071 1.1.2.2 bouyer goto do_in;
1072 1.1.2.2 bouyer }
1073 1.1.2.2 bouyer state->script =
1074 1.1.2.2 bouyer &asc_scripts[SCRIPT_RESUME_DMA_IN];
1075 1.1.2.2 bouyer } else if (state->flags & DMA_OUT)
1076 1.1.2.2 bouyer state->script =
1077 1.1.2.2 bouyer &asc_scripts[SCRIPT_RESUME_DMA_OUT];
1078 1.1.2.2 bouyer else
1079 1.1.2.2 bouyer state->script = asc->script;
1080 1.1.2.2 bouyer } else if (state->flags & DMA_IN) {
1081 1.1.2.2 bouyer if (len) {
1082 1.1.2.2 bouyer #ifdef DEBUG
1083 1.1.2.2 bouyer printf("asc_intr: 1: bn %d len %d (fifo %d)\n",
1084 1.1.2.2 bouyer asc_debug_bn, len, fifo); /* XXX */
1085 1.1.2.2 bouyer #endif
1086 1.1.2.2 bouyer goto abort;
1087 1.1.2.2 bouyer }
1088 1.1.2.2 bouyer /* setup state to resume to */
1089 1.1.2.2 bouyer if (state->flags & DMA_IN_PROGRESS) {
1090 1.1.2.2 bouyer len = state->dmalen;
1091 1.1.2.2 bouyer state->flags &= ~DMA_IN_PROGRESS;
1092 1.1.2.2 bouyer do_in:
1093 1.1.2.2 bouyer DMA_END(asc->dma);
1094 1.1.2.2 bouyer state->buf += len;
1095 1.1.2.2 bouyer state->buflen -= len;
1096 1.1.2.2 bouyer }
1097 1.1.2.2 bouyer if (state->buflen)
1098 1.1.2.2 bouyer state->script =
1099 1.1.2.2 bouyer &asc_scripts[SCRIPT_RESUME_IN];
1100 1.1.2.2 bouyer else
1101 1.1.2.2 bouyer state->script =
1102 1.1.2.2 bouyer &asc_scripts[SCRIPT_RESUME_NO_DATA];
1103 1.1.2.2 bouyer } else if (state->flags & DMA_OUT) {
1104 1.1.2.2 bouyer if (len) {
1105 1.1.2.2 bouyer printf("asc_intr: 2: len %d (fifo %d)\n", len,
1106 1.1.2.2 bouyer fifo); /* XXX */
1107 1.1.2.2 bouyer /* XXX THEO */
1108 1.1.2.2 bouyer #if 1
1109 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_FLUSH;
1110 1.1.2.2 bouyer readback(regs->asc_cmd);
1111 1.1.2.2 bouyer DELAY(2);
1112 1.1.2.2 bouyer len = 0;
1113 1.1.2.2 bouyer #else
1114 1.1.2.2 bouyer goto abort;
1115 1.1.2.2 bouyer #endif
1116 1.1.2.2 bouyer }
1117 1.1.2.2 bouyer /*
1118 1.1.2.2 bouyer * If this is the last chunk, the next expected
1119 1.1.2.2 bouyer * state is to get status.
1120 1.1.2.2 bouyer */
1121 1.1.2.2 bouyer if (state->flags & DMA_IN_PROGRESS) {
1122 1.1.2.2 bouyer state->flags &= ~DMA_IN_PROGRESS;
1123 1.1.2.2 bouyer DMA_END(asc->dma);
1124 1.1.2.2 bouyer len = state->dmalen;
1125 1.1.2.2 bouyer state->buf += len;
1126 1.1.2.2 bouyer state->buflen -= len;
1127 1.1.2.2 bouyer }
1128 1.1.2.2 bouyer if (state->buflen)
1129 1.1.2.2 bouyer state->script =
1130 1.1.2.2 bouyer &asc_scripts[SCRIPT_RESUME_OUT];
1131 1.1.2.2 bouyer else
1132 1.1.2.2 bouyer state->script =
1133 1.1.2.2 bouyer &asc_scripts[SCRIPT_RESUME_NO_DATA];
1134 1.1.2.2 bouyer } else if (asc->script == &asc_scripts[SCRIPT_SIMPLE])
1135 1.1.2.2 bouyer state->script = &asc_scripts[SCRIPT_RESUME_NO_DATA];
1136 1.1.2.2 bouyer else
1137 1.1.2.2 bouyer state->script = asc->script;
1138 1.1.2.2 bouyer
1139 1.1.2.2 bouyer /* setup to receive a message */
1140 1.1.2.2 bouyer asc->script = &asc_scripts[SCRIPT_MSG_IN];
1141 1.1.2.2 bouyer state->msglen = 0;
1142 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_XFER_INFO;
1143 1.1.2.2 bouyer readback(regs->asc_cmd);
1144 1.1.2.2 bouyer goto done;
1145 1.1.2.2 bouyer }
1146 1.1.2.2 bouyer
1147 1.1.2.2 bouyer /* check for SCSI bus reset */
1148 1.1.2.2 bouyer if (ir & ASC_INT_RESET) {
1149 1.1.2.2 bouyer register int i;
1150 1.1.2.2 bouyer
1151 1.1.2.2 bouyer printf("%s: SCSI bus reset!!\n", asc->sc_dev.dv_xname);
1152 1.1.2.2 bouyer /* need to flush any pending commands */
1153 1.1.2.2 bouyer for (i = 0; i < ASC_NCMD; i++) {
1154 1.1.2.2 bouyer if (!asc->cmd[i])
1155 1.1.2.2 bouyer continue;
1156 1.1.2.2 bouyer asc->cmd[i]->error = XS_DRIVER_STUFFUP;
1157 1.1.2.2 bouyer asc_end(asc, 0, 0, 0);
1158 1.1.2.2 bouyer }
1159 1.1.2.2 bouyer /* rearbitrate synchronous offset */
1160 1.1.2.2 bouyer for (i = 0; i < ASC_NCMD; i++) {
1161 1.1.2.2 bouyer asc->st[i].sync_offset = 0;
1162 1.1.2.2 bouyer asc->st[i].flags = 0;
1163 1.1.2.2 bouyer }
1164 1.1.2.2 bouyer asc->target = -1;
1165 1.1.2.2 bouyer return(1);
1166 1.1.2.2 bouyer }
1167 1.1.2.2 bouyer
1168 1.1.2.2 bouyer /* check for command errors */
1169 1.1.2.2 bouyer if (ir & ASC_INT_ILL)
1170 1.1.2.2 bouyer goto abort;
1171 1.1.2.2 bouyer
1172 1.1.2.2 bouyer /* check for disconnect */
1173 1.1.2.2 bouyer if (ir & ASC_INT_DISC) {
1174 1.1.2.2 bouyer state = &asc->st[asc->target];
1175 1.1.2.2 bouyer switch (asc->script - asc_scripts) {
1176 1.1.2.2 bouyer case SCRIPT_DONE:
1177 1.1.2.2 bouyer case SCRIPT_DISCONNECT:
1178 1.1.2.2 bouyer /*
1179 1.1.2.2 bouyer * Disconnects can happen normally when the
1180 1.1.2.2 bouyer * command is complete with the phase being
1181 1.1.2.2 bouyer * either ASC_PHASE_DATAO or ASC_PHASE_MSG_IN.
1182 1.1.2.2 bouyer * The SCRIPT_MATCH() only checks for one phase
1183 1.1.2.2 bouyer * so we can wind up here.
1184 1.1.2.2 bouyer * Perform the appropriate operation, then proceed.
1185 1.1.2.2 bouyer */
1186 1.1.2.2 bouyer if ((*scpt->action)(asc, status, ss, ir)) {
1187 1.1.2.2 bouyer regs->asc_cmd = scpt->command;
1188 1.1.2.2 bouyer readback(regs->asc_cmd);
1189 1.1.2.2 bouyer asc->script = scpt->next;
1190 1.1.2.2 bouyer }
1191 1.1.2.2 bouyer goto done;
1192 1.1.2.2 bouyer
1193 1.1.2.2 bouyer case SCRIPT_TRY_SYNC:
1194 1.1.2.2 bouyer case SCRIPT_SIMPLE:
1195 1.1.2.2 bouyer case SCRIPT_DATA_IN:
1196 1.1.2.2 bouyer case SCRIPT_DATA_OUT: /* one of the starting scripts */
1197 1.1.2.2 bouyer if (ASC_SS(ss) == 0) {
1198 1.1.2.2 bouyer /* device did not respond */
1199 1.1.2.2 bouyer if (regs->asc_flags & ASC_FLAGS_FIFO_CNT) {
1200 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_FLUSH;
1201 1.1.2.2 bouyer readback(regs->asc_cmd);
1202 1.1.2.2 bouyer }
1203 1.1.2.2 bouyer asc->cmd[asc->target]->error = XS_DRIVER_STUFFUP;
1204 1.1.2.2 bouyer asc_end(asc, status, ss, ir);
1205 1.1.2.2 bouyer return(1);
1206 1.1.2.2 bouyer }
1207 1.1.2.2 bouyer /* FALLTHROUGH */
1208 1.1.2.2 bouyer
1209 1.1.2.2 bouyer default:
1210 1.1.2.2 bouyer printf("%s: SCSI device %d: unexpected disconnect\n",
1211 1.1.2.2 bouyer asc->sc_dev.dv_xname, asc->target);
1212 1.1.2.2 bouyer #ifdef DEBUG
1213 1.1.2.2 bouyer asc_DumpLog("asc_disc");
1214 1.1.2.2 bouyer #endif
1215 1.1.2.2 bouyer /*
1216 1.1.2.2 bouyer * On rare occasions my RZ24 does a disconnect during
1217 1.1.2.2 bouyer * data in phase and the following seems to keep it
1218 1.1.2.2 bouyer * happy.
1219 1.1.2.2 bouyer * XXX Should a scsi disk ever do this??
1220 1.1.2.2 bouyer */
1221 1.1.2.2 bouyer asc->script = &asc_scripts[SCRIPT_RESEL];
1222 1.1.2.2 bouyer asc->state = ASC_STATE_RESEL;
1223 1.1.2.2 bouyer state->flags |= DISCONN;
1224 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_ENABLE_SEL;
1225 1.1.2.2 bouyer readback(regs->asc_cmd);
1226 1.1.2.2 bouyer return(1);
1227 1.1.2.2 bouyer }
1228 1.1.2.2 bouyer }
1229 1.1.2.2 bouyer
1230 1.1.2.2 bouyer /* check for reselect */
1231 1.1.2.2 bouyer if (ir & ASC_INT_RESEL) {
1232 1.1.2.2 bouyer unsigned fifo, id, msg;
1233 1.1.2.2 bouyer
1234 1.1.2.2 bouyer fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1235 1.1.2.2 bouyer if (fifo < 2)
1236 1.1.2.2 bouyer goto abort;
1237 1.1.2.2 bouyer /* read unencoded SCSI ID and convert to binary */
1238 1.1.2.2 bouyer msg = regs->asc_fifo & asc->myidmask;
1239 1.1.2.2 bouyer for (id = 0; (msg & 1) == 0; id++)
1240 1.1.2.2 bouyer msg >>= 1;
1241 1.1.2.2 bouyer /* read identify message */
1242 1.1.2.2 bouyer msg = regs->asc_fifo;
1243 1.1.2.2 bouyer #ifdef DEBUG
1244 1.1.2.2 bouyer if (asc_logp == asc_log)
1245 1.1.2.2 bouyer asc_log[NLOG - 1].msg = msg;
1246 1.1.2.2 bouyer else
1247 1.1.2.2 bouyer asc_logp[-1].msg = msg;
1248 1.1.2.2 bouyer #endif
1249 1.1.2.2 bouyer asc->state = ASC_STATE_BUSY;
1250 1.1.2.2 bouyer asc->target = id;
1251 1.1.2.2 bouyer state = &asc->st[id];
1252 1.1.2.2 bouyer asc->script = state->script;
1253 1.1.2.2 bouyer state->script = (script_t *)0;
1254 1.1.2.2 bouyer if (!(state->flags & DISCONN))
1255 1.1.2.2 bouyer goto abort;
1256 1.1.2.2 bouyer state->flags &= ~DISCONN;
1257 1.1.2.2 bouyer regs->asc_syn_p = state->sync_period;
1258 1.1.2.2 bouyer regs->asc_syn_o = state->sync_offset;
1259 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_MSG_ACPT;
1260 1.1.2.2 bouyer readback(regs->asc_cmd);
1261 1.1.2.2 bouyer goto done;
1262 1.1.2.2 bouyer }
1263 1.1.2.2 bouyer
1264 1.1.2.2 bouyer /* check if we are being selected as a target */
1265 1.1.2.2 bouyer if (ir & (ASC_INT_SEL | ASC_INT_SEL_ATN))
1266 1.1.2.2 bouyer goto abort;
1267 1.1.2.2 bouyer
1268 1.1.2.2 bouyer /*
1269 1.1.2.2 bouyer * 'ir' must be just ASC_INT_FC.
1270 1.1.2.2 bouyer * This is normal if canceling an ASC_ENABLE_SEL.
1271 1.1.2.2 bouyer */
1272 1.1.2.2 bouyer
1273 1.1.2.2 bouyer done:
1274 1.1.2.2 bouyer wbflush();
1275 1.1.2.2 bouyer /*
1276 1.1.2.2 bouyer * If the next interrupt comes in immediatly the interrupt
1277 1.1.2.2 bouyer * dispatcher (which we are returning to) will catch it
1278 1.1.2.2 bouyer * before returning to the interrupted code.
1279 1.1.2.2 bouyer */
1280 1.1.2.2 bouyer return(1);
1281 1.1.2.2 bouyer
1282 1.1.2.2 bouyer abort:
1283 1.1.2.2 bouyer #ifdef DEBUG
1284 1.1.2.2 bouyer asc_DumpLog("asc_intr");
1285 1.1.2.2 bouyer #endif
1286 1.1.2.2 bouyer panic("asc_intr");
1287 1.1.2.2 bouyer return(1);
1288 1.1.2.2 bouyer }
1289 1.1.2.2 bouyer
1290 1.1.2.2 bouyer /*
1291 1.1.2.2 bouyer * All the many little things that the interrupt
1292 1.1.2.2 bouyer * routine might switch to.
1293 1.1.2.2 bouyer */
1294 1.1.2.2 bouyer
1295 1.1.2.2 bouyer /* ARGSUSED */
1296 1.1.2.2 bouyer static int
1297 1.1.2.2 bouyer script_nop(asc, status, ss, ir)
1298 1.1.2.2 bouyer asc_softc_t asc;
1299 1.1.2.2 bouyer int status, ss, ir;
1300 1.1.2.2 bouyer {
1301 1.1.2.2 bouyer return (1);
1302 1.1.2.2 bouyer }
1303 1.1.2.2 bouyer
1304 1.1.2.2 bouyer /* ARGSUSED */
1305 1.1.2.2 bouyer static int
1306 1.1.2.2 bouyer asc_get_status(asc, status, ss, ir)
1307 1.1.2.2 bouyer register asc_softc_t asc;
1308 1.1.2.2 bouyer register int status, ss, ir;
1309 1.1.2.2 bouyer {
1310 1.1.2.2 bouyer register asc_regmap_t *regs = asc->regs;
1311 1.1.2.2 bouyer register int data;
1312 1.1.2.2 bouyer
1313 1.1.2.2 bouyer /*
1314 1.1.2.2 bouyer * Get the last two bytes in the FIFO.
1315 1.1.2.2 bouyer */
1316 1.1.2.2 bouyer if ((data = regs->asc_flags & ASC_FLAGS_FIFO_CNT) != 2) {
1317 1.1.2.2 bouyer printf("asc_get_status: cmdreg %x, fifo cnt %d\n",
1318 1.1.2.2 bouyer regs->asc_cmd, data); /* XXX */
1319 1.1.2.2 bouyer #ifdef DEBUG
1320 1.1.2.2 bouyer asc_DumpLog("get_status"); /* XXX */
1321 1.1.2.2 bouyer #endif
1322 1.1.2.2 bouyer if (data < 2) {
1323 1.1.2.2 bouyer asc->regs->asc_cmd = ASC_CMD_MSG_ACPT;
1324 1.1.2.2 bouyer readback(asc->regs->asc_cmd);
1325 1.1.2.2 bouyer return (0);
1326 1.1.2.2 bouyer }
1327 1.1.2.2 bouyer do {
1328 1.1.2.2 bouyer data = regs->asc_fifo;
1329 1.1.2.2 bouyer } while ((regs->asc_flags & ASC_FLAGS_FIFO_CNT) > 2);
1330 1.1.2.2 bouyer }
1331 1.1.2.2 bouyer
1332 1.1.2.2 bouyer /* save the status byte */
1333 1.1.2.2 bouyer asc->st[asc->target].statusByte = data = regs->asc_fifo;
1334 1.1.2.2 bouyer #ifdef DEBUG
1335 1.1.2.2 bouyer if (asc_logp == asc_log)
1336 1.1.2.2 bouyer asc_log[NLOG - 1].msg = data;
1337 1.1.2.2 bouyer else
1338 1.1.2.2 bouyer asc_logp[-1].msg = data;
1339 1.1.2.2 bouyer #endif
1340 1.1.2.2 bouyer
1341 1.1.2.2 bouyer /* get the (presumed) command_complete message */
1342 1.1.2.2 bouyer if ((data = regs->asc_fifo) == SCSI_COMMAND_COMPLETE)
1343 1.1.2.2 bouyer return (1);
1344 1.1.2.2 bouyer
1345 1.1.2.2 bouyer #ifdef DEBUG
1346 1.1.2.2 bouyer printf("asc_get_status: status %x cmd %x\n",
1347 1.1.2.2 bouyer asc->st[asc->target].statusByte, data);
1348 1.1.2.2 bouyer asc_DumpLog("asc_get_status");
1349 1.1.2.2 bouyer #endif
1350 1.1.2.2 bouyer return (0);
1351 1.1.2.2 bouyer }
1352 1.1.2.2 bouyer
1353 1.1.2.2 bouyer /* ARGSUSED */
1354 1.1.2.2 bouyer static int
1355 1.1.2.2 bouyer asc_end(asc, status, ss, ir)
1356 1.1.2.2 bouyer asc_softc_t asc;
1357 1.1.2.2 bouyer int status, ss, ir;
1358 1.1.2.2 bouyer {
1359 1.1.2.2 bouyer struct scsipi_xfer *scsicmd;
1360 1.1.2.3 bouyer struct scsipi_periph *periph;
1361 1.1.2.2 bouyer State *state;
1362 1.1.2.2 bouyer int i, target;
1363 1.1.2.2 bouyer
1364 1.1.2.2 bouyer asc->state = ASC_STATE_IDLE;
1365 1.1.2.2 bouyer target = asc->target;
1366 1.1.2.2 bouyer asc->target = -1;
1367 1.1.2.2 bouyer scsicmd = asc->cmd[target];
1368 1.1.2.3 bouyer periph = scsicmd->xs_periph;
1369 1.1.2.2 bouyer asc->cmd[target] = (struct scsipi_xfer *)0;
1370 1.1.2.2 bouyer state = &asc->st[target];
1371 1.1.2.2 bouyer
1372 1.1.2.2 bouyer #ifdef DEBUG
1373 1.1.2.2 bouyer if (asc_debug > 1) {
1374 1.1.2.2 bouyer printf("asc_end: %s target %d cmd %x err %d resid %d\n",
1375 1.1.2.2 bouyer asc->sc_dev.dv_xname, target,
1376 1.1.2.2 bouyer state->cmd.opcode, scsicmd->error, state->buflen);
1377 1.1.2.2 bouyer }
1378 1.1.2.2 bouyer #endif
1379 1.1.2.2 bouyer #ifdef DIAGNOSTIC
1380 1.1.2.2 bouyer if (target < 0 || !scsicmd)
1381 1.1.2.2 bouyer panic("asc_end");
1382 1.1.2.2 bouyer #endif
1383 1.1.2.2 bouyer
1384 1.1.2.2 bouyer /* look for disconnected devices */
1385 1.1.2.2 bouyer for (i = 0; i < ASC_NCMD; i++) {
1386 1.1.2.2 bouyer if (!asc->cmd[i] || !(asc->st[i].flags & DISCONN))
1387 1.1.2.2 bouyer continue;
1388 1.1.2.2 bouyer asc->regs->asc_cmd = ASC_CMD_ENABLE_SEL;
1389 1.1.2.2 bouyer readback(asc->regs->asc_cmd);
1390 1.1.2.2 bouyer asc->state = ASC_STATE_RESEL;
1391 1.1.2.2 bouyer asc->script = &asc_scripts[SCRIPT_RESEL];
1392 1.1.2.2 bouyer break;
1393 1.1.2.2 bouyer }
1394 1.1.2.2 bouyer
1395 1.1.2.3 bouyer if(scsicmd->error == XS_NOERROR) {
1396 1.1.2.2 bouyer if((state->statusByte & ST_MASK) == SCSI_CHECK) {
1397 1.1.2.2 bouyer scsicmd->status = state->statusByte;
1398 1.1.2.3 bouyer scsicmd->error = XS_BUSY;
1399 1.1.2.2 bouyer }
1400 1.1.2.2 bouyer }
1401 1.1.2.2 bouyer
1402 1.1.2.3 bouyer scsicmd->resid = state->buflen;
1403 1.1.2.2 bouyer
1404 1.1.2.2 bouyer /*
1405 1.1.2.2 bouyer * Look for another device that is ready.
1406 1.1.2.2 bouyer * May want to keep last one started and increment for fairness
1407 1.1.2.2 bouyer * rather than always starting at zero.
1408 1.1.2.2 bouyer */
1409 1.1.2.2 bouyer for (i = 0; i < ASC_NCMD; i++) {
1410 1.1.2.2 bouyer /* don't restart a disconnected command */
1411 1.1.2.2 bouyer if (!asc->cmd[i] || (asc->st[i].flags & DISCONN))
1412 1.1.2.2 bouyer continue;
1413 1.1.2.2 bouyer asc_startcmd(asc, i);
1414 1.1.2.2 bouyer break;
1415 1.1.2.2 bouyer }
1416 1.1.2.2 bouyer
1417 1.1.2.2 bouyer /* signal device driver that the command is done */
1418 1.1.2.2 bouyer scsipi_done(scsicmd);
1419 1.1.2.2 bouyer
1420 1.1.2.2 bouyer return (0);
1421 1.1.2.2 bouyer }
1422 1.1.2.2 bouyer
1423 1.1.2.2 bouyer /* ARGSUSED */
1424 1.1.2.2 bouyer static int
1425 1.1.2.2 bouyer asc_dma_in(asc, status, ss, ir)
1426 1.1.2.2 bouyer register asc_softc_t asc;
1427 1.1.2.2 bouyer register int status, ss, ir;
1428 1.1.2.2 bouyer {
1429 1.1.2.2 bouyer register asc_regmap_t *regs = asc->regs;
1430 1.1.2.2 bouyer register State *state = &asc->st[asc->target];
1431 1.1.2.2 bouyer register int len;
1432 1.1.2.2 bouyer
1433 1.1.2.2 bouyer /* check for previous chunk in buffer */
1434 1.1.2.2 bouyer if (state->flags & DMA_IN_PROGRESS) {
1435 1.1.2.2 bouyer /*
1436 1.1.2.2 bouyer * Only count bytes that have been copied to memory.
1437 1.1.2.2 bouyer * There may be some bytes in the FIFO if synchonous transfers
1438 1.1.2.2 bouyer * are in progress.
1439 1.1.2.2 bouyer */
1440 1.1.2.2 bouyer DMA_END(asc->dma);
1441 1.1.2.2 bouyer ASC_TC_GET(regs, len);
1442 1.1.2.2 bouyer len = state->dmalen - len;
1443 1.1.2.2 bouyer state->buf += len;
1444 1.1.2.2 bouyer state->buflen -= len;
1445 1.1.2.2 bouyer }
1446 1.1.2.2 bouyer
1447 1.1.2.2 bouyer /* setup to start reading the next chunk */
1448 1.1.2.2 bouyer len = state->buflen;
1449 1.1.2.2 bouyer #ifdef DEBUG
1450 1.1.2.2 bouyer if (asc_logp == asc_log)
1451 1.1.2.2 bouyer asc_log[NLOG - 1].resid = len;
1452 1.1.2.2 bouyer else
1453 1.1.2.2 bouyer asc_logp[-1].resid = len;
1454 1.1.2.2 bouyer #endif
1455 1.1.2.2 bouyer if (len > state->dmaBufSize)
1456 1.1.2.2 bouyer len = state->dmaBufSize;
1457 1.1.2.2 bouyer state->dmalen = len;
1458 1.1.2.2 bouyer DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_FROM_DEV);
1459 1.1.2.2 bouyer ASC_TC_PUT(regs, len, asc->is24bit);
1460 1.1.2.2 bouyer #ifdef DEBUG
1461 1.1.2.2 bouyer if (asc_debug > 2)
1462 1.1.2.2 bouyer printf("asc_dma_in: buflen %d, len %d\n", state->buflen, len);
1463 1.1.2.2 bouyer #endif
1464 1.1.2.2 bouyer
1465 1.1.2.2 bouyer /* check for next chunk */
1466 1.1.2.2 bouyer state->flags |= DMA_IN_PROGRESS;
1467 1.1.2.2 bouyer if (len != state->buflen) {
1468 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1469 1.1.2.2 bouyer readback(regs->asc_cmd);
1470 1.1.2.2 bouyer asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
1471 1.1.2.2 bouyer return (0);
1472 1.1.2.2 bouyer }
1473 1.1.2.2 bouyer return (1);
1474 1.1.2.2 bouyer }
1475 1.1.2.2 bouyer
1476 1.1.2.2 bouyer /* ARGSUSED */
1477 1.1.2.2 bouyer static int
1478 1.1.2.2 bouyer asc_last_dma_in(asc, status, ss, ir)
1479 1.1.2.2 bouyer register asc_softc_t asc;
1480 1.1.2.2 bouyer register int status, ss, ir;
1481 1.1.2.2 bouyer {
1482 1.1.2.2 bouyer register asc_regmap_t *regs = asc->regs;
1483 1.1.2.2 bouyer register State *state = &asc->st[asc->target];
1484 1.1.2.2 bouyer register int len, fifo;
1485 1.1.2.2 bouyer
1486 1.1.2.2 bouyer DMA_END(asc->dma);
1487 1.1.2.2 bouyer ASC_TC_GET(regs, len);
1488 1.1.2.2 bouyer fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1489 1.1.2.2 bouyer #ifdef DEBUG
1490 1.1.2.2 bouyer if (asc_debug > 2)
1491 1.1.2.2 bouyer printf("asc_last_dma_in: buflen %d dmalen %d tc %d fifo %d\n",
1492 1.1.2.2 bouyer state->buflen, state->dmalen, len, fifo);
1493 1.1.2.2 bouyer #endif
1494 1.1.2.2 bouyer if (fifo) {
1495 1.1.2.2 bouyer /* device must be trying to send more than we expect */
1496 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_FLUSH;
1497 1.1.2.2 bouyer readback(regs->asc_cmd);
1498 1.1.2.2 bouyer }
1499 1.1.2.2 bouyer state->flags &= ~DMA_IN_PROGRESS;
1500 1.1.2.2 bouyer len = state->dmalen - len;
1501 1.1.2.2 bouyer state->buflen -= len;
1502 1.1.2.2 bouyer
1503 1.1.2.2 bouyer return (1);
1504 1.1.2.2 bouyer }
1505 1.1.2.2 bouyer
1506 1.1.2.2 bouyer /* ARGSUSED */
1507 1.1.2.2 bouyer static int
1508 1.1.2.2 bouyer asc_resume_in(asc, status, ss, ir)
1509 1.1.2.2 bouyer register asc_softc_t asc;
1510 1.1.2.2 bouyer register int status, ss, ir;
1511 1.1.2.2 bouyer {
1512 1.1.2.2 bouyer register asc_regmap_t *regs = asc->regs;
1513 1.1.2.2 bouyer register State *state = &asc->st[asc->target];
1514 1.1.2.2 bouyer register int len;
1515 1.1.2.2 bouyer
1516 1.1.2.2 bouyer /* setup to start reading the next chunk */
1517 1.1.2.2 bouyer len = state->buflen;
1518 1.1.2.2 bouyer #ifdef DEBUG
1519 1.1.2.2 bouyer if (asc_logp == asc_log)
1520 1.1.2.2 bouyer asc_log[NLOG - 1].resid = len;
1521 1.1.2.2 bouyer else
1522 1.1.2.2 bouyer asc_logp[-1].resid = len;
1523 1.1.2.2 bouyer #endif
1524 1.1.2.2 bouyer if (len > state->dmaBufSize)
1525 1.1.2.2 bouyer len = state->dmaBufSize;
1526 1.1.2.2 bouyer state->dmalen = len;
1527 1.1.2.2 bouyer #ifdef DEBUG
1528 1.1.2.2 bouyer if (asc_logp == asc_log)
1529 1.1.2.2 bouyer asc_log[NLOG - 1].resid = len;
1530 1.1.2.2 bouyer else
1531 1.1.2.2 bouyer asc_logp[-1].resid = len;
1532 1.1.2.2 bouyer #endif
1533 1.1.2.2 bouyer DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_FROM_DEV);
1534 1.1.2.2 bouyer ASC_TC_PUT(regs, len, asc->is24bit);
1535 1.1.2.2 bouyer #ifdef DEBUG
1536 1.1.2.2 bouyer if (asc_debug > 2)
1537 1.1.2.2 bouyer printf("asc_resume_in: buflen %d, len %d\n", state->buflen,
1538 1.1.2.2 bouyer len);
1539 1.1.2.2 bouyer #endif
1540 1.1.2.2 bouyer
1541 1.1.2.2 bouyer /* check for next chunk */
1542 1.1.2.2 bouyer state->flags |= DMA_IN_PROGRESS;
1543 1.1.2.2 bouyer if (len != state->buflen) {
1544 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1545 1.1.2.2 bouyer readback(regs->asc_cmd);
1546 1.1.2.2 bouyer asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
1547 1.1.2.2 bouyer return (0);
1548 1.1.2.2 bouyer }
1549 1.1.2.2 bouyer return (1);
1550 1.1.2.2 bouyer }
1551 1.1.2.2 bouyer
1552 1.1.2.2 bouyer /* ARGSUSED */
1553 1.1.2.2 bouyer static int
1554 1.1.2.2 bouyer asc_resume_dma_in(asc, status, ss, ir)
1555 1.1.2.2 bouyer register asc_softc_t asc;
1556 1.1.2.2 bouyer register int status, ss, ir;
1557 1.1.2.2 bouyer {
1558 1.1.2.2 bouyer register asc_regmap_t *regs = asc->regs;
1559 1.1.2.2 bouyer register State *state = &asc->st[asc->target];
1560 1.1.2.2 bouyer register int len, off;
1561 1.1.2.2 bouyer
1562 1.1.2.2 bouyer /* setup to finish reading the current chunk */
1563 1.1.2.2 bouyer len = state->dmaresid;
1564 1.1.2.2 bouyer off = state->dmalen - len;
1565 1.1.2.2 bouyer if ((off & 1) && state->sync_offset) {
1566 1.1.2.2 bouyer printf("asc_resume_dma_in: odd xfer dmalen %d len %d off %d\n",
1567 1.1.2.2 bouyer state->dmalen, len, off); /* XXX */
1568 1.1.2.2 bouyer regs->asc_res_fifo = ((u_char *)state->buf)[off];
1569 1.1.2.2 bouyer /*XXX Need to flush cache ? */
1570 1.1.2.2 bouyer }
1571 1.1.2.2 bouyer DMA_START(asc->dma, (caddr_t)state->buf + off, len, DMA_FROM_DEV);
1572 1.1.2.2 bouyer ASC_TC_PUT(regs, len, asc->is24bit);
1573 1.1.2.2 bouyer #ifdef DEBUG
1574 1.1.2.2 bouyer if (asc_debug > 2)
1575 1.1.2.2 bouyer printf("asc_resume_dma_in: buflen %d dmalen %d len %d off %d\n",
1576 1.1.2.2 bouyer state->dmalen, state->buflen, len, off);
1577 1.1.2.2 bouyer #endif
1578 1.1.2.2 bouyer
1579 1.1.2.2 bouyer /* check for next chunk */
1580 1.1.2.2 bouyer state->flags |= DMA_IN_PROGRESS;
1581 1.1.2.2 bouyer if (state->dmalen != state->buflen) {
1582 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1583 1.1.2.2 bouyer readback(regs->asc_cmd);
1584 1.1.2.2 bouyer asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
1585 1.1.2.2 bouyer return (0);
1586 1.1.2.2 bouyer }
1587 1.1.2.2 bouyer return (1);
1588 1.1.2.2 bouyer }
1589 1.1.2.2 bouyer
1590 1.1.2.2 bouyer /* ARGSUSED */
1591 1.1.2.2 bouyer static int
1592 1.1.2.2 bouyer asc_dma_out(asc, status, ss, ir)
1593 1.1.2.2 bouyer register asc_softc_t asc;
1594 1.1.2.2 bouyer register int status, ss, ir;
1595 1.1.2.2 bouyer {
1596 1.1.2.2 bouyer register asc_regmap_t *regs = asc->regs;
1597 1.1.2.2 bouyer register State *state = &asc->st[asc->target];
1598 1.1.2.2 bouyer register int len, fifo;
1599 1.1.2.2 bouyer
1600 1.1.2.2 bouyer if (state->flags & DMA_IN_PROGRESS) {
1601 1.1.2.2 bouyer /* check to be sure previous chunk was finished */
1602 1.1.2.2 bouyer ASC_TC_GET(regs, len);
1603 1.1.2.2 bouyer fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1604 1.1.2.2 bouyer if (len || fifo)
1605 1.1.2.2 bouyer printf("asc_dma_out: buflen %d dmalen %d tc %d fifo %d\n",
1606 1.1.2.2 bouyer state->buflen, state->dmalen, len, fifo); /* XXX */
1607 1.1.2.2 bouyer len += fifo;
1608 1.1.2.2 bouyer len = state->dmalen - len;
1609 1.1.2.2 bouyer state->buf += len;
1610 1.1.2.2 bouyer state->buflen -= len;
1611 1.1.2.2 bouyer }
1612 1.1.2.2 bouyer
1613 1.1.2.2 bouyer /* setup for this chunk */
1614 1.1.2.2 bouyer len = state->buflen;
1615 1.1.2.2 bouyer #ifdef DEBUG
1616 1.1.2.2 bouyer if (asc_logp == asc_log)
1617 1.1.2.2 bouyer asc_log[NLOG - 1].resid = len;
1618 1.1.2.2 bouyer else
1619 1.1.2.2 bouyer asc_logp[-1].resid = len;
1620 1.1.2.2 bouyer #endif
1621 1.1.2.2 bouyer if (len > state->dmaBufSize)
1622 1.1.2.2 bouyer len = state->dmaBufSize;
1623 1.1.2.2 bouyer state->dmalen = len;
1624 1.1.2.2 bouyer DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_TO_DEV);
1625 1.1.2.2 bouyer ASC_TC_PUT(regs, len, asc->is24bit);
1626 1.1.2.2 bouyer #ifdef DEBUG
1627 1.1.2.2 bouyer if (asc_debug > 2)
1628 1.1.2.2 bouyer printf("asc_dma_out: buflen %d, len %d\n", state->buflen, len);
1629 1.1.2.2 bouyer #endif
1630 1.1.2.2 bouyer
1631 1.1.2.2 bouyer /* check for next chunk */
1632 1.1.2.2 bouyer state->flags |= DMA_IN_PROGRESS;
1633 1.1.2.2 bouyer if (len != state->buflen) {
1634 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1635 1.1.2.2 bouyer readback(regs->asc_cmd);
1636 1.1.2.2 bouyer asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
1637 1.1.2.2 bouyer return (0);
1638 1.1.2.2 bouyer }
1639 1.1.2.2 bouyer return (1);
1640 1.1.2.2 bouyer }
1641 1.1.2.2 bouyer
1642 1.1.2.2 bouyer /* ARGSUSED */
1643 1.1.2.2 bouyer static int
1644 1.1.2.2 bouyer asc_last_dma_out(asc, status, ss, ir)
1645 1.1.2.2 bouyer register asc_softc_t asc;
1646 1.1.2.2 bouyer register int status, ss, ir;
1647 1.1.2.2 bouyer {
1648 1.1.2.2 bouyer register asc_regmap_t *regs = asc->regs;
1649 1.1.2.2 bouyer register State *state = &asc->st[asc->target];
1650 1.1.2.2 bouyer register int len, fifo;
1651 1.1.2.2 bouyer
1652 1.1.2.2 bouyer ASC_TC_GET(regs, len);
1653 1.1.2.2 bouyer fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1654 1.1.2.2 bouyer #ifdef DEBUG
1655 1.1.2.2 bouyer if (asc_debug > 2)
1656 1.1.2.2 bouyer printf("asc_last_dma_out: buflen %d dmalen %d tc %d fifo %d\n",
1657 1.1.2.2 bouyer state->buflen, state->dmalen, len, fifo);
1658 1.1.2.2 bouyer #endif
1659 1.1.2.2 bouyer if (fifo) {
1660 1.1.2.2 bouyer len += fifo;
1661 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_FLUSH;
1662 1.1.2.2 bouyer readback(regs->asc_cmd);
1663 1.1.2.2 bouyer }
1664 1.1.2.2 bouyer state->flags &= ~DMA_IN_PROGRESS;
1665 1.1.2.2 bouyer len = state->dmalen - len;
1666 1.1.2.2 bouyer state->buflen -= len;
1667 1.1.2.2 bouyer return (1);
1668 1.1.2.2 bouyer }
1669 1.1.2.2 bouyer
1670 1.1.2.2 bouyer /* ARGSUSED */
1671 1.1.2.2 bouyer static int
1672 1.1.2.2 bouyer asc_resume_out(asc, status, ss, ir)
1673 1.1.2.2 bouyer register asc_softc_t asc;
1674 1.1.2.2 bouyer register int status, ss, ir;
1675 1.1.2.2 bouyer {
1676 1.1.2.2 bouyer register asc_regmap_t *regs = asc->regs;
1677 1.1.2.2 bouyer register State *state = &asc->st[asc->target];
1678 1.1.2.2 bouyer register int len;
1679 1.1.2.2 bouyer
1680 1.1.2.2 bouyer /* setup for this chunk */
1681 1.1.2.2 bouyer len = state->buflen;
1682 1.1.2.2 bouyer #ifdef DEBUG
1683 1.1.2.2 bouyer if (asc_logp == asc_log)
1684 1.1.2.2 bouyer asc_log[NLOG - 1].resid = len;
1685 1.1.2.2 bouyer else
1686 1.1.2.2 bouyer asc_logp[-1].resid = len;
1687 1.1.2.2 bouyer #endif
1688 1.1.2.2 bouyer if (len > state->dmaBufSize)
1689 1.1.2.2 bouyer len = state->dmaBufSize;
1690 1.1.2.2 bouyer state->dmalen = len;
1691 1.1.2.2 bouyer #ifdef DEBUG
1692 1.1.2.2 bouyer if (asc_logp == asc_log)
1693 1.1.2.2 bouyer asc_log[NLOG - 1].resid = len;
1694 1.1.2.2 bouyer else
1695 1.1.2.2 bouyer asc_logp[-1].resid = len;
1696 1.1.2.2 bouyer #endif
1697 1.1.2.2 bouyer DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_TO_DEV);
1698 1.1.2.2 bouyer ASC_TC_PUT(regs, len, asc->is24bit);
1699 1.1.2.2 bouyer #ifdef DEBUG
1700 1.1.2.2 bouyer if (asc_debug > 2)
1701 1.1.2.2 bouyer printf("asc_resume_out: buflen %d, len %d\n", state->buflen,
1702 1.1.2.2 bouyer len);
1703 1.1.2.2 bouyer #endif
1704 1.1.2.2 bouyer
1705 1.1.2.2 bouyer /* check for next chunk */
1706 1.1.2.2 bouyer state->flags |= DMA_IN_PROGRESS;
1707 1.1.2.2 bouyer if (len != state->buflen) {
1708 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1709 1.1.2.2 bouyer readback(regs->asc_cmd);
1710 1.1.2.2 bouyer asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
1711 1.1.2.2 bouyer return (0);
1712 1.1.2.2 bouyer }
1713 1.1.2.2 bouyer return (1);
1714 1.1.2.2 bouyer }
1715 1.1.2.2 bouyer
1716 1.1.2.2 bouyer /* ARGSUSED */
1717 1.1.2.2 bouyer static int
1718 1.1.2.2 bouyer asc_resume_dma_out(asc, status, ss, ir)
1719 1.1.2.2 bouyer register asc_softc_t asc;
1720 1.1.2.2 bouyer register int status, ss, ir;
1721 1.1.2.2 bouyer {
1722 1.1.2.2 bouyer register asc_regmap_t *regs = asc->regs;
1723 1.1.2.2 bouyer register State *state = &asc->st[asc->target];
1724 1.1.2.2 bouyer register int len, off;
1725 1.1.2.2 bouyer
1726 1.1.2.2 bouyer /* setup to finish writing this chunk */
1727 1.1.2.2 bouyer len = state->dmaresid;
1728 1.1.2.2 bouyer off = state->dmalen - len;
1729 1.1.2.2 bouyer if (off & 1) {
1730 1.1.2.2 bouyer printf("asc_resume_dma_out: odd xfer dmalen %d len %d off %d\n",
1731 1.1.2.2 bouyer state->dmalen, len, off); /* XXX */
1732 1.1.2.2 bouyer regs->asc_fifo = ((u_char *)state->buf)[off];
1733 1.1.2.2 bouyer /*XXX Need to flush Cache ? */
1734 1.1.2.2 bouyer off++;
1735 1.1.2.2 bouyer len--;
1736 1.1.2.2 bouyer }
1737 1.1.2.2 bouyer DMA_START(asc->dma, (caddr_t)state->buf + off, len, DMA_TO_DEV);
1738 1.1.2.2 bouyer ASC_TC_PUT(regs, len, asc->is24bit);
1739 1.1.2.2 bouyer #ifdef DEBUG
1740 1.1.2.2 bouyer if (asc_debug > 2)
1741 1.1.2.2 bouyer printf("asc_resume_dma_out: buflen %d dmalen %d len %d off %d\n",
1742 1.1.2.2 bouyer state->dmalen, state->buflen, len, off);
1743 1.1.2.2 bouyer #endif
1744 1.1.2.2 bouyer
1745 1.1.2.2 bouyer /* check for next chunk */
1746 1.1.2.2 bouyer state->flags |= DMA_IN_PROGRESS;
1747 1.1.2.2 bouyer if (state->dmalen != state->buflen) {
1748 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1749 1.1.2.2 bouyer readback(regs->asc_cmd);
1750 1.1.2.2 bouyer asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
1751 1.1.2.2 bouyer return (0);
1752 1.1.2.2 bouyer }
1753 1.1.2.2 bouyer return (1);
1754 1.1.2.2 bouyer }
1755 1.1.2.2 bouyer
1756 1.1.2.2 bouyer /* ARGSUSED */
1757 1.1.2.2 bouyer static int
1758 1.1.2.2 bouyer asc_sendsync(asc, status, ss, ir)
1759 1.1.2.2 bouyer register asc_softc_t asc;
1760 1.1.2.2 bouyer register int status, ss, ir;
1761 1.1.2.2 bouyer {
1762 1.1.2.2 bouyer register asc_regmap_t *regs = asc->regs;
1763 1.1.2.2 bouyer register State *state = &asc->st[asc->target];
1764 1.1.2.2 bouyer
1765 1.1.2.2 bouyer /* send the extended synchronous negotiation message */
1766 1.1.2.2 bouyer regs->asc_fifo = SCSI_EXTENDED_MSG;
1767 1.1.2.2 bouyer wbflush();
1768 1.1.2.2 bouyer regs->asc_fifo = 3;
1769 1.1.2.2 bouyer wbflush();
1770 1.1.2.2 bouyer regs->asc_fifo = SCSI_SYNCHRONOUS_XFER;
1771 1.1.2.2 bouyer wbflush();
1772 1.1.2.2 bouyer regs->asc_fifo = SCSI_MIN_PERIOD;
1773 1.1.2.2 bouyer wbflush();
1774 1.1.2.2 bouyer regs->asc_fifo = ASC_MAX_OFFSET;
1775 1.1.2.2 bouyer /* state to resume after we see the sync reply message */
1776 1.1.2.2 bouyer state->script = asc->script + 2;
1777 1.1.2.2 bouyer state->msglen = 0;
1778 1.1.2.2 bouyer return (1);
1779 1.1.2.2 bouyer }
1780 1.1.2.2 bouyer
1781 1.1.2.2 bouyer /* ARGSUSED */
1782 1.1.2.2 bouyer static int
1783 1.1.2.2 bouyer asc_replysync(asc, status, ss, ir)
1784 1.1.2.2 bouyer register asc_softc_t asc;
1785 1.1.2.2 bouyer register int status, ss, ir;
1786 1.1.2.2 bouyer {
1787 1.1.2.2 bouyer register asc_regmap_t *regs = asc->regs;
1788 1.1.2.2 bouyer register State *state = &asc->st[asc->target];
1789 1.1.2.2 bouyer
1790 1.1.2.2 bouyer #ifdef DEBUG
1791 1.1.2.2 bouyer if (asc_debug > 2)
1792 1.1.2.2 bouyer printf("asc_replysync: %x %x\n",
1793 1.1.2.2 bouyer asc_to_scsi_period[state->sync_period] * asc->tb_ticks,
1794 1.1.2.2 bouyer state->sync_offset);
1795 1.1.2.2 bouyer #endif
1796 1.1.2.2 bouyer /* send synchronous transfer in response to a request */
1797 1.1.2.2 bouyer regs->asc_fifo = SCSI_EXTENDED_MSG;
1798 1.1.2.2 bouyer wbflush();
1799 1.1.2.2 bouyer regs->asc_fifo = 3;
1800 1.1.2.2 bouyer wbflush();
1801 1.1.2.2 bouyer regs->asc_fifo = SCSI_SYNCHRONOUS_XFER;
1802 1.1.2.2 bouyer wbflush();
1803 1.1.2.2 bouyer regs->asc_fifo = asc_to_scsi_period[state->sync_period] * asc->tb_ticks;
1804 1.1.2.2 bouyer wbflush();
1805 1.1.2.2 bouyer regs->asc_fifo = state->sync_offset;
1806 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_XFER_INFO;
1807 1.1.2.2 bouyer readback(regs->asc_cmd);
1808 1.1.2.2 bouyer
1809 1.1.2.2 bouyer /* return to the appropriate script */
1810 1.1.2.2 bouyer if (!state->script) {
1811 1.1.2.2 bouyer #ifdef DEBUG
1812 1.1.2.2 bouyer asc_DumpLog("asc_replsync");
1813 1.1.2.2 bouyer #endif
1814 1.1.2.2 bouyer panic("asc_replysync");
1815 1.1.2.2 bouyer }
1816 1.1.2.2 bouyer asc->script = state->script;
1817 1.1.2.2 bouyer state->script = (script_t *)0;
1818 1.1.2.2 bouyer return (0);
1819 1.1.2.2 bouyer }
1820 1.1.2.2 bouyer
1821 1.1.2.2 bouyer /* ARGSUSED */
1822 1.1.2.2 bouyer static int
1823 1.1.2.2 bouyer asc_msg_in(asc, status, ss, ir)
1824 1.1.2.2 bouyer register asc_softc_t asc;
1825 1.1.2.2 bouyer register int status, ss, ir;
1826 1.1.2.2 bouyer {
1827 1.1.2.2 bouyer register asc_regmap_t *regs = asc->regs;
1828 1.1.2.2 bouyer register State *state = &asc->st[asc->target];
1829 1.1.2.2 bouyer register int msg;
1830 1.1.2.2 bouyer int i;
1831 1.1.2.2 bouyer
1832 1.1.2.2 bouyer /* read one message byte */
1833 1.1.2.2 bouyer msg = regs->asc_fifo;
1834 1.1.2.2 bouyer #ifdef DEBUG
1835 1.1.2.2 bouyer if (asc_logp == asc_log)
1836 1.1.2.2 bouyer asc_log[NLOG - 1].msg = msg;
1837 1.1.2.2 bouyer else
1838 1.1.2.2 bouyer asc_logp[-1].msg = msg;
1839 1.1.2.2 bouyer #endif
1840 1.1.2.2 bouyer
1841 1.1.2.2 bouyer /* check for multi-byte message */
1842 1.1.2.2 bouyer if (state->msglen != 0) {
1843 1.1.2.2 bouyer /* first byte is the message length */
1844 1.1.2.2 bouyer if (state->msglen < 0) {
1845 1.1.2.2 bouyer state->msglen = msg;
1846 1.1.2.2 bouyer return (1);
1847 1.1.2.2 bouyer }
1848 1.1.2.2 bouyer if (state->msgcnt >= state->msglen)
1849 1.1.2.2 bouyer goto abort;
1850 1.1.2.2 bouyer state->msg_in[state->msgcnt++] = msg;
1851 1.1.2.2 bouyer
1852 1.1.2.2 bouyer /* did we just read the last byte of the message? */
1853 1.1.2.2 bouyer if (state->msgcnt != state->msglen)
1854 1.1.2.2 bouyer return (1);
1855 1.1.2.2 bouyer
1856 1.1.2.2 bouyer /* process an extended message */
1857 1.1.2.2 bouyer #ifdef DEBUG
1858 1.1.2.2 bouyer if (asc_debug > 2)
1859 1.1.2.2 bouyer printf("asc_msg_in: msg %x %x %x\n",
1860 1.1.2.2 bouyer state->msg_in[0],
1861 1.1.2.2 bouyer state->msg_in[1],
1862 1.1.2.2 bouyer state->msg_in[2]);
1863 1.1.2.2 bouyer #endif
1864 1.1.2.2 bouyer switch (state->msg_in[0]) {
1865 1.1.2.2 bouyer case SCSI_SYNCHRONOUS_XFER:
1866 1.1.2.2 bouyer state->flags |= DID_SYNC;
1867 1.1.2.2 bouyer state->sync_offset = state->msg_in[2];
1868 1.1.2.2 bouyer
1869 1.1.2.2 bouyer /* convert SCSI period to ASC period */
1870 1.1.2.2 bouyer i = state->msg_in[1] / asc->tb_ticks;
1871 1.1.2.2 bouyer if (i < asc->min_period)
1872 1.1.2.2 bouyer i = asc->min_period;
1873 1.1.2.2 bouyer else if (i >= asc->max_period) {
1874 1.1.2.2 bouyer /* can't do sync transfer, period too long */
1875 1.1.2.2 bouyer printf("%s: SCSI device %d: sync xfer period too long (%d)\n",
1876 1.1.2.2 bouyer asc->sc_dev.dv_xname, asc->target, i);
1877 1.1.2.2 bouyer i = asc->max_period;
1878 1.1.2.2 bouyer state->sync_offset = 0;
1879 1.1.2.2 bouyer }
1880 1.1.2.2 bouyer if ((i * asc->tb_ticks) != state->msg_in[1])
1881 1.1.2.2 bouyer i++;
1882 1.1.2.2 bouyer state->sync_period = i & 0x1F;
1883 1.1.2.2 bouyer
1884 1.1.2.2 bouyer /*
1885 1.1.2.2 bouyer * If this is a request, check minimums and
1886 1.1.2.2 bouyer * send back an acknowledge.
1887 1.1.2.2 bouyer */
1888 1.1.2.2 bouyer if (!(state->flags & TRY_SYNC)) {
1889 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_SET_ATN;
1890 1.1.2.2 bouyer readback(regs->asc_cmd);
1891 1.1.2.2 bouyer
1892 1.1.2.2 bouyer if (state->sync_period < asc->min_period)
1893 1.1.2.2 bouyer state->sync_period =
1894 1.1.2.2 bouyer asc->min_period;
1895 1.1.2.2 bouyer if (state->sync_offset > ASC_MAX_OFFSET)
1896 1.1.2.2 bouyer state->sync_offset =
1897 1.1.2.2 bouyer ASC_MAX_OFFSET;
1898 1.1.2.2 bouyer asc->script = &asc_scripts[SCRIPT_REPLY_SYNC];
1899 1.1.2.2 bouyer regs->asc_syn_p = state->sync_period;
1900 1.1.2.2 bouyer readback(regs->asc_syn_p);
1901 1.1.2.2 bouyer regs->asc_syn_o = state->sync_offset;
1902 1.1.2.2 bouyer readback(regs->asc_syn_o);
1903 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_MSG_ACPT;
1904 1.1.2.2 bouyer readback(regs->asc_cmd);
1905 1.1.2.2 bouyer return (0);
1906 1.1.2.2 bouyer }
1907 1.1.2.2 bouyer
1908 1.1.2.2 bouyer regs->asc_syn_p = state->sync_period;
1909 1.1.2.2 bouyer readback(regs->asc_syn_p);
1910 1.1.2.2 bouyer regs->asc_syn_o = state->sync_offset;
1911 1.1.2.2 bouyer readback(regs->asc_syn_o);
1912 1.1.2.2 bouyer goto done;
1913 1.1.2.2 bouyer
1914 1.1.2.2 bouyer default:
1915 1.1.2.2 bouyer printf("%s: SCSI device %d: rejecting extended message 0x%x\n",
1916 1.1.2.2 bouyer asc->sc_dev.dv_xname, asc->target,
1917 1.1.2.2 bouyer state->msg_in[0]);
1918 1.1.2.2 bouyer goto reject;
1919 1.1.2.2 bouyer }
1920 1.1.2.2 bouyer }
1921 1.1.2.2 bouyer
1922 1.1.2.2 bouyer /* process first byte of a message */
1923 1.1.2.2 bouyer #ifdef DEBUG
1924 1.1.2.2 bouyer if (asc_debug > 2)
1925 1.1.2.2 bouyer printf("asc_msg_in: msg %x\n", msg);
1926 1.1.2.2 bouyer #endif
1927 1.1.2.2 bouyer switch (msg) {
1928 1.1.2.2 bouyer #if 0
1929 1.1.2.2 bouyer case SCSI_MESSAGE_REJECT:
1930 1.1.2.2 bouyer printf(" did not like SYNCH xfer "); /* XXX */
1931 1.1.2.2 bouyer state->flags |= DID_SYNC;
1932 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_MSG_ACPT;
1933 1.1.2.2 bouyer readback(regs->asc_cmd);
1934 1.1.2.2 bouyer status = asc_wait(regs, ASC_CSR_INT);
1935 1.1.2.2 bouyer ir = regs->asc_intr;
1936 1.1.2.2 bouyer /* some just break out here, some dont */
1937 1.1.2.2 bouyer if (ASC_PHASE(status) == ASC_PHASE_MSG_OUT) {
1938 1.1.2.2 bouyer regs->asc_fifo = SCSI_ABORT;
1939 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_XFER_INFO;
1940 1.1.2.2 bouyer readback(regs->asc_cmd);
1941 1.1.2.2 bouyer status = asc_wait(regs, ASC_CSR_INT);
1942 1.1.2.2 bouyer ir = regs->asc_intr;
1943 1.1.2.2 bouyer }
1944 1.1.2.2 bouyer if (ir & ASC_INT_DISC) {
1945 1.1.2.2 bouyer asc_end(asc, status, 0, ir);
1946 1.1.2.2 bouyer return (0);
1947 1.1.2.2 bouyer }
1948 1.1.2.2 bouyer goto status;
1949 1.1.2.2 bouyer #endif /* 0 */
1950 1.1.2.2 bouyer
1951 1.1.2.2 bouyer case SCSI_EXTENDED_MSG: /* read an extended message */
1952 1.1.2.2 bouyer /* setup to read message length next */
1953 1.1.2.2 bouyer state->msglen = -1;
1954 1.1.2.2 bouyer state->msgcnt = 0;
1955 1.1.2.2 bouyer return (1);
1956 1.1.2.2 bouyer
1957 1.1.2.2 bouyer case SCSI_NO_OP:
1958 1.1.2.2 bouyer break;
1959 1.1.2.2 bouyer
1960 1.1.2.2 bouyer case SCSI_SAVE_DATA_POINTER:
1961 1.1.2.2 bouyer /* expect another message */
1962 1.1.2.2 bouyer return (1);
1963 1.1.2.2 bouyer
1964 1.1.2.2 bouyer case SCSI_RESTORE_POINTERS:
1965 1.1.2.2 bouyer /*
1966 1.1.2.2 bouyer * Need to do the following if resuming synchonous data in
1967 1.1.2.2 bouyer * on an odd byte boundary.
1968 1.1.2.2 bouyer regs->asc_cnfg2 |= ASC_CNFG2_RFB;
1969 1.1.2.2 bouyer */
1970 1.1.2.2 bouyer break;
1971 1.1.2.2 bouyer
1972 1.1.2.2 bouyer case SCSI_DISCONNECT:
1973 1.1.2.2 bouyer if (state->flags & DISCONN)
1974 1.1.2.2 bouyer goto abort;
1975 1.1.2.2 bouyer state->flags |= DISCONN;
1976 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_MSG_ACPT;
1977 1.1.2.2 bouyer readback(regs->asc_cmd);
1978 1.1.2.2 bouyer asc->script = &asc_scripts[SCRIPT_DISCONNECT];
1979 1.1.2.2 bouyer return (0);
1980 1.1.2.2 bouyer
1981 1.1.2.2 bouyer default:
1982 1.1.2.2 bouyer printf("%s: SCSI device %d: rejecting message 0x%x\n",
1983 1.1.2.2 bouyer asc->sc_dev.dv_xname, asc->target, msg);
1984 1.1.2.2 bouyer reject:
1985 1.1.2.2 bouyer /* request a message out before acknowledging this message */
1986 1.1.2.2 bouyer state->msg_out = SCSI_MESSAGE_REJECT;
1987 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_SET_ATN;
1988 1.1.2.2 bouyer readback(regs->asc_cmd);
1989 1.1.2.2 bouyer }
1990 1.1.2.2 bouyer
1991 1.1.2.2 bouyer done:
1992 1.1.2.2 bouyer /* return to original script */
1993 1.1.2.2 bouyer regs->asc_cmd = ASC_CMD_MSG_ACPT;
1994 1.1.2.2 bouyer readback(regs->asc_cmd);
1995 1.1.2.2 bouyer if (!state->script) {
1996 1.1.2.2 bouyer abort:
1997 1.1.2.2 bouyer #ifdef DEBUG
1998 1.1.2.2 bouyer asc_DumpLog("asc_msg_in");
1999 1.1.2.2 bouyer #endif
2000 1.1.2.2 bouyer panic("asc_msg_in");
2001 1.1.2.2 bouyer }
2002 1.1.2.2 bouyer asc->script = state->script;
2003 1.1.2.2 bouyer state->script = (script_t *)0;
2004 1.1.2.2 bouyer return (0);
2005 1.1.2.2 bouyer }
2006 1.1.2.2 bouyer
2007 1.1.2.2 bouyer /* ARGSUSED */
2008 1.1.2.2 bouyer static int
2009 1.1.2.2 bouyer asc_disconnect(asc, status, ss, ir)
2010 1.1.2.2 bouyer asc_softc_t asc;
2011 1.1.2.2 bouyer int status, ss, ir;
2012 1.1.2.2 bouyer {
2013 1.1.2.2 bouyer State *state = &asc->st[asc->target];
2014 1.1.2.2 bouyer
2015 1.1.2.2 bouyer #ifdef DIAGNOSTIC
2016 1.1.2.2 bouyer if (!(state->flags & DISCONN)) {
2017 1.1.2.2 bouyer printf("asc_disconnect: device %d: DISCONN not set!\n",
2018 1.1.2.2 bouyer asc->target);
2019 1.1.2.2 bouyer }
2020 1.1.2.2 bouyer #endif /* DIAGNOSTIC */
2021 1.1.2.2 bouyer asc->target = -1;
2022 1.1.2.2 bouyer asc->state = ASC_STATE_RESEL;
2023 1.1.2.2 bouyer return (1);
2024 1.1.2.2 bouyer }
2025 1.1.2.2 bouyer
2026 1.1.2.2 bouyer #ifdef DEBUG
2027 1.1.2.2 bouyer /*
2028 1.1.2.2 bouyer * Dump the log buffer.
2029 1.1.2.2 bouyer */
2030 1.1.2.2 bouyer static void
2031 1.1.2.2 bouyer asc_DumpLog(str)
2032 1.1.2.2 bouyer char *str;
2033 1.1.2.2 bouyer {
2034 1.1.2.2 bouyer register struct asc_log *lp;
2035 1.1.2.2 bouyer register u_int status;
2036 1.1.2.2 bouyer
2037 1.1.2.2 bouyer printf("asc: %s: cmd %x bn %d cnt %d\n", str, asc_debug_cmd,
2038 1.1.2.2 bouyer asc_debug_bn, asc_debug_sz);
2039 1.1.2.2 bouyer lp = asc_logp;
2040 1.1.2.2 bouyer do {
2041 1.1.2.2 bouyer status = lp->status;
2042 1.1.2.2 bouyer printf("asc%d tgt %d status %x ss %x ir %x cond %d:%x msg %x resid %d\n",
2043 1.1.2.2 bouyer status >> 24,
2044 1.1.2.2 bouyer lp->target,
2045 1.1.2.2 bouyer (status >> 16) & 0xFF,
2046 1.1.2.2 bouyer (status >> 8) & 0xFF,
2047 1.1.2.2 bouyer status & 0XFF,
2048 1.1.2.2 bouyer lp->state,
2049 1.1.2.2 bouyer asc_scripts[lp->state].condition,
2050 1.1.2.2 bouyer lp->msg, lp->resid);
2051 1.1.2.2 bouyer if (++lp >= &asc_log[NLOG])
2052 1.1.2.2 bouyer lp = asc_log;
2053 1.1.2.2 bouyer } while (lp != asc_logp);
2054 1.1.2.2 bouyer }
2055 1.1.2.2 bouyer #endif /* DEBUG */
2056