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