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