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