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