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