asc.c revision 1.6 1 /* $NetBSD: asc.c,v 1.6 2001/11/14 18:15:15 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 struct cfattach asc_ca = {
498 sizeof(struct asc_softc), ascmatch, ascattach
499 };
500
501 /*
502 * Glue to the machine dependent scsi
503 */
504 void asc_scsipi_request __P((struct scsipi_channel *,
505 scsipi_adapter_req_t, void *));
506
507 static int asc_intr __P((void *));
508 static void asc_poll __P((struct asc_softc *, int));
509 #ifdef DEBUG
510 static void asc_DumpLog __P((char *));
511 #endif
512
513 /*
514 * Match driver based on name
515 */
516 int
517 ascmatch(parent, match, aux)
518 struct device *parent;
519 struct cfdata *match;
520 void *aux;
521 {
522 struct jazzio_attach_args *ja = aux;
523
524 if(strcmp(ja->ja_name, "asc") != 0)
525 return (0);
526 return (1);
527 }
528
529 void
530 ascattach(parent, self, aux)
531 struct device *parent;
532 struct device *self;
533 void *aux;
534 {
535 struct jazzio_attach_args *ja = aux;
536 asc_softc_t asc = (void *)self;
537 asc_regmap_t *regs;
538 int id, s, i;
539 int bufsiz;
540
541 if (asc_conf == NULL)
542 panic("asc_conf isn't initialized");
543
544 /*
545 * Initialize hw descriptor, cache some pointers
546 */
547 asc->regs = (asc_regmap_t *)ja->ja_addr; /* XXX */
548
549 /*
550 * Set up machine dependencies.
551 * 1) how to do dma
552 * 2) timing based on chip clock frequency
553 */
554 #if 1 /*XXX check if code handles 0 as 64k */
555 bufsiz = 63 * 1024;
556 #else
557 bufsiz = 64 * 1024;
558 #endif
559 asc->dma = &asc->__dma;
560 asc_dma_init(asc->dma);
561
562 /*
563 * Now for timing.
564 */
565 asc->min_period = asc_conf->ac_timing->min_period;
566 asc->max_period = asc_conf->ac_timing->max_period;
567 asc->ccf = asc_conf->ac_timing->ccf;
568 asc->timeout_250 = asc_conf->ac_timing->timeout_250;
569 asc->tb_ticks = asc_conf->ac_timing->tb_ticks;
570
571 asc->state = ASC_STATE_IDLE;
572 asc->target = -1;
573
574 regs = asc->regs;
575
576 /*
577 * Reset chip, fully. Note that interrupts are already enabled.
578 */
579 s = splbio();
580
581 /* preserve our ID for now */
582 asc->sc_id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID;
583 asc->myidmask = ~(1 << asc->sc_id);
584
585 /* identify 53CF9x-2 or not */
586 regs->asc_cmd = ASC_CMD_RESET;
587 wbflush(); DELAY(25);
588 regs->asc_cmd = ASC_CMD_DMA | ASC_CMD_NOP;
589 wbflush(); DELAY(25);
590 regs->asc_cnfg2 = ASC_CNFG2_FE;
591 wbflush(); DELAY(25);
592 regs->asc_cmd = ASC_CMD_DMA | ASC_CMD_NOP;
593 wbflush(); DELAY(25);
594 asc->is24bit = regs->asc_id == ASC_ID_53CF94;
595
596 asc_reset(asc, regs);
597
598 /*
599 * Our SCSI id on the bus.
600 * The user can set this via the prom on 3maxen/picaen.
601 * If this changes it is easy to fix: make a default that
602 * can be changed as boot arg.
603 */
604 #ifdef unneeded
605 regs->asc_cnfg1 = (regs->asc_cnfg1 & ~ASC_CNFG1_MY_BUS_ID) |
606 (scsi_initiator_id[unit] & 0x7);
607 asc->sc_id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID;
608 #endif
609 id = asc->sc_id;
610 splx(s);
611
612 /*
613 * Give each target its DMA buffer region.
614 * The buffer address is the same for all targets,
615 * the allocated dma viritual scatter/gather space.
616 */
617 for (i = 0; i < ASC_NCMD; i++) {
618 asc->st[i].dmaBufSize = bufsiz;
619 }
620
621 /*
622 * Set up interrupt handler.
623 */
624 jazzio_intr_establish(ja->ja_intr, asc_intr, (void *)asc);
625
626 printf(": %s, target %d\n", asc->is24bit ? "NCR53CF9X-2" : "NCR53C94",
627 id);
628
629 asc->sc_adapter.adapt_dev = &asc->sc_dev;
630 asc->sc_adapter.adapt_nchannels = 1;
631 asc->sc_adapter.adapt_openings = 7;
632 asc->sc_adapter.adapt_max_periph = 1;
633 asc->sc_adapter.adapt_ioctl = NULL;
634 asc->sc_adapter.adapt_minphys = minphys;
635 asc->sc_adapter.adapt_request = asc_scsipi_request;
636
637 memset(&asc->sc_channel, 0, sizeof(asc->sc_channel));
638 asc->sc_channel.chan_adapter = &asc->sc_adapter;
639 asc->sc_channel.chan_bustype = &scsi_bustype;
640 asc->sc_channel.chan_channel = 0;
641 asc->sc_channel.chan_ntargets = 8;
642 asc->sc_channel.chan_nluns = 8;
643 asc->sc_channel.chan_id = asc->sc_id;
644
645 /*
646 * Now try to attach all the sub devices.
647 */
648 config_found(self, &asc->sc_channel, scsiprint);
649 }
650
651 /*
652 * Start activity on a SCSI device.
653 * We maintain information on each device separately since devices can
654 * connect/disconnect during an operation.
655 */
656 void
657 asc_scsipi_request(chan, req, arg)
658 struct scsipi_channel *chan;
659 scsipi_adapter_req_t req;
660 void *arg;
661 {
662 struct scsipi_xfer *xs;
663 struct scsipi_periph *periph;
664 struct asc_softc *asc = (void *)chan->chan_adapter->adapt_dev;
665 int dontqueue, s;
666
667 switch (req) {
668 case ADAPTER_REQ_RUN_XFER:
669 xs = arg;
670 periph = xs->xs_periph;
671
672 dontqueue = xs->xs_control & XS_CTL_POLL;
673
674 /*
675 * Flush caches for any data buffer
676 */
677 if(xs->datalen != 0) {
678 mips_dcache_wbinv_range((vaddr_t)xs->data, xs->datalen);
679 }
680 /*
681 * The hack on the next few lines are to avoid buffers
682 * mapped to UADDR. Realloc to the kva uarea address.
683 */
684 if((u_int)(xs->data) >= UADDR) {
685 xs->data = ((u_int)(xs->data) & ~UADDR) + (u_char *)(curproc->p_addr);
686 }
687
688 s = splbio();
689 asc->cmd[periph->periph_target] = xs;
690
691 /*
692 * Going to launch.
693 * Make a local copy of the command and some pointers.
694 */
695 asc_startcmd(asc, periph->periph_target);
696
697 /*
698 * If in startup, interrupts not usable yet.
699 */
700 if(dontqueue) {
701 asc_poll(asc,periph->periph_target);
702 }
703 splx(s);
704 return;
705 case ADAPTER_REQ_GROW_RESOURCES:
706 /* XXX Not supported. */
707 return;
708 case ADAPTER_REQ_SET_XFER_MODE:
709 /* XXX Not supported. */
710 return;
711 }
712 }
713
714 void
715 asc_poll(asc, target)
716 struct asc_softc *asc;
717 int target;
718 {
719 struct scsipi_xfer *scsicmd = asc->cmd[target];
720 int count = scsicmd->timeout * 10;
721
722 while(count) {
723 if(asc->regs->asc_status &ASC_CSR_INT) {
724 asc_intr(asc);
725 }
726 if(scsicmd->xs_status & XS_STS_DONE)
727 break;
728 DELAY(5);
729 count--;
730 }
731 if(count == 0) {
732 scsicmd->error = XS_TIMEOUT;
733 asc_end(asc, 0, 0, 0);
734 }
735 }
736
737 static void
738 asc_reset(asc, regs)
739 asc_softc_t asc;
740 asc_regmap_t *regs;
741 {
742
743 /*
744 * Reset chip and wait till done
745 */
746 regs->asc_cmd = ASC_CMD_RESET;
747 wbflush(); DELAY(25);
748
749 /* spec says this is needed after reset */
750 regs->asc_cmd = ASC_CMD_NOP;
751 wbflush(); DELAY(25);
752
753 /*
754 * Set up various chip parameters
755 */
756 regs->asc_ccf = asc->ccf;
757 wbflush(); DELAY(25);
758 regs->asc_sel_timo = asc->timeout_250;
759 /* restore our ID */
760 regs->asc_cnfg1 = asc->sc_id | ASC_CNFG1_P_CHECK;
761 /* include ASC_CNFG2_SCSI2 if you want to allow SCSI II commands */
762 regs->asc_cnfg2 = /* ASC_CNFG2_RFB | ASC_CNFG2_SCSI2 | */ ASC_CNFG2_EPL;
763 regs->asc_cnfg3 = asc_conf->ac_cnfg3;
764 /* zero anything else */
765 ASC_TC_PUT(regs, 0, asc->is24bit);
766 regs->asc_syn_p = asc->min_period;
767 regs->asc_syn_o = 0; /* async for now */
768 wbflush();
769 }
770
771 /*
772 * Start a SCSI command on a target.
773 */
774 static void
775 asc_startcmd(asc, target)
776 asc_softc_t asc;
777 int target;
778 {
779 asc_regmap_t *regs;
780 State *state;
781 struct scsipi_xfer *scsicmd;
782 int i, len;
783
784 /*
785 * See if another target is currently selected on this SCSI bus.
786 */
787 if (asc->target >= 0)
788 return;
789
790 regs = asc->regs;
791
792 /*
793 * If a reselection is in progress, it is Ok to ignore it since
794 * the ASC will automatically cancel the command and flush
795 * the FIFO if the ASC is reselected before the command starts.
796 * If we try to use ASC_CMD_DISABLE_SEL, we can hang the system if
797 * a reselect occurs before starting the command.
798 */
799
800 asc->state = ASC_STATE_BUSY;
801 asc->target = target;
802
803 /* cache some pointers */
804 scsicmd = asc->cmd[target];
805 state = &asc->st[target];
806
807 /*
808 * Init the chip and target state.
809 */
810 state->flags = state->flags & DID_SYNC;
811 state->script = (script_t *)0;
812 state->msg_out = SCSI_NO_OP;
813
814 /*
815 * Set up for DMA of command output. Also need to flush cache.
816 */
817 bcopy(scsicmd->cmd, &state->cmd, scsicmd->cmdlen);
818 state->cmdlen = scsicmd->cmdlen;
819 state->buf = (vaddr_t)scsicmd->data;
820 state->buflen = scsicmd->datalen;
821 len = state->cmdlen;
822 state->dmalen = len;
823
824 #ifdef DEBUG
825 if (asc_debug > 1) {
826 printf("asc_startcmd: %s target %d cmd %x len %d\n",
827 asc->sc_dev.dv_xname, target,
828 state->cmd.opcode, state->buflen);
829 }
830 #endif
831
832 /* check for simple SCSI command with no data transfer */
833 if (scsicmd->xs_control & XS_CTL_DATA_OUT) {
834 asc->script = &asc_scripts[SCRIPT_DATA_OUT];
835 state->flags |= DMA_OUT;
836 }
837 else if (scsicmd->xs_control & XS_CTL_DATA_IN) {
838 asc->script = &asc_scripts[SCRIPT_DATA_IN];
839 state->flags |= DMA_IN;
840 }
841 else if (state->buflen == 0) {
842 /* check for sync negotiation */
843 if ((scsicmd->xs_status & /* SCSICMD_USE_SYNC */ 0) &&
844 !(state->flags & DID_SYNC)) {
845 asc->script = &asc_scripts[SCRIPT_TRY_SYNC];
846 state->flags |= TRY_SYNC;
847 } else
848 asc->script = &asc_scripts[SCRIPT_SIMPLE];
849 state->buf = (vaddr_t)0;
850 }
851
852 #ifdef DEBUG
853 asc_debug_cmd = state->cmd.opcode;
854 if (state->cmd.opcode == SCSI_READ_EXT) {
855 asc_debug_bn = (state->cmd.bytes[1] << 24) |
856 (state->cmd.bytes[2] << 16) |
857 (state->cmd.bytes[3] << 8) |
858 state->cmd.bytes[4];
859 asc_debug_sz = (state->cmd.bytes[6] << 8) | state->cmd.bytes[7];
860 }
861 asc_logp->status = PACK(asc->sc_dev.dv_unit, 0, 0, asc_debug_cmd);
862 asc_logp->target = asc->target;
863 asc_logp->state = asc->script - asc_scripts;
864 asc_logp->msg = SCSI_DIS_REC_IDENTIFY;
865 asc_logp->resid = scsicmd->datalen;
866 if (++asc_logp >= &asc_log[NLOG])
867 asc_logp = asc_log;
868 #endif
869
870 /* preload the FIFO with the message and command to be sent */
871 regs->asc_fifo = SCSI_DIS_REC_IDENTIFY |
872 (scsicmd->xs_periph->periph_lun & 0x07);
873
874 for( i = 0; i < len; i++ ) {
875 regs->asc_fifo = ((caddr_t)&state->cmd)[i];
876 }
877 ASC_TC_PUT(regs, 0, asc->is24bit);
878 readback(regs->asc_cmd);
879 regs->asc_cmd = ASC_CMD_DMA;
880 readback(regs->asc_cmd);
881
882 regs->asc_dbus_id = target;
883 readback(regs->asc_dbus_id);
884 regs->asc_syn_p = state->sync_period;
885 readback(regs->asc_syn_p);
886 regs->asc_syn_o = state->sync_offset;
887 readback(regs->asc_syn_o);
888
889 /*XXX PEFO */
890 /* we are not using sync transfer now, need to check this if we will */
891
892 if (state->flags & TRY_SYNC)
893 regs->asc_cmd = ASC_CMD_SEL_ATN_STOP;
894 else
895 regs->asc_cmd = ASC_CMD_SEL_ATN;
896 readback(regs->asc_cmd);
897 }
898
899 /*
900 * Interrupt routine
901 * Take interrupts from the chip
902 *
903 * Implementation:
904 * Move along the current command's script if
905 * all is well, invoke error handler if not.
906 */
907 int
908 asc_intr(sc)
909 void *sc;
910 {
911 asc_softc_t asc = sc;
912 asc_regmap_t *regs = asc->regs;
913 State *state;
914 script_t *scpt;
915 int ss, ir, status;
916
917 /* collect ephemeral information */
918 status = regs->asc_status;
919 ss = regs->asc_ss;
920
921 if ((status & ASC_CSR_INT) == 0) /* Make shure it's a real interrupt */
922 return(0);
923
924 ir = regs->asc_intr; /* this resets the previous two */
925 scpt = asc->script;
926
927 #ifdef DEBUG
928 asc_logp->status = PACK(asc->sc_dev.dv_unit, status, ss, ir);
929 asc_logp->target = (asc->state == ASC_STATE_BUSY) ? asc->target : -1;
930 asc_logp->state = scpt - asc_scripts;
931 asc_logp->msg = -1;
932 asc_logp->resid = 0;
933 if (++asc_logp >= &asc_log[NLOG])
934 asc_logp = asc_log;
935 if (asc_debug > 2)
936 printf("asc_intr: status %x ss %x ir %x cond %d:%x\n",
937 status, ss, ir, scpt - asc_scripts, scpt->condition);
938 #endif
939
940 /* check the expected state */
941 if (SCRIPT_MATCH(ir, status) == scpt->condition) {
942 /*
943 * Perform the appropriate operation, then proceed.
944 */
945 if ((*scpt->action)(asc, status, ss, ir)) {
946 regs->asc_cmd = scpt->command;
947 readback(regs->asc_cmd);
948 asc->script = scpt->next;
949 }
950 goto done;
951 }
952
953 /*
954 * Check for parity error.
955 * Hardware will automatically set ATN
956 * to request the device for a MSG_OUT phase.
957 */
958 if (status & ASC_CSR_PE) {
959 printf("%s: SCSI device %d: incomming parity error seen\n",
960 asc->sc_dev.dv_xname, asc->target);
961 asc->st[asc->target].flags |= PARITY_ERR;
962 }
963
964 /*
965 * Check for gross error.
966 * Probably a bug in a device driver.
967 */
968 if (status & ASC_CSR_GE) {
969 printf("%s: SCSI device %d: gross error\n",
970 asc->sc_dev.dv_xname, asc->target);
971 goto abort;
972 }
973
974 /* check for message in or out */
975 if ((ir & ~ASC_INT_FC) == ASC_INT_BS) {
976 register int len, fifo;
977
978 state = &asc->st[asc->target];
979 switch (ASC_PHASE(status)) {
980 case ASC_PHASE_DATAI:
981 case ASC_PHASE_DATAO:
982 ASC_TC_GET(regs, len);
983 fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
984 printf("asc_intr: data overrun: buflen %d dmalen %d tc %d fifo %d\n",
985 state->buflen, state->dmalen, len, fifo);
986 goto abort;
987
988 case ASC_PHASE_MSG_IN:
989 break;
990
991 case ASC_PHASE_MSG_OUT:
992 /*
993 * Check for parity error.
994 * Hardware will automatically set ATN
995 * to request the device for a MSG_OUT phase.
996 */
997 if (state->flags & PARITY_ERR) {
998 state->flags &= ~PARITY_ERR;
999 state->msg_out = SCSI_MESSAGE_PARITY_ERROR;
1000 /* reset message in counter */
1001 state->msglen = 0;
1002 } else
1003 state->msg_out = SCSI_NO_OP;
1004 regs->asc_fifo = state->msg_out;
1005 regs->asc_cmd = ASC_CMD_XFER_INFO;
1006 readback(regs->asc_cmd);
1007 goto done;
1008
1009 case ASC_PHASE_STATUS:
1010 /* probably an error in the SCSI command */
1011 asc->script = &asc_scripts[SCRIPT_GET_STATUS];
1012 regs->asc_cmd = ASC_CMD_I_COMPLETE;
1013 readback(regs->asc_cmd);
1014 goto done;
1015
1016 default:
1017 goto abort;
1018 }
1019
1020 if (state->script)
1021 goto abort;
1022
1023 /*
1024 * OK, message coming in clean up whatever is going on.
1025 * Get number of bytes left to transfered from byte counter
1026 * counter decrements when data is trf on the SCSI bus
1027 */
1028 ASC_TC_GET(regs, len);
1029 fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1030 /* flush any data in the FIFO */
1031 if (fifo && !(state->flags & DMA_IN_PROGRESS)) {
1032 printf("asc_intr: fifo flush %d len %d fifo %x\n", fifo, len, regs->asc_fifo);
1033 regs->asc_cmd = ASC_CMD_FLUSH;
1034 readback(regs->asc_cmd);
1035 DELAY(2);
1036 }
1037 else if (fifo && state->flags & DMA_IN_PROGRESS) {
1038 if (state->flags & DMA_OUT) {
1039 len += fifo; /* Bytes dma'ed but not sent */
1040 }
1041 else if (state->flags & DMA_IN) {
1042 printf("asc_intr: IN: dmalen %d len %d fifo %d\n",
1043 state->dmalen, len, fifo); /* XXX */
1044 }
1045 regs->asc_cmd = ASC_CMD_FLUSH;
1046 readback(regs->asc_cmd);
1047 DELAY(2);
1048 }
1049 if (len && (state->flags & DMA_IN_PROGRESS)) {
1050 /* save number of bytes still to be sent or received */
1051 state->dmaresid = len;
1052 state->flags &= ~DMA_IN_PROGRESS;
1053 ASC_TC_PUT(regs, 0, asc->is24bit);
1054 #ifdef DEBUG
1055 if (asc_logp == asc_log)
1056 asc_log[NLOG - 1].resid = len;
1057 else
1058 asc_logp[-1].resid = len;
1059 #endif
1060 /* setup state to resume to */
1061 if (state->flags & DMA_IN) {
1062 /*
1063 * Since the ASC_CNFG3_SRB bit of the
1064 * cnfg3 register bit is not set,
1065 * we just transferred an extra byte.
1066 * Since we can't resume on an odd byte
1067 * boundary, we copy the valid data out
1068 * and resume DMA at the start address.
1069 */
1070 if (len & 1) {
1071 printf("asc_intr: msg in len %d (fifo %d)\n",
1072 len, fifo); /* XXX */
1073 len = state->dmalen - len;
1074 goto do_in;
1075 }
1076 state->script =
1077 &asc_scripts[SCRIPT_RESUME_DMA_IN];
1078 } else if (state->flags & DMA_OUT)
1079 state->script =
1080 &asc_scripts[SCRIPT_RESUME_DMA_OUT];
1081 else
1082 state->script = asc->script;
1083 } else if (state->flags & DMA_IN) {
1084 if (len) {
1085 #ifdef DEBUG
1086 printf("asc_intr: 1: bn %d len %d (fifo %d)\n",
1087 asc_debug_bn, len, fifo); /* XXX */
1088 #endif
1089 goto abort;
1090 }
1091 /* setup state to resume to */
1092 if (state->flags & DMA_IN_PROGRESS) {
1093 len = state->dmalen;
1094 state->flags &= ~DMA_IN_PROGRESS;
1095 do_in:
1096 DMA_END(asc->dma);
1097 state->buf += len;
1098 state->buflen -= len;
1099 }
1100 if (state->buflen)
1101 state->script =
1102 &asc_scripts[SCRIPT_RESUME_IN];
1103 else
1104 state->script =
1105 &asc_scripts[SCRIPT_RESUME_NO_DATA];
1106 } else if (state->flags & DMA_OUT) {
1107 if (len) {
1108 printf("asc_intr: 2: len %d (fifo %d)\n", len,
1109 fifo); /* XXX */
1110 /* XXX THEO */
1111 #if 1
1112 regs->asc_cmd = ASC_CMD_FLUSH;
1113 readback(regs->asc_cmd);
1114 DELAY(2);
1115 len = 0;
1116 #else
1117 goto abort;
1118 #endif
1119 }
1120 /*
1121 * If this is the last chunk, the next expected
1122 * state is to get status.
1123 */
1124 if (state->flags & DMA_IN_PROGRESS) {
1125 state->flags &= ~DMA_IN_PROGRESS;
1126 DMA_END(asc->dma);
1127 len = state->dmalen;
1128 state->buf += len;
1129 state->buflen -= len;
1130 }
1131 if (state->buflen)
1132 state->script =
1133 &asc_scripts[SCRIPT_RESUME_OUT];
1134 else
1135 state->script =
1136 &asc_scripts[SCRIPT_RESUME_NO_DATA];
1137 } else if (asc->script == &asc_scripts[SCRIPT_SIMPLE])
1138 state->script = &asc_scripts[SCRIPT_RESUME_NO_DATA];
1139 else
1140 state->script = asc->script;
1141
1142 /* setup to receive a message */
1143 asc->script = &asc_scripts[SCRIPT_MSG_IN];
1144 state->msglen = 0;
1145 regs->asc_cmd = ASC_CMD_XFER_INFO;
1146 readback(regs->asc_cmd);
1147 goto done;
1148 }
1149
1150 /* check for SCSI bus reset */
1151 if (ir & ASC_INT_RESET) {
1152 register int i;
1153
1154 printf("%s: SCSI bus reset!!\n", asc->sc_dev.dv_xname);
1155 /* need to flush any pending commands */
1156 for (i = 0; i < ASC_NCMD; i++) {
1157 if (!asc->cmd[i])
1158 continue;
1159 asc->cmd[i]->error = XS_DRIVER_STUFFUP;
1160 asc_end(asc, 0, 0, 0);
1161 }
1162 /* rearbitrate synchronous offset */
1163 for (i = 0; i < ASC_NCMD; i++) {
1164 asc->st[i].sync_offset = 0;
1165 asc->st[i].flags = 0;
1166 }
1167 asc->target = -1;
1168 return(1);
1169 }
1170
1171 /* check for command errors */
1172 if (ir & ASC_INT_ILL)
1173 goto abort;
1174
1175 /* check for disconnect */
1176 if (ir & ASC_INT_DISC) {
1177 state = &asc->st[asc->target];
1178 switch (asc->script - asc_scripts) {
1179 case SCRIPT_DONE:
1180 case SCRIPT_DISCONNECT:
1181 /*
1182 * Disconnects can happen normally when the
1183 * command is complete with the phase being
1184 * either ASC_PHASE_DATAO or ASC_PHASE_MSG_IN.
1185 * The SCRIPT_MATCH() only checks for one phase
1186 * so we can wind up here.
1187 * Perform the appropriate operation, then proceed.
1188 */
1189 if ((*scpt->action)(asc, status, ss, ir)) {
1190 regs->asc_cmd = scpt->command;
1191 readback(regs->asc_cmd);
1192 asc->script = scpt->next;
1193 }
1194 goto done;
1195
1196 case SCRIPT_TRY_SYNC:
1197 case SCRIPT_SIMPLE:
1198 case SCRIPT_DATA_IN:
1199 case SCRIPT_DATA_OUT: /* one of the starting scripts */
1200 if (ASC_SS(ss) == 0) {
1201 /* device did not respond */
1202 if (regs->asc_flags & ASC_FLAGS_FIFO_CNT) {
1203 regs->asc_cmd = ASC_CMD_FLUSH;
1204 readback(regs->asc_cmd);
1205 }
1206 asc->cmd[asc->target]->error = XS_SELTIMEOUT;
1207 asc_end(asc, status, ss, ir);
1208 return(1);
1209 }
1210 /* FALLTHROUGH */
1211
1212 default:
1213 printf("%s: SCSI device %d: unexpected disconnect\n",
1214 asc->sc_dev.dv_xname, asc->target);
1215 #ifdef DEBUG
1216 asc_DumpLog("asc_disc");
1217 #endif
1218 /*
1219 * On rare occasions my RZ24 does a disconnect during
1220 * data in phase and the following seems to keep it
1221 * happy.
1222 * XXX Should a scsi disk ever do this??
1223 */
1224 asc->script = &asc_scripts[SCRIPT_RESEL];
1225 asc->state = ASC_STATE_RESEL;
1226 state->flags |= DISCONN;
1227 regs->asc_cmd = ASC_CMD_ENABLE_SEL;
1228 readback(regs->asc_cmd);
1229 return(1);
1230 }
1231 }
1232
1233 /* check for reselect */
1234 if (ir & ASC_INT_RESEL) {
1235 unsigned fifo, id, msg;
1236
1237 fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1238 if (fifo < 2)
1239 goto abort;
1240 /* read unencoded SCSI ID and convert to binary */
1241 msg = regs->asc_fifo & asc->myidmask;
1242 for (id = 0; (msg & 1) == 0; id++)
1243 msg >>= 1;
1244 /* read identify message */
1245 msg = regs->asc_fifo;
1246 #ifdef DEBUG
1247 if (asc_logp == asc_log)
1248 asc_log[NLOG - 1].msg = msg;
1249 else
1250 asc_logp[-1].msg = msg;
1251 #endif
1252 asc->state = ASC_STATE_BUSY;
1253 asc->target = id;
1254 state = &asc->st[id];
1255 asc->script = state->script;
1256 state->script = (script_t *)0;
1257 if (!(state->flags & DISCONN))
1258 goto abort;
1259 state->flags &= ~DISCONN;
1260 regs->asc_syn_p = state->sync_period;
1261 regs->asc_syn_o = state->sync_offset;
1262 regs->asc_cmd = ASC_CMD_MSG_ACPT;
1263 readback(regs->asc_cmd);
1264 goto done;
1265 }
1266
1267 /* check if we are being selected as a target */
1268 if (ir & (ASC_INT_SEL | ASC_INT_SEL_ATN))
1269 goto abort;
1270
1271 /*
1272 * 'ir' must be just ASC_INT_FC.
1273 * This is normal if canceling an ASC_ENABLE_SEL.
1274 */
1275
1276 done:
1277 wbflush();
1278 /*
1279 * If the next interrupt comes in immediatly the interrupt
1280 * dispatcher (which we are returning to) will catch it
1281 * before returning to the interrupted code.
1282 */
1283 return(1);
1284
1285 abort:
1286 #ifdef DEBUG
1287 asc_DumpLog("asc_intr");
1288 #endif
1289 panic("asc_intr");
1290 return(1);
1291 }
1292
1293 /*
1294 * All the many little things that the interrupt
1295 * routine might switch to.
1296 */
1297
1298 /* ARGSUSED */
1299 static int
1300 script_nop(asc, status, ss, ir)
1301 asc_softc_t asc;
1302 int status, ss, ir;
1303 {
1304 return (1);
1305 }
1306
1307 /* ARGSUSED */
1308 static int
1309 asc_get_status(asc, status, ss, ir)
1310 register asc_softc_t asc;
1311 register int status, ss, ir;
1312 {
1313 register asc_regmap_t *regs = asc->regs;
1314 register int data;
1315
1316 /*
1317 * Get the last two bytes in the FIFO.
1318 */
1319 if ((data = regs->asc_flags & ASC_FLAGS_FIFO_CNT) != 2) {
1320 printf("asc_get_status: cmdreg %x, fifo cnt %d\n",
1321 regs->asc_cmd, data); /* XXX */
1322 #ifdef DEBUG
1323 asc_DumpLog("get_status"); /* XXX */
1324 #endif
1325 if (data < 2) {
1326 asc->regs->asc_cmd = ASC_CMD_MSG_ACPT;
1327 readback(asc->regs->asc_cmd);
1328 return (0);
1329 }
1330 do {
1331 data = regs->asc_fifo;
1332 } while ((regs->asc_flags & ASC_FLAGS_FIFO_CNT) > 2);
1333 }
1334
1335 /* save the status byte */
1336 asc->st[asc->target].statusByte = data = regs->asc_fifo;
1337 #ifdef DEBUG
1338 if (asc_logp == asc_log)
1339 asc_log[NLOG - 1].msg = data;
1340 else
1341 asc_logp[-1].msg = data;
1342 #endif
1343
1344 /* get the (presumed) command_complete message */
1345 if ((data = regs->asc_fifo) == SCSI_COMMAND_COMPLETE)
1346 return (1);
1347
1348 #ifdef DEBUG
1349 printf("asc_get_status: status %x cmd %x\n",
1350 asc->st[asc->target].statusByte, data);
1351 asc_DumpLog("asc_get_status");
1352 #endif
1353 return (0);
1354 }
1355
1356 /* ARGSUSED */
1357 static int
1358 asc_end(asc, status, ss, ir)
1359 asc_softc_t asc;
1360 int status, ss, ir;
1361 {
1362 struct scsipi_xfer *scsicmd;
1363 struct scsipi_periph *periph;
1364 State *state;
1365 int i, target;
1366
1367 asc->state = ASC_STATE_IDLE;
1368 target = asc->target;
1369 asc->target = -1;
1370 scsicmd = asc->cmd[target];
1371 periph = scsicmd->xs_periph;
1372 asc->cmd[target] = (struct scsipi_xfer *)0;
1373 state = &asc->st[target];
1374
1375 #ifdef DEBUG
1376 if (asc_debug > 1) {
1377 printf("asc_end: %s target %d cmd %x err %d resid %d\n",
1378 asc->sc_dev.dv_xname, target,
1379 state->cmd.opcode, scsicmd->error, state->buflen);
1380 }
1381 #endif
1382 #ifdef DIAGNOSTIC
1383 if (target < 0 || !scsicmd)
1384 panic("asc_end");
1385 #endif
1386
1387 /* look for disconnected devices */
1388 for (i = 0; i < ASC_NCMD; i++) {
1389 if (!asc->cmd[i] || !(asc->st[i].flags & DISCONN))
1390 continue;
1391 asc->regs->asc_cmd = ASC_CMD_ENABLE_SEL;
1392 readback(asc->regs->asc_cmd);
1393 asc->state = ASC_STATE_RESEL;
1394 asc->script = &asc_scripts[SCRIPT_RESEL];
1395 break;
1396 }
1397
1398 if(scsicmd->error == XS_NOERROR) {
1399 if((state->statusByte & ST_MASK) == SCSI_CHECK) {
1400 scsicmd->status = state->statusByte;
1401 scsicmd->error = XS_BUSY;
1402 }
1403 }
1404
1405 scsicmd->resid = state->buflen;
1406
1407 /*
1408 * Look for another device that is ready.
1409 * May want to keep last one started and increment for fairness
1410 * rather than always starting at zero.
1411 */
1412 for (i = 0; i < ASC_NCMD; i++) {
1413 /* don't restart a disconnected command */
1414 if (!asc->cmd[i] || (asc->st[i].flags & DISCONN))
1415 continue;
1416 asc_startcmd(asc, i);
1417 break;
1418 }
1419
1420 /* signal device driver that the command is done */
1421 scsipi_done(scsicmd);
1422
1423 return (0);
1424 }
1425
1426 /* ARGSUSED */
1427 static int
1428 asc_dma_in(asc, status, ss, ir)
1429 register asc_softc_t asc;
1430 register int status, ss, ir;
1431 {
1432 register asc_regmap_t *regs = asc->regs;
1433 register State *state = &asc->st[asc->target];
1434 register int len;
1435
1436 /* check for previous chunk in buffer */
1437 if (state->flags & DMA_IN_PROGRESS) {
1438 /*
1439 * Only count bytes that have been copied to memory.
1440 * There may be some bytes in the FIFO if synchonous transfers
1441 * are in progress.
1442 */
1443 DMA_END(asc->dma);
1444 ASC_TC_GET(regs, len);
1445 len = state->dmalen - len;
1446 state->buf += len;
1447 state->buflen -= len;
1448 }
1449
1450 /* setup to start reading the next chunk */
1451 len = state->buflen;
1452 #ifdef DEBUG
1453 if (asc_logp == asc_log)
1454 asc_log[NLOG - 1].resid = len;
1455 else
1456 asc_logp[-1].resid = len;
1457 #endif
1458 if (len > state->dmaBufSize)
1459 len = state->dmaBufSize;
1460 state->dmalen = len;
1461 DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_FROM_DEV);
1462 ASC_TC_PUT(regs, len, asc->is24bit);
1463 #ifdef DEBUG
1464 if (asc_debug > 2)
1465 printf("asc_dma_in: buflen %d, len %d\n", state->buflen, len);
1466 #endif
1467
1468 /* check for next chunk */
1469 state->flags |= DMA_IN_PROGRESS;
1470 if (len != state->buflen) {
1471 regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1472 readback(regs->asc_cmd);
1473 asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
1474 return (0);
1475 }
1476 return (1);
1477 }
1478
1479 /* ARGSUSED */
1480 static int
1481 asc_last_dma_in(asc, status, ss, ir)
1482 register asc_softc_t asc;
1483 register int status, ss, ir;
1484 {
1485 register asc_regmap_t *regs = asc->regs;
1486 register State *state = &asc->st[asc->target];
1487 register int len, fifo;
1488
1489 DMA_END(asc->dma);
1490 ASC_TC_GET(regs, len);
1491 fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1492 #ifdef DEBUG
1493 if (asc_debug > 2)
1494 printf("asc_last_dma_in: buflen %d dmalen %d tc %d fifo %d\n",
1495 state->buflen, state->dmalen, len, fifo);
1496 #endif
1497 if (fifo) {
1498 /* device must be trying to send more than we expect */
1499 regs->asc_cmd = ASC_CMD_FLUSH;
1500 readback(regs->asc_cmd);
1501 }
1502 state->flags &= ~DMA_IN_PROGRESS;
1503 len = state->dmalen - len;
1504 state->buflen -= len;
1505
1506 return (1);
1507 }
1508
1509 /* ARGSUSED */
1510 static int
1511 asc_resume_in(asc, status, ss, ir)
1512 register asc_softc_t asc;
1513 register int status, ss, ir;
1514 {
1515 register asc_regmap_t *regs = asc->regs;
1516 register State *state = &asc->st[asc->target];
1517 register int len;
1518
1519 /* setup to start reading the next chunk */
1520 len = state->buflen;
1521 #ifdef DEBUG
1522 if (asc_logp == asc_log)
1523 asc_log[NLOG - 1].resid = len;
1524 else
1525 asc_logp[-1].resid = len;
1526 #endif
1527 if (len > state->dmaBufSize)
1528 len = state->dmaBufSize;
1529 state->dmalen = len;
1530 #ifdef DEBUG
1531 if (asc_logp == asc_log)
1532 asc_log[NLOG - 1].resid = len;
1533 else
1534 asc_logp[-1].resid = len;
1535 #endif
1536 DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_FROM_DEV);
1537 ASC_TC_PUT(regs, len, asc->is24bit);
1538 #ifdef DEBUG
1539 if (asc_debug > 2)
1540 printf("asc_resume_in: buflen %d, len %d\n", state->buflen,
1541 len);
1542 #endif
1543
1544 /* check for next chunk */
1545 state->flags |= DMA_IN_PROGRESS;
1546 if (len != state->buflen) {
1547 regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1548 readback(regs->asc_cmd);
1549 asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
1550 return (0);
1551 }
1552 return (1);
1553 }
1554
1555 /* ARGSUSED */
1556 static int
1557 asc_resume_dma_in(asc, status, ss, ir)
1558 register asc_softc_t asc;
1559 register int status, ss, ir;
1560 {
1561 register asc_regmap_t *regs = asc->regs;
1562 register State *state = &asc->st[asc->target];
1563 register int len, off;
1564
1565 /* setup to finish reading the current chunk */
1566 len = state->dmaresid;
1567 off = state->dmalen - len;
1568 if ((off & 1) && state->sync_offset) {
1569 printf("asc_resume_dma_in: odd xfer dmalen %d len %d off %d\n",
1570 state->dmalen, len, off); /* XXX */
1571 regs->asc_res_fifo = ((u_char *)state->buf)[off];
1572 /*XXX Need to flush cache ? */
1573 }
1574 DMA_START(asc->dma, (caddr_t)state->buf + off, len, DMA_FROM_DEV);
1575 ASC_TC_PUT(regs, len, asc->is24bit);
1576 #ifdef DEBUG
1577 if (asc_debug > 2)
1578 printf("asc_resume_dma_in: buflen %d dmalen %d len %d off %d\n",
1579 state->dmalen, state->buflen, len, off);
1580 #endif
1581
1582 /* check for next chunk */
1583 state->flags |= DMA_IN_PROGRESS;
1584 if (state->dmalen != state->buflen) {
1585 regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1586 readback(regs->asc_cmd);
1587 asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
1588 return (0);
1589 }
1590 return (1);
1591 }
1592
1593 /* ARGSUSED */
1594 static int
1595 asc_dma_out(asc, status, ss, ir)
1596 register asc_softc_t asc;
1597 register int status, ss, ir;
1598 {
1599 register asc_regmap_t *regs = asc->regs;
1600 register State *state = &asc->st[asc->target];
1601 register int len, fifo;
1602
1603 if (state->flags & DMA_IN_PROGRESS) {
1604 /* check to be sure previous chunk was finished */
1605 ASC_TC_GET(regs, len);
1606 fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1607 if (len || fifo)
1608 printf("asc_dma_out: buflen %d dmalen %d tc %d fifo %d\n",
1609 state->buflen, state->dmalen, len, fifo); /* XXX */
1610 len += fifo;
1611 len = state->dmalen - len;
1612 state->buf += len;
1613 state->buflen -= len;
1614 }
1615
1616 /* setup for this chunk */
1617 len = state->buflen;
1618 #ifdef DEBUG
1619 if (asc_logp == asc_log)
1620 asc_log[NLOG - 1].resid = len;
1621 else
1622 asc_logp[-1].resid = len;
1623 #endif
1624 if (len > state->dmaBufSize)
1625 len = state->dmaBufSize;
1626 state->dmalen = len;
1627 DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_TO_DEV);
1628 ASC_TC_PUT(regs, len, asc->is24bit);
1629 #ifdef DEBUG
1630 if (asc_debug > 2)
1631 printf("asc_dma_out: buflen %d, len %d\n", state->buflen, len);
1632 #endif
1633
1634 /* check for next chunk */
1635 state->flags |= DMA_IN_PROGRESS;
1636 if (len != state->buflen) {
1637 regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1638 readback(regs->asc_cmd);
1639 asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
1640 return (0);
1641 }
1642 return (1);
1643 }
1644
1645 /* ARGSUSED */
1646 static int
1647 asc_last_dma_out(asc, status, ss, ir)
1648 register asc_softc_t asc;
1649 register int status, ss, ir;
1650 {
1651 register asc_regmap_t *regs = asc->regs;
1652 register State *state = &asc->st[asc->target];
1653 register int len, fifo;
1654
1655 ASC_TC_GET(regs, len);
1656 fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1657 #ifdef DEBUG
1658 if (asc_debug > 2)
1659 printf("asc_last_dma_out: buflen %d dmalen %d tc %d fifo %d\n",
1660 state->buflen, state->dmalen, len, fifo);
1661 #endif
1662 if (fifo) {
1663 len += fifo;
1664 regs->asc_cmd = ASC_CMD_FLUSH;
1665 readback(regs->asc_cmd);
1666 }
1667 state->flags &= ~DMA_IN_PROGRESS;
1668 len = state->dmalen - len;
1669 state->buflen -= len;
1670 return (1);
1671 }
1672
1673 /* ARGSUSED */
1674 static int
1675 asc_resume_out(asc, status, ss, ir)
1676 register asc_softc_t asc;
1677 register int status, ss, ir;
1678 {
1679 register asc_regmap_t *regs = asc->regs;
1680 register State *state = &asc->st[asc->target];
1681 register int len;
1682
1683 /* setup for this chunk */
1684 len = state->buflen;
1685 #ifdef DEBUG
1686 if (asc_logp == asc_log)
1687 asc_log[NLOG - 1].resid = len;
1688 else
1689 asc_logp[-1].resid = len;
1690 #endif
1691 if (len > state->dmaBufSize)
1692 len = state->dmaBufSize;
1693 state->dmalen = len;
1694 #ifdef DEBUG
1695 if (asc_logp == asc_log)
1696 asc_log[NLOG - 1].resid = len;
1697 else
1698 asc_logp[-1].resid = len;
1699 #endif
1700 DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_TO_DEV);
1701 ASC_TC_PUT(regs, len, asc->is24bit);
1702 #ifdef DEBUG
1703 if (asc_debug > 2)
1704 printf("asc_resume_out: buflen %d, len %d\n", state->buflen,
1705 len);
1706 #endif
1707
1708 /* check for next chunk */
1709 state->flags |= DMA_IN_PROGRESS;
1710 if (len != state->buflen) {
1711 regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1712 readback(regs->asc_cmd);
1713 asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
1714 return (0);
1715 }
1716 return (1);
1717 }
1718
1719 /* ARGSUSED */
1720 static int
1721 asc_resume_dma_out(asc, status, ss, ir)
1722 register asc_softc_t asc;
1723 register int status, ss, ir;
1724 {
1725 register asc_regmap_t *regs = asc->regs;
1726 register State *state = &asc->st[asc->target];
1727 register int len, off;
1728
1729 /* setup to finish writing this chunk */
1730 len = state->dmaresid;
1731 off = state->dmalen - len;
1732 if (off & 1) {
1733 printf("asc_resume_dma_out: odd xfer dmalen %d len %d off %d\n",
1734 state->dmalen, len, off); /* XXX */
1735 regs->asc_fifo = ((u_char *)state->buf)[off];
1736 /*XXX Need to flush Cache ? */
1737 off++;
1738 len--;
1739 }
1740 DMA_START(asc->dma, (caddr_t)state->buf + off, len, DMA_TO_DEV);
1741 ASC_TC_PUT(regs, len, asc->is24bit);
1742 #ifdef DEBUG
1743 if (asc_debug > 2)
1744 printf("asc_resume_dma_out: buflen %d dmalen %d len %d off %d\n",
1745 state->dmalen, state->buflen, len, off);
1746 #endif
1747
1748 /* check for next chunk */
1749 state->flags |= DMA_IN_PROGRESS;
1750 if (state->dmalen != state->buflen) {
1751 regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1752 readback(regs->asc_cmd);
1753 asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
1754 return (0);
1755 }
1756 return (1);
1757 }
1758
1759 /* ARGSUSED */
1760 static int
1761 asc_sendsync(asc, status, ss, ir)
1762 register asc_softc_t asc;
1763 register int status, ss, ir;
1764 {
1765 register asc_regmap_t *regs = asc->regs;
1766 register State *state = &asc->st[asc->target];
1767
1768 /* send the extended synchronous negotiation message */
1769 regs->asc_fifo = SCSI_EXTENDED_MSG;
1770 wbflush();
1771 regs->asc_fifo = 3;
1772 wbflush();
1773 regs->asc_fifo = SCSI_SYNCHRONOUS_XFER;
1774 wbflush();
1775 regs->asc_fifo = SCSI_MIN_PERIOD;
1776 wbflush();
1777 regs->asc_fifo = ASC_MAX_OFFSET;
1778 /* state to resume after we see the sync reply message */
1779 state->script = asc->script + 2;
1780 state->msglen = 0;
1781 return (1);
1782 }
1783
1784 /* ARGSUSED */
1785 static int
1786 asc_replysync(asc, status, ss, ir)
1787 register asc_softc_t asc;
1788 register int status, ss, ir;
1789 {
1790 register asc_regmap_t *regs = asc->regs;
1791 register State *state = &asc->st[asc->target];
1792
1793 #ifdef DEBUG
1794 if (asc_debug > 2)
1795 printf("asc_replysync: %x %x\n",
1796 asc_to_scsi_period[state->sync_period] * asc->tb_ticks,
1797 state->sync_offset);
1798 #endif
1799 /* send synchronous transfer in response to a request */
1800 regs->asc_fifo = SCSI_EXTENDED_MSG;
1801 wbflush();
1802 regs->asc_fifo = 3;
1803 wbflush();
1804 regs->asc_fifo = SCSI_SYNCHRONOUS_XFER;
1805 wbflush();
1806 regs->asc_fifo = asc_to_scsi_period[state->sync_period] * asc->tb_ticks;
1807 wbflush();
1808 regs->asc_fifo = state->sync_offset;
1809 regs->asc_cmd = ASC_CMD_XFER_INFO;
1810 readback(regs->asc_cmd);
1811
1812 /* return to the appropriate script */
1813 if (!state->script) {
1814 #ifdef DEBUG
1815 asc_DumpLog("asc_replsync");
1816 #endif
1817 panic("asc_replysync");
1818 }
1819 asc->script = state->script;
1820 state->script = (script_t *)0;
1821 return (0);
1822 }
1823
1824 /* ARGSUSED */
1825 static int
1826 asc_msg_in(asc, status, ss, ir)
1827 register asc_softc_t asc;
1828 register int status, ss, ir;
1829 {
1830 register asc_regmap_t *regs = asc->regs;
1831 register State *state = &asc->st[asc->target];
1832 register int msg;
1833 int i;
1834
1835 /* read one message byte */
1836 msg = regs->asc_fifo;
1837 #ifdef DEBUG
1838 if (asc_logp == asc_log)
1839 asc_log[NLOG - 1].msg = msg;
1840 else
1841 asc_logp[-1].msg = msg;
1842 #endif
1843
1844 /* check for multi-byte message */
1845 if (state->msglen != 0) {
1846 /* first byte is the message length */
1847 if (state->msglen < 0) {
1848 state->msglen = msg;
1849 return (1);
1850 }
1851 if (state->msgcnt >= state->msglen)
1852 goto abort;
1853 state->msg_in[state->msgcnt++] = msg;
1854
1855 /* did we just read the last byte of the message? */
1856 if (state->msgcnt != state->msglen)
1857 return (1);
1858
1859 /* process an extended message */
1860 #ifdef DEBUG
1861 if (asc_debug > 2)
1862 printf("asc_msg_in: msg %x %x %x\n",
1863 state->msg_in[0],
1864 state->msg_in[1],
1865 state->msg_in[2]);
1866 #endif
1867 switch (state->msg_in[0]) {
1868 case SCSI_SYNCHRONOUS_XFER:
1869 state->flags |= DID_SYNC;
1870 state->sync_offset = state->msg_in[2];
1871
1872 /* convert SCSI period to ASC period */
1873 i = state->msg_in[1] / asc->tb_ticks;
1874 if (i < asc->min_period)
1875 i = asc->min_period;
1876 else if (i >= asc->max_period) {
1877 /* can't do sync transfer, period too long */
1878 printf("%s: SCSI device %d: sync xfer period too long (%d)\n",
1879 asc->sc_dev.dv_xname, asc->target, i);
1880 i = asc->max_period;
1881 state->sync_offset = 0;
1882 }
1883 if ((i * asc->tb_ticks) != state->msg_in[1])
1884 i++;
1885 state->sync_period = i & 0x1F;
1886
1887 /*
1888 * If this is a request, check minimums and
1889 * send back an acknowledge.
1890 */
1891 if (!(state->flags & TRY_SYNC)) {
1892 regs->asc_cmd = ASC_CMD_SET_ATN;
1893 readback(regs->asc_cmd);
1894
1895 if (state->sync_period < asc->min_period)
1896 state->sync_period =
1897 asc->min_period;
1898 if (state->sync_offset > ASC_MAX_OFFSET)
1899 state->sync_offset =
1900 ASC_MAX_OFFSET;
1901 asc->script = &asc_scripts[SCRIPT_REPLY_SYNC];
1902 regs->asc_syn_p = state->sync_period;
1903 readback(regs->asc_syn_p);
1904 regs->asc_syn_o = state->sync_offset;
1905 readback(regs->asc_syn_o);
1906 regs->asc_cmd = ASC_CMD_MSG_ACPT;
1907 readback(regs->asc_cmd);
1908 return (0);
1909 }
1910
1911 regs->asc_syn_p = state->sync_period;
1912 readback(regs->asc_syn_p);
1913 regs->asc_syn_o = state->sync_offset;
1914 readback(regs->asc_syn_o);
1915 goto done;
1916
1917 default:
1918 printf("%s: SCSI device %d: rejecting extended message 0x%x\n",
1919 asc->sc_dev.dv_xname, asc->target,
1920 state->msg_in[0]);
1921 goto reject;
1922 }
1923 }
1924
1925 /* process first byte of a message */
1926 #ifdef DEBUG
1927 if (asc_debug > 2)
1928 printf("asc_msg_in: msg %x\n", msg);
1929 #endif
1930 switch (msg) {
1931 #if 0
1932 case SCSI_MESSAGE_REJECT:
1933 printf(" did not like SYNCH xfer "); /* XXX */
1934 state->flags |= DID_SYNC;
1935 regs->asc_cmd = ASC_CMD_MSG_ACPT;
1936 readback(regs->asc_cmd);
1937 status = asc_wait(regs, ASC_CSR_INT);
1938 ir = regs->asc_intr;
1939 /* some just break out here, some dont */
1940 if (ASC_PHASE(status) == ASC_PHASE_MSG_OUT) {
1941 regs->asc_fifo = SCSI_ABORT;
1942 regs->asc_cmd = ASC_CMD_XFER_INFO;
1943 readback(regs->asc_cmd);
1944 status = asc_wait(regs, ASC_CSR_INT);
1945 ir = regs->asc_intr;
1946 }
1947 if (ir & ASC_INT_DISC) {
1948 asc_end(asc, status, 0, ir);
1949 return (0);
1950 }
1951 goto status;
1952 #endif /* 0 */
1953
1954 case SCSI_EXTENDED_MSG: /* read an extended message */
1955 /* setup to read message length next */
1956 state->msglen = -1;
1957 state->msgcnt = 0;
1958 return (1);
1959
1960 case SCSI_NO_OP:
1961 break;
1962
1963 case SCSI_SAVE_DATA_POINTER:
1964 /* expect another message */
1965 return (1);
1966
1967 case SCSI_RESTORE_POINTERS:
1968 /*
1969 * Need to do the following if resuming synchonous data in
1970 * on an odd byte boundary.
1971 regs->asc_cnfg2 |= ASC_CNFG2_RFB;
1972 */
1973 break;
1974
1975 case SCSI_DISCONNECT:
1976 if (state->flags & DISCONN)
1977 goto abort;
1978 state->flags |= DISCONN;
1979 regs->asc_cmd = ASC_CMD_MSG_ACPT;
1980 readback(regs->asc_cmd);
1981 asc->script = &asc_scripts[SCRIPT_DISCONNECT];
1982 return (0);
1983
1984 default:
1985 printf("%s: SCSI device %d: rejecting message 0x%x\n",
1986 asc->sc_dev.dv_xname, asc->target, msg);
1987 reject:
1988 /* request a message out before acknowledging this message */
1989 state->msg_out = SCSI_MESSAGE_REJECT;
1990 regs->asc_cmd = ASC_CMD_SET_ATN;
1991 readback(regs->asc_cmd);
1992 }
1993
1994 done:
1995 /* return to original script */
1996 regs->asc_cmd = ASC_CMD_MSG_ACPT;
1997 readback(regs->asc_cmd);
1998 if (!state->script) {
1999 abort:
2000 #ifdef DEBUG
2001 asc_DumpLog("asc_msg_in");
2002 #endif
2003 panic("asc_msg_in");
2004 }
2005 asc->script = state->script;
2006 state->script = (script_t *)0;
2007 return (0);
2008 }
2009
2010 /* ARGSUSED */
2011 static int
2012 asc_disconnect(asc, status, ss, ir)
2013 asc_softc_t asc;
2014 int status, ss, ir;
2015 {
2016 #ifdef DIAGNOSTIC
2017 if (!(asc->st[asc->target].flags & DISCONN)) {
2018 printf("asc_disconnect: device %d: DISCONN not set!\n",
2019 asc->target);
2020 }
2021 #endif /* DIAGNOSTIC */
2022 asc->target = -1;
2023 asc->state = ASC_STATE_RESEL;
2024 return (1);
2025 }
2026
2027 #ifdef DEBUG
2028 /*
2029 * Dump the log buffer.
2030 */
2031 static void
2032 asc_DumpLog(str)
2033 char *str;
2034 {
2035 register struct asc_log *lp;
2036 register u_int status;
2037
2038 printf("asc: %s: cmd %x bn %d cnt %d\n", str, asc_debug_cmd,
2039 asc_debug_bn, asc_debug_sz);
2040 lp = asc_logp;
2041 do {
2042 status = lp->status;
2043 printf("asc%d tgt %d status %x ss %x ir %x cond %d:%x msg %x resid %d\n",
2044 status >> 24,
2045 lp->target,
2046 (status >> 16) & 0xFF,
2047 (status >> 8) & 0xFF,
2048 status & 0XFF,
2049 lp->state,
2050 asc_scripts[lp->state].condition,
2051 lp->msg, lp->resid);
2052 if (++lp >= &asc_log[NLOG])
2053 lp = asc_log;
2054 } while (lp != asc_logp);
2055 }
2056 #endif /* DEBUG */
2057