siop.c revision 1.2 1 /*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Van Jacobson of Lawrence Berkeley Laboratory.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)siop.c 7.5 (Berkeley) 5/4/91
37 *
38 * MULTICONTROLLER support only working for multiple controllers of the
39 * same kind at the moment !!
40 *
41 */
42
43 /*
44 * AMIGA 53C710 scsi adaptor driver
45 */
46
47 #include "zeusscsi.h"
48 #include "magnumscsi.h"
49 #define NSIOP (NZEUSSCSI + NMAGNUMSCSI)
50 #if NSIOP > 0
51
52 #ifndef lint
53 static char rcsid[] = "$Header: /tank/opengrok/rsync2/NetBSD/src/sys/arch/amiga/dev/siop.c,v 1.2 1994/02/01 11:52:35 chopps Exp $";
54 #endif
55
56 /* need to know if any tapes have been configured */
57 #include "st.h"
58
59 #include "sys/param.h"
60 #include "sys/systm.h"
61 #include "sys/buf.h"
62 #include "device.h"
63
64 #include "scsidefs.h"
65 #include "siopvar.h"
66 #include "siopreg.h"
67
68 #include "../amiga/custom.h"
69
70 #include "machine/cpu.h"
71
72 extern u_int kvtop();
73
74 /*
75 * SCSI delays
76 * In u-seconds, primarily for state changes on the SPC.
77 */
78 #define SCSI_CMD_WAIT 50000 /* wait per step of 'immediate' cmds */
79 #define SCSI_DATA_WAIT 50000 /* wait per data in/out step */
80 #define SCSI_INIT_WAIT 50000 /* wait per step (both) during init */
81
82 void siopstart (int unit);
83 int siopgo (int ctlr, int slave, int unit, struct buf *bp, struct scsi_fmt_cdb *cdb, int pad);
84 int siopintr2 (void);
85 void siopdone (int unit);
86 int siopustart (int unit);
87 int siopreq (register struct devqueue *dq);
88 void siopfree (register struct devqueue *dq);
89 void siopreset (int unit);
90 void siop_delay (int delay);
91 int siop_test_unit_rdy (int ctlr, int slave, int unit);
92 int siop_start_stop_unit (int ctlr, int slave, int unit, int start);
93 int siop_request_sense (int ctlr, int slave, int unit, u_char *buf, unsigned int len);
94 int siop_immed_command (int ctlr, int slave, int unit, struct scsi_fmt_cdb *cdb, u_char *buf, unsigned int len, int rd);
95 int siop_tt_read (int ctlr, int slave, int unit, u_char *buf, u_int len, daddr_t blk, int bshift);
96 int siop_tt_write (int ctlr, int slave, int unit, u_char *buf, u_int len, daddr_t blk, int bshift);
97 #if NST > 0
98 int siop_tt_oddio (int ctlr, int slave, int unit, u_char *buf, u_int len, int b_flags, int freedma);
99 #endif
100
101 #if NZEUSSCSI > 0
102 int zeusscsiinit();
103
104 struct driver zeusscsidriver = {
105 zeusscsiinit, "Zeusscsi", (int (*)())siopstart, (int (*)())siopgo,
106 (int (*)())siopintr2, (int (*)())siopdone,
107 siopustart, siopreq, siopfree, siopreset,
108 siop_delay, siop_test_unit_rdy, siop_start_stop_unit,
109 siop_request_sense, siop_immed_command, siop_tt_read, siop_tt_write,
110 #if NST > 0
111 siop_tt_oddio
112 #else
113 0
114 #endif
115 };
116 #endif
117
118 #if NMAGNUMSCSI > 0
119 int magnumscsiinit();
120
121 struct driver magnumscsidriver = {
122 magnumscsiinit, "Magnumscsi", (int (*)())siopstart, (int (*)())siopgo,
123 (int (*)())siopintr2, (int (*)())siopdone,
124 siopustart, siopreq, siopfree, siopreset,
125 siop_delay, siop_test_unit_rdy, siop_start_stop_unit,
126 siop_request_sense, siop_immed_command, siop_tt_read, siop_tt_write,
127 #if NST > 0
128 siop_tt_oddio
129 #else
130 0
131 #endif
132 };
133 #endif
134
135 /* 53C710 script */
136 unsigned long scripts[] = {
137 0x47000000, 0x00000298, /* 000 - 0 */
138 0x838b0000, 0x000000d0, /* 008 - 8 */
139 0x7a1b1000, 0x00000000, /* 010 - 16 */
140 0x828a0000, 0x00000088, /* 018 - 24 */
141 0x9e020000, 0x0000ff01, /* 020 - 32 */
142 0x72350000, 0x00000000, /* 028 - 40 */
143 0x808c0000, 0x00000048, /* 030 - 48 */
144 0x58000008, 0x00000000, /* 038 - 56 */
145 0x1e000024, 0x00000024, /* 040 - 64 */
146 0x838b0000, 0x00000090, /* 048 - 72 */
147 0x1f00002c, 0x0000002c, /* 050 - 80 */
148 0x838b0000, 0x00000080, /* 058 - 88 */
149 0x868a0000, 0xffffffd0, /* 060 - 96 */
150 0x838a0000, 0x00000070, /* 068 - 104 */
151 0x878a0000, 0x00000120, /* 070 - 112 */
152 0x80880000, 0x00000028, /* 078 - 120 */
153 0x1e000004, 0x00000004, /* 080 - 128 */
154 0x838b0000, 0x00000050, /* 088 - 136 */
155 0x868a0000, 0xffffffe8, /* 090 - 144 */
156 0x838a0000, 0x00000040, /* 098 - 152 */
157 0x878a0000, 0x000000f0, /* 0a0 - 160 */
158 0x9a020000, 0x0000ff02, /* 0a8 - 168 */
159 0x1a00000c, 0x0000000c, /* 0b0 - 176 */
160 0x878b0000, 0x00000130, /* 0b8 - 184 */
161 0x838a0000, 0x00000018, /* 0c0 - 192 */
162 0x818a0000, 0x000000b0, /* 0c8 - 200 */
163 0x808a0000, 0x00000080, /* 0d0 - 208 */
164 0x98080000, 0x0000ff03, /* 0d8 - 216 */
165 0x1b000014, 0x00000014, /* 0e0 - 224 */
166 0x72090000, 0x00000000, /* 0e8 - 232 */
167 0x6a340000, 0x00000000, /* 0f0 - 240 */
168 0x9f030000, 0x0000ff04, /* 0f8 - 248 */
169 0x1f00001c, 0x0000001c, /* 100 - 256 */
170 0x98040000, 0x0000ff26, /* 108 - 264 */
171 0x60000040, 0x00000000, /* 110 - 272 */
172 0x48000000, 0x00000000, /* 118 - 280 */
173 0x7c1bef00, 0x00000000, /* 120 - 288 */
174 0x72340000, 0x00000000, /* 128 - 296 */
175 0x980c0002, 0x0000fffc, /* 130 - 304 */
176 0x980c0008, 0x0000fffb, /* 138 - 312 */
177 0x980c0018, 0x0000fffd, /* 140 - 320 */
178 0x98040000, 0x0000fffe, /* 148 - 328 */
179 0x98080000, 0x0000ff00, /* 150 - 336 */
180 0x18000034, 0x00000034, /* 158 - 344 */
181 0x808b0000, 0x000001c0, /* 160 - 352 */
182 0x838b0000, 0xffffff70, /* 168 - 360 */
183 0x878a0000, 0x000000d0, /* 170 - 368 */
184 0x98080000, 0x0000ff05, /* 178 - 376 */
185 0x19000034, 0x00000034, /* 180 - 384 */
186 0x818b0000, 0x00000160, /* 188 - 392 */
187 0x80880000, 0xffffffd0, /* 190 - 400 */
188 0x1f00001c, 0x0000001c, /* 198 - 408 */
189 0x808c0001, 0x00000018, /* 1a0 - 416 */
190 0x980c0002, 0x0000ff08, /* 1a8 - 424 */
191 0x808c0004, 0x00000020, /* 1b0 - 432 */
192 0x98080000, 0x0000ff06, /* 1b8 - 440 */
193 0x60000040, 0x00000000, /* 1c0 - 448 */
194 0x1f00002c, 0x0000002c, /* 1c8 - 456 */
195 0x98080000, 0x0000ff07, /* 1d0 - 464 */
196 0x60000040, 0x00000000, /* 1d8 - 472 */
197 0x48000000, 0x00000000, /* 1e0 - 480 */
198 0x98080000, 0x0000ff09, /* 1e8 - 488 */
199 0x1f00001c, 0x0000001c, /* 1f0 - 496 */
200 0x808c0001, 0x00000018, /* 1f8 - 504 */
201 0x980c0002, 0x0000ff10, /* 200 - 512 */
202 0x808c0004, 0x00000020, /* 208 - 520 */
203 0x98080000, 0x0000ff11, /* 210 - 528 */
204 0x60000040, 0x00000000, /* 218 - 536 */
205 0x1f00002c, 0x0000002c, /* 220 - 544 */
206 0x98080000, 0x0000ff12, /* 228 - 552 */
207 0x60000040, 0x00000000, /* 230 - 560 */
208 0x48000000, 0x00000000, /* 238 - 568 */
209 0x98080000, 0x0000ff13, /* 240 - 576 */
210 0x1f00001c, 0x0000001c, /* 248 - 584 */
211 0x808c0001, 0x00000018, /* 250 - 592 */
212 0x980c0002, 0x0000ff14, /* 258 - 600 */
213 0x808c0004, 0x00000020, /* 260 - 608 */
214 0x98080000, 0x0000ff15, /* 268 - 616 */
215 0x60000040, 0x00000000, /* 270 - 624 */
216 0x1f00002c, 0x0000002c, /* 278 - 632 */
217 0x98080000, 0x0000ff16, /* 280 - 640 */
218 0x60000040, 0x00000000, /* 288 - 648 */
219 0x48000000, 0x00000000, /* 290 - 656 */
220 0x98080000, 0x0000ff17, /* 298 - 664 */
221 0x54000000, 0x00000040, /* 2a0 - 672 */
222 0x9f030000, 0x0000ff18, /* 2a8 - 680 */
223 0x1f00001c, 0x0000001c, /* 2b0 - 688 */
224 0x990b0000, 0x0000ff19, /* 2b8 - 696 */
225 0x980a0000, 0x0000ff20, /* 2c0 - 704 */
226 0x9f0a0000, 0x0000ff21, /* 2c8 - 712 */
227 0x9b0a0000, 0x0000ff22, /* 2d0 - 720 */
228 0x9e0a0000, 0x0000ff23, /* 2d8 - 728 */
229 0x98080000, 0x0000ff24, /* 2e0 - 736 */
230 0x98080000, 0x0000ff25, /* 2e8 - 744 */
231 0x76100800, 0x00000000, /* 2f0 - 752 */
232 0x80840700, 0x00000008, /* 2f8 - 760 */
233 0x7e110100, 0x00000000, /* 300 - 768 */
234 0x6a100000, 0x00000000, /* 308 - 776 */
235 0x19000034, 0x00000034, /* 310 - 784 */
236 0x818b0000, 0xffffffd0, /* 318 - 792 */
237 0x98080000, 0x0000ff27, /* 320 - 800 */
238 0x76100800, 0x00000000, /* 328 - 808 */
239 0x80840700, 0x00000008, /* 330 - 816 */
240 0x7e110100, 0x00000000, /* 338 - 824 */
241 0x6a100000, 0x00000000, /* 340 - 832 */
242 0x18000034, 0x00000034, /* 348 - 840 */
243 0x808b0000, 0xffffffd0, /* 350 - 848 */
244 0x98080000, 0x0000ff27 /* 358 - 856 */
245 };
246
247 #define Ent_msgout 0x00000018
248 #define Ent_cmd 0x000000a8
249 #define Ent_status 0x000000e0
250 #define Ent_msgin 0x000000f8
251 #define Ent_dataout 0x00000158
252 #define Ent_datain 0x00000180
253
254 struct siop_softc siop_softc[NSIOP];
255
256 int siop_cmd_wait = SCSI_CMD_WAIT;
257 int siop_data_wait = SCSI_DATA_WAIT;
258 int siop_init_wait = SCSI_INIT_WAIT;
259
260 static struct {
261 unsigned char x; /* period from sync request message */
262 unsigned char y; /* siop_period << 4 | sbcl */
263 } xxx[] = {
264 {0x0f, 0x01},
265 {0x13, 0x11},
266 {0x17, 0x21},
267 /* {0x17, 0x02}, */
268 {0x1b, 0x31},
269 {0x1d, 0x12},
270 {0x1e, 0x41},
271 /* {0x1e, 0x03}, */
272 {0x22, 0x51},
273 {0x23, 0x22},
274 {0x26, 0x61},
275 /* {0x26, 0x13}, */
276 {0x29, 0x32},
277 {0x2a, 0x71},
278 {0x2d, 0x23},
279 {0x2e, 0x42},
280 {0x34, 0x52},
281 {0x35, 0x33},
282 {0x3a, 0x62},
283 {0x3c, 0x43},
284 {0x40, 0x72},
285 {0x44, 0x53},
286 {0x4b, 0x63},
287 {0x53, 0x73}
288 };
289
290 scsi_period_to_siop (dev, target)
291 struct siop_softc *dev;
292 {
293 int period, offset, i, sxfer;
294
295 period = dev->sc_msg[4];
296 offset = dev->sc_msg[5];
297 sxfer = 0;
298 if (offset <= SIOP_MAX_OFFSET)
299 sxfer = offset;
300 for (i = 0; i < sizeof (xxx) / 2; ++i) {
301 if (period <= xxx[i].x) {
302 sxfer |= xxx[i].y & 0x70;
303 offset = xxx[i].y & 0x03;
304 break;
305 }
306 }
307 dev->sc_sync[target].period = sxfer;
308 dev->sc_sync[target].offset = offset;
309 #ifdef DEBUG
310 printf ("sync: siop_sxfr %02x, siop_sbcl %02x\n", sxfer, offset);
311 #endif
312 }
313
314 /* default to not inhibit sync negotiation on any drive */
315 u_char siop_inhibit_sync[NSIOP][8] = { 0, 0, 1, 0, 0, 0, 0 }; /* initialize, so patchable */
316 int siop_no_dma = 0;
317
318 /*
319 * XXX Set/reset long delays.
320 *
321 * if delay == 0, reset default delays
322 * if delay < 0, set both delays to default long initialization values
323 * if delay > 0, set both delays to this value
324 *
325 * Used when a devices is expected to respond slowly (e.g. during
326 * initialization).
327 */
328 void
329 siop_delay(delay)
330 int delay;
331 {
332 static int saved_cmd_wait, saved_data_wait;
333
334 if (delay) {
335 saved_cmd_wait = siop_cmd_wait;
336 saved_data_wait = siop_data_wait;
337 if (delay > 0)
338 siop_cmd_wait = siop_data_wait = delay;
339 else
340 siop_cmd_wait = siop_data_wait = siop_init_wait;
341 } else {
342 siop_cmd_wait = saved_cmd_wait;
343 siop_data_wait = saved_data_wait;
344 }
345 }
346
347 static int initialized[NSIOP];
348
349 #ifdef DEBUG
350 /* 0x01 - full debug */
351 /* 0x02 - DMA chaining */
352 /* 0x04 - siopintr */
353 /* 0x08 - phase mismatch */
354 int siop_debug = 0;
355 int siopsync_debug = 0;
356 int siopdma_hits = 0;
357 int siopdma_misses = 0;
358 #endif
359
360 static void
361 siopabort(dev, regs, where)
362 register struct siop_softc *dev;
363 volatile register siop_regmap_t *regs;
364 char *where;
365 {
366
367 printf ("siop%d: abort %s: dstat %02x, sstat0 %02x sbcl %02x\n",
368 dev->sc_ac->amiga_unit,
369 where, regs->siop_dstat, regs->siop_sstat0, regs->siop_sbcl);
370
371 if (dev->sc_flags & SIOP_SELECTED) {
372 #ifdef TODO
373 SET_SBIC_cmd (regs, SBIC_CMD_ABORT);
374 WAIT_CIP (regs);
375
376 GET_SBIC_asr (regs, asr);
377 if (asr & (SBIC_ASR_BSY|SBIC_ASR_LCI))
378 {
379 /* ok, get more drastic.. */
380
381 SET_SBIC_cmd (regs, SBIC_CMD_RESET);
382 DELAY(25);
383 SBIC_WAIT(regs, SBIC_ASR_INT, 0);
384 GET_SBIC_csr (regs, csr); /* clears interrupt also */
385
386 dev->sc_flags &= ~SIOP_SELECTED;
387 return;
388 }
389
390 do
391 {
392 SBIC_WAIT (regs, SBIC_ASR_INT, 0);
393 GET_SBIC_csr (regs, csr);
394 }
395 while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1)
396 && (csr != SBIC_CSR_CMD_INVALID));
397 #endif
398
399 /* lets just hope it worked.. */
400 dev->sc_flags &= ~SIOP_SELECTED;
401 }
402 }
403
404 #if NZEUSSCSI > 0
405 int
406 zeusscsiinit(ac)
407 register struct amiga_ctlr *ac;
408 {
409 register struct siop_softc *dev = &siop_softc[ac->amiga_unit];
410
411 #ifdef DEBUG
412 if (siop_debug)
413 printf ("zeusscsiinit: addr %x unit %d scripts %x ds %x\n",
414 ac->amiga_addr, ac->amiga_unit, scripts, &dev->sc_ds);
415 #endif
416 if ((int) scripts & 3)
417 panic ("zeusscsiinit: scripts not on a longword boundary");
418 if ((long)&dev->sc_ds & 3)
419 panic("zeusscsiinit: data storage alignment error\n");
420 if (! ac->amiga_addr)
421 return 0;
422
423 if (initialized[ac->amiga_unit])
424 return 0;
425
426 initialized[ac->amiga_unit] = 1;
427
428 /* advance ac->amiga_addr to point to the real siop-registers */
429 ac->amiga_addr = (caddr_t) ((int)ac->amiga_addr + 0x4000);
430 dev->sc_clock_freq = 0xc0;
431
432 /* hardwired IPL */
433 ac->amiga_ipl = 6;
434 dev->sc_ac = ac;
435 dev->sc_dq.dq_driver = &zeusscsidriver;
436 dev->sc_sq.dq_forw = dev->sc_sq.dq_back = &dev->sc_sq;
437 siopreset (ac->amiga_unit);
438
439 /* For the ZEUS SCSI, both IPL6 and IPL2 interrupts have to be
440 enabled. The ZEUS SCSI generates IPL6 interrupts, which are
441 not blocked by splbio(). The ZEUS interrupt handler saves the
442 siop interrupt status information in siop_softc and sets the
443 PORTS interrupt to process the interrupt at IPL2.
444
445 make sure IPL2 interrupts are delivered to the cpu when siopintr6
446 generates some. Note that this does not yet enable siop-interrupts,
447 this is handled in siopgo, which selectively enables interrupts only
448 while DMA requests are pending.
449
450 Note that enabling PORTS interrupts also enables keyboard interrupts
451 as soon as the corresponding int-enable bit in CIA-A is set. */
452
453 #if 0 /* EXTER interrupts are enabled in the clock initialization */
454 custom.intreq = INTF_EXTER;
455 custom.intena = INTF_SETCLR | INTF_EXTER;
456 #endif
457 custom.intreq = INTF_PORTS;
458 custom.intena = INTF_SETCLR | INTF_PORTS;
459 return(1);
460 }
461 #endif
462
463 #if NMAGNUMSCSI > 0
464 int
465 magnumscsiinit(ac)
466 register struct amiga_ctlr *ac;
467 {
468 register struct siop_softc *dev = &siop_softc[ac->amiga_unit];
469
470 #ifdef DEBUG
471 if (siop_debug)
472 printf ("magnumscsiinit: addr %x unit %d scripts %x ds %x\n",
473 ac->amiga_addr, ac->amiga_unit, scripts, &dev->sc_ds);
474 #endif
475 if ((int) scripts & 3)
476 panic ("magnumscsiinit: scripts not on a longword boundary");
477 if ((long)&dev->sc_ds & 3)
478 panic("magnumscsiinit: data storage alignment error\n");
479 if (! ac->amiga_addr)
480 return 0;
481
482 if (initialized[ac->amiga_unit])
483 return 0;
484
485 initialized[ac->amiga_unit] = 1;
486
487 /* advance ac->amiga_addr to point to the real siop-registers */
488 ac->amiga_addr = (caddr_t) ((int)ac->amiga_addr + 0x8000);
489 dev->sc_clock_freq = 0x40; /* DCNTL = 25.01->37.5MHZ / SCLK/1.5 */
490
491 /* hardwired IPL */
492 ac->amiga_ipl = 2;
493 dev->sc_ac = ac;
494 dev->sc_dq.dq_driver = &magnumscsidriver;
495 dev->sc_sq.dq_forw = dev->sc_sq.dq_back = &dev->sc_sq;
496 siopreset (ac->amiga_unit);
497
498 /* make sure IPL2 interrupts are delivered to the cpu when the siop
499 generates some. Note that this does not yet enable siop-interrupts,
500 this is handled in siopgo, which selectively enables interrupts only
501 while DMA requests are pending.
502
503 Note that enabling PORTS interrupts also enables keyboard interrupts
504 as soon as the corresponding int-enable bit in CIA-A is set. */
505
506 custom.intreq = INTF_PORTS;
507 custom.intena = INTF_SETCLR | INTF_PORTS;
508 return(1);
509 }
510 #endif
511
512
513 void
514 siopreset(unit)
515 register int unit;
516 {
517 register struct siop_softc *dev = &siop_softc[unit];
518 volatile register siop_regmap_t *regs =
519 (siop_regmap_t *)dev->sc_ac->amiga_addr;
520 u_int i, s;
521 u_char my_id, csr;
522
523 if (dev->sc_flags & SIOP_ALIVE)
524 siopabort(dev, regs, "reset");
525
526 printf("siop%d: ", unit);
527
528 s = splbio();
529 my_id = 7;
530
531 /*
532 * Reset the chip
533 * XXX - is this really needed?
534 */
535 regs->siop_sien &= ~SIOP_SIEN_RST;
536 regs->siop_scntl1 |= SIOP_SCNTL1_RST;
537 for (i = 0; i < 1000; ++i)
538 ;
539 regs->siop_scntl1 &= ~SIOP_SCNTL1_RST;
540 regs->siop_sien |= SIOP_SIEN_RST;
541
542 /*
543 * Set up various chip parameters
544 */
545 regs->siop_istat = 0x40;
546 for (i = 0; i < 1000; ++i)
547 ;
548 regs->siop_istat = 0x00;
549 regs->siop_scntl0 = SIOP_ARB_FULL | SIOP_SCNTL0_EPC | SIOP_SCNTL0_EPG;
550 regs->siop_dcntl = dev->sc_clock_freq;
551 regs->siop_dmode = 0x80;
552 regs->siop_sien = 0x00; /* don't enable interrupts yet */
553 regs->siop_dien = 0x00; /* don't enable interrupts yet */
554 regs->siop_scid = 1 << my_id;
555 regs->siop_dwt = 0x00;
556 regs->siop_ctest0 |= 0x20; /* Enable Active Negation ?? */
557 regs->siop_ctest7 |= 0x02; /* TT1 */
558
559 /* will need to re-negotiate sync xfers */
560 bzero(&dev->sc_sync, sizeof (dev->sc_sync));
561
562 splx (s);
563
564 printf("siop id %d\n", my_id);
565 dev->sc_flags |= SIOP_ALIVE;
566 dev->sc_flags &= ~(SIOP_SELECTED | SIOP_DMA);
567 }
568
569 /*
570 * Setup Data Storage for 53C710 and start SCRIPTS processing
571 */
572
573 static void
574 siop_setup (dev, target, cbuf, clen, buf, len)
575 struct siop_softc *dev;
576 int target;
577 u_char *cbuf;
578 int clen;
579 u_char *buf;
580 int len;
581 {
582 volatile register siop_regmap_t *regs =
583 (siop_regmap_t *)dev->sc_ac->amiga_addr;
584 int i;
585 int nchain;
586 int count, tcount;
587 char *addr, *dmaend;
588
589 dev->sc_istat = 0;
590 dev->sc_lun = 0x80; /* XXX */
591 dev->sc_stat[0] = -1;
592 dev->sc_msg[0] = -1;
593 dev->sc_ds.scsi_addr = (0x10000 << target) | (dev->sc_sync[target].period << 8);
594 dev->sc_ds.idlen = 1;
595 dev->sc_ds.idbuf = (char *) kvtop(&dev->sc_lun);
596 dev->sc_ds.cmdlen = clen;
597 dev->sc_ds.cmdbuf = (char *) kvtop(cbuf);
598 dev->sc_ds.stslen = 1;
599 dev->sc_ds.stsbuf = (char *) kvtop(&dev->sc_stat[0]);
600 dev->sc_ds.msglen = 1;
601 dev->sc_ds.msgbuf = (char *) kvtop(&dev->sc_msg[0]);
602 dev->sc_ds.sdtrolen = 0;
603 dev->sc_ds.sdtrilen = 0;
604 dev->sc_ds.chain[0].datalen = len;
605 dev->sc_ds.chain[0].databuf = (char *) kvtop(buf);
606
607 if (dev->sc_sync[target].state == SYNC_START) {
608 if (siop_inhibit_sync[dev->sc_ac->amiga_unit][target]) {
609 dev->sc_sync[target].state = SYNC_DONE;
610 dev->sc_sync[target].offset = 0;
611 dev->sc_sync[target].period = 0;
612 #ifdef DEBUG
613 if (siopsync_debug)
614 printf ("Forcing target %d asynchronous\n", target);
615 #endif
616 }
617 else {
618 dev->sc_msg[1] = MSG_IDENTIFY;
619 dev->sc_msg[2] = MSG_EXT_MESSAGE;
620 dev->sc_msg[3] = 3;
621 dev->sc_msg[4] = MSG_SYNC_REQ;
622 dev->sc_msg[5] = 100/4; /* min period = 100 nsec */
623 dev->sc_msg[6] = SIOP_MAX_OFFSET;
624 dev->sc_ds.sdtrolen = 6;
625 dev->sc_ds.sdtrilen = sizeof (dev->sc_msg) - 1;
626 dev->sc_ds.sdtrobuf = dev->sc_ds.sdtribuf = (char *) kvtop(dev->sc_msg + 1);
627 dev->sc_sync[target].state = SYNC_SENT;
628 #ifdef DEBUG
629 if (siopsync_debug)
630 printf ("Sending sync request to target %d\n", target);
631 #endif
632 }
633 }
634
635 /*
636 * If length is > 1 page, check for consecutive physical pages
637 * Need to set up chaining if not
638 */
639 nchain = 0;
640 count = len;
641 addr = buf;
642 dmaend = NULL;
643 while (count > 0) {
644 dev->sc_ds.chain[nchain].databuf = (char *) kvtop (addr);
645 if (count < (tcount = NBPG - ((int) addr & PGOFSET)))
646 tcount = count;
647 dev->sc_ds.chain[nchain].datalen = tcount;
648 addr += tcount;
649 count -= tcount;
650 if (dev->sc_ds.chain[nchain].databuf == dmaend) {
651 dmaend += dev->sc_ds.chain[nchain].datalen;
652 dev->sc_ds.chain[--nchain].datalen += tcount;
653 #ifdef DEBUG
654 ++siopdma_hits;
655 #endif
656 }
657 else {
658 dmaend = dev->sc_ds.chain[nchain].databuf +
659 dev->sc_ds.chain[nchain].datalen;
660 dev->sc_ds.chain[nchain].datalen = tcount;
661 #ifdef DEBUG
662 ++siopdma_misses;
663 #endif
664 }
665 ++nchain;
666 }
667 #ifdef DEBUG
668 if (nchain != 1 && len != 0 && siop_debug & 3) {
669 printf ("DMA chaining set: %d\n", nchain);
670 for (i = 0; i < nchain; ++i) {
671 printf (" [%d] %8x %4x\n", i, dev->sc_ds.chain[i].databuf,
672 dev->sc_ds.chain[i].datalen);
673 }
674 }
675 #endif
676
677 regs->siop_sbcl = dev->sc_sync[target].offset;
678 if (dev->sc_ds.sdtrolen)
679 regs->siop_scratch = regs->siop_scratch | 0x100;
680 else
681 regs->siop_scratch = regs->siop_scratch & ~0xff00;
682 regs->siop_dsa = (long) kvtop(&dev->sc_ds);
683 DCIS(); /* push data cache */
684 regs->siop_dsp = (long) kvtop(scripts);
685 }
686
687 /*
688 * Process a DMA or SCSI interrupt from the 53C710 SIOP
689 */
690
691 static int
692 siop_checkintr(dev, istat, dstat, sstat0, status)
693 struct siop_softc *dev;
694 u_char istat;
695 u_char dstat;
696 u_char sstat0;
697 int *status;
698 {
699 volatile register siop_regmap_t *regs =
700 (siop_regmap_t *)dev->sc_ac->amiga_addr;
701 int target;
702
703 regs->siop_ctest8 |= 0x04;
704 while ((regs->siop_ctest1 & SIOP_CTEST1_FMT) == 0)
705 ;
706 regs->siop_ctest8 &= ~0x04;
707 #ifdef DEBUG
708 if (siop_debug & 1) {
709 DCIAS(kvtop(&dev->sc_stat)); /* XXX */
710 printf ("siopchkintr: istat %x dstat %x sstat0 %x dsps %x sbcl %x sts %x msg %x\n",
711 istat, dstat, sstat0, regs->siop_dsps, regs->siop_sbcl, dev->sc_stat[0], dev->sc_msg[0]);
712 }
713 #endif
714 if (dstat & SIOP_DSTAT_SIR && (regs->siop_dsps == 0xff00 ||
715 regs->siop_dsps == 0xfffc)) {
716 /* Normal completion status, or check condition */
717 if (regs->siop_dsa != (long) kvtop(&dev->sc_ds)) {
718 printf ("siop: invalid dsa: %x %x\n", regs->siop_dsa,
719 kvtop(&dev->sc_ds));
720 panic("*** siop DSA invalid ***");
721 }
722 target = dev->sc_slave;
723 if (dev->sc_sync[target].state == SYNC_SENT) {
724 #ifdef DEBUG
725 if (siopsync_debug)
726 printf ("sync msg in: %02x %02x %02x %02x %02x %02x\n",
727 dev->sc_msg[1], dev->sc_msg[2], dev->sc_msg[3],
728 dev->sc_msg[4], dev->sc_msg[5], dev->sc_msg[6]);
729 #endif
730 dev->sc_sync[target].state = SYNC_DONE;
731 dev->sc_sync[target].period = 0;
732 dev->sc_sync[target].offset = 0;
733 if (dev->sc_msg[1] == MSG_EXT_MESSAGE &&
734 dev->sc_msg[2] == 3 &&
735 dev->sc_msg[3] == MSG_SYNC_REQ) {
736 printf ("siop%d: target %d now synchronous, period=%dns, offset=%d\n",
737 dev->sc_ac->amiga_unit, target,
738 dev->sc_msg[4] * 4, dev->sc_msg[5]);
739 scsi_period_to_siop (dev, target);
740 }
741 }
742 DCIAS(kvtop(&dev->sc_stat)); /* XXX */
743 *status = dev->sc_stat[0];
744 return 1;
745 }
746 if (sstat0 & SIOP_SSTAT0_M_A) { /* Phase mismatch */
747 #ifdef DEBUG
748 if (siop_debug & 9)
749 printf ("Phase mismatch: %x dsp +%x\n", regs->siop_sbcl,
750 regs->siop_dsp - kvtop(scripts));
751 #endif
752 if ((regs->siop_sbcl & SIOP_REQ) == 0)
753 printf ("Phase mismatch: REQ not asserted! %02x\n",
754 regs->siop_sbcl);
755 switch (regs->siop_sbcl & 7) {
756 /*
757 * For data out and data in phase, check for DMA chaining
758 */
759
760 /*
761 * for message in, check for possible reject for sync request
762 */
763 case 0:
764 regs->siop_dsp = kvtop(scripts) + Ent_dataout;
765 break;
766 case 1:
767 regs->siop_dsp = kvtop(scripts) + Ent_datain;
768 break;
769 case 2:
770 regs->siop_dsp = kvtop(scripts) + Ent_cmd;
771 break;
772 case 3:
773 regs->siop_dsp = kvtop(scripts) + Ent_status;
774 break;
775 case 6:
776 regs->siop_dsp = kvtop(scripts) + Ent_msgout;
777 break;
778 case 7:
779 regs->siop_dsp = kvtop(scripts) + Ent_msgin;
780 break;
781 default:
782 goto bad_phase;
783 }
784 return 0;
785 }
786 if (sstat0 & SIOP_SSTAT0_STO) { /* Select timed out */
787 *status = -1;
788 return 1;
789 }
790 if (dstat & SIOP_DSTAT_SIR && regs->siop_dsps == 0xff05 &&
791 (regs->siop_sbcl & (SIOP_MSG | SIOP_CD)) == 0) {
792 printf ("DMA chaining failed\n");
793 siopreset (dev->sc_ac->amiga_unit);
794 *status = -1;
795 return 1;
796 }
797 if (dstat & SIOP_DSTAT_SIR && regs->siop_dsps == 0xff27) {
798 #ifdef DEBUG
799 if (siop_debug & 3)
800 printf ("DMA chaining completed: dsa %x dnad %x addr %x\n",
801 regs->siop_dsa, regs->siop_dnad, regs->siop_addr);
802 #endif
803 regs->siop_dsa = kvtop (&dev->sc_ds);
804 regs->siop_dsp = kvtop (scripts) + Ent_status;
805 return 0;
806 }
807 target = dev->sc_slave;
808 if (dstat & SIOP_DSTAT_SIR && regs->siop_dsps == 0xff26 &&
809 dev->sc_msg[0] == MSG_REJECT && dev->sc_sync[target].state == SYNC_SENT) {
810 dev->sc_sync[target].state = SYNC_DONE;
811 dev->sc_sync[target].period = 0;
812 dev->sc_sync[target].offset = 0;
813 dev->sc_ds.sdtrolen = 0;
814 dev->sc_ds.sdtrilen = 0;
815 #ifdef DEBUG
816 if (siopsync_debug || 1)
817 printf ("target %d rejected sync, going asynchronous\n", target);
818 #endif
819 siop_inhibit_sync[dev->sc_ac->amiga_unit][target] = -1;
820 if ((regs->siop_sbcl & 7) == 6) {
821 regs->siop_dsp = kvtop(scripts) + Ent_msgout;
822 return (0);
823 }
824 }
825 if (sstat0 == 0 && dstat & SIOP_DSTAT_SIR) {
826 DCIAS(kvtop(&dev->sc_stat));
827 printf ("SIOP interrupt: %x sts %x msg %x sbcl %x\n",
828 regs->siop_dsps, dev->sc_stat[0], dev->sc_msg[0],
829 regs->siop_sbcl);
830 siopreset (dev->sc_ac->amiga_unit);
831 *status = -1;
832 return 1;
833 }
834 bad_phase:
835 /*
836 * temporary panic for unhandled conditions
837 * displays various things about the 53C710 status and registers
838 * then panics
839 */
840 printf ("siopchkintr: target %x ds %x\n", target, &dev->sc_ds);
841 printf ("scripts %x ds %x regs %x dsp %x dcmd %x\n", kvtop(scripts),
842 kvtop(&dev->sc_ds), kvtop(regs), regs->siop_dsp, *((long *)®s->siop_dcmd));
843 printf ("siopchkintr: istat %x dstat %x sstat0 %x dsps %x dsa %x sbcl %x sts %x msg %x\n",
844 istat, dstat, sstat0, regs->siop_dsps, regs->siop_dsa, regs->siop_sbcl,
845 dev->sc_stat[0], dev->sc_msg[0]);
846 panic("siopchkintr: **** temp ****");
847 }
848
849 /*
850 * SCSI 'immediate' command: issue a command to some SCSI device
851 * and get back an 'immediate' response (i.e., do programmed xfer
852 * to get the response data). 'cbuf' is a buffer containing a scsi
853 * command of length clen bytes. 'buf' is a buffer of length 'len'
854 * bytes for data. The transfer direction is determined by the device
855 * (i.e., by the scsi bus data xfer phase). If 'len' is zero, the
856 * command must supply no data. 'xferphase' is the bus phase the
857 * caller expects to happen after the command is issued. It should
858 * be one of DATA_IN_PHASE, DATA_OUT_PHASE or STATUS_PHASE.
859 *
860 * XXX - 53C710 will use DMA, but no interrupts (it's a heck of a
861 * lot easier to do than to use programmed I/O).
862 *
863 */
864 static int
865 siopicmd(dev, target, cbuf, clen, buf, len)
866 struct siop_softc *dev;
867 int target;
868 u_char *cbuf;
869 int clen;
870 u_char *buf;
871 int len;
872 {
873 volatile register siop_regmap_t *regs =
874 (siop_regmap_t *)dev->sc_ac->amiga_addr;
875 int i;
876 int status;
877 u_char istat;
878 u_char dstat;
879 u_char sstat0;
880
881 if (dev->sc_flags & SIOP_SELECTED) {
882 printf ("siopicmd%d: bus busy\n", target);
883 return -1;
884 }
885 regs->siop_sien = 0x00; /* disable SCSI and DMA interrupts */
886 regs->siop_dien = 0x00;
887 dev->sc_flags |= SIOP_SELECTED;
888 dev->sc_slave = target;
889 #ifdef DEBUG
890 if (siop_debug & 1)
891 printf ("siopicmd: target %x cmd %02x ds %x\n", target,
892 cbuf[0], &dev->sc_ds);
893 #endif
894 siop_setup (dev, target, cbuf, clen, buf, len);
895
896 for (;;) {
897 /* use cmd_wait values? */
898 i = siop_cmd_wait << 1;
899 while (((istat = regs->siop_istat) &
900 (SIOP_ISTAT_SIP | SIOP_ISTAT_DIP)) == 0) {
901 if (--i <= 0) {
902 printf ("waiting: tgt %d cmd %02x sbcl %02x dsp %x (+%x) dcmd %x ds %x\n",
903 target, cbuf[0],
904 regs->siop_sbcl, regs->siop_dsp,
905 regs->siop_dsp - kvtop(scripts),
906 *((long *)®s->siop_dcmd), &dev->sc_ds);
907 i = siop_cmd_wait << 2;
908 }
909 DELAY(1);
910 }
911 dstat = regs->siop_dstat;
912 sstat0 = regs->siop_sstat0;
913 #ifdef DEBUG
914 if (siop_debug & 1) {
915 DCIAS(kvtop(&dev->sc_stat)); /* XXX should just invalidate dev->sc_stat */
916 printf ("siopicmd: istat %x dstat %x sstat0 %x dsps %x sbcl %x sts %x msg %x\n",
917 istat, dstat, sstat0, regs->siop_dsps, regs->siop_sbcl,
918 dev->sc_stat[0], dev->sc_msg[0]);
919 }
920 #endif
921 if (siop_checkintr(dev, istat, dstat, sstat0, &status)) {
922 dev->sc_flags &= ~SIOP_SELECTED;
923 return (status);
924 }
925 }
926 }
927
928 int
929 siop_test_unit_rdy(ctlr, slave, unit)
930 int ctlr, slave, unit;
931 {
932 register struct siop_softc *dev = &siop_softc[ctlr];
933 static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
934
935 cdb.lun = unit;
936 return (siopicmd(dev, slave, (u_char *)&cdb, sizeof(cdb), (u_char *)0, 0));
937 }
938
939 int
940 siop_start_stop_unit (ctlr, slave, unit, start)
941 int ctlr, slave, unit;
942 {
943 register struct siop_softc *dev = &siop_softc[ctlr];
944 static struct scsi_cdb6 cdb = { CMD_LOADUNLOAD };
945
946 cdb.lun = unit;
947 /* we don't set the immediate bit, so we wait for the
948 command to succeed.
949 We also don't touch the LoEj bit, which is primarily meant
950 for floppies. */
951 cdb.len = start & 0x01;
952 return (siopicmd(dev, slave, (u_char *)&cdb, sizeof(cdb), (u_char *)0, 0));
953 }
954
955
956 int
957 siop_request_sense(ctlr, slave, unit, buf, len)
958 int ctlr, slave, unit;
959 u_char *buf;
960 unsigned len;
961 {
962 register struct siop_softc *dev = &siop_softc[ctlr];
963 static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE };
964
965 cdb.lun = unit;
966 cdb.len = len;
967 return (siopicmd(dev, slave, (u_char *)&cdb, sizeof(cdb), buf, len));
968 }
969
970 int
971 siop_immed_command(ctlr, slave, unit, cdb, buf, len, rd)
972 int ctlr, slave, unit;
973 struct scsi_fmt_cdb *cdb;
974 u_char *buf;
975 unsigned len;
976 {
977 register struct siop_softc *dev = &siop_softc[ctlr];
978
979 cdb->cdb[1] |= (unit << 5);
980 return (siopicmd(dev, slave, (u_char *) cdb->cdb, cdb->len, buf, len));
981 }
982
983 /*
984 * The following routines are test-and-transfer i/o versions of read/write
985 * for things like reading disk labels and writing core dumps. The
986 * routine scsigo should be used for normal data transfers, NOT these
987 * routines.
988 */
989 int
990 siop_tt_read(ctlr, slave, unit, buf, len, blk, bshift)
991 int ctlr, slave, unit;
992 u_char *buf;
993 u_int len;
994 daddr_t blk;
995 int bshift;
996 {
997 register struct siop_softc *dev = &siop_softc[ctlr];
998 struct scsi_cdb10 cdb;
999 int stat;
1000 int old_wait = siop_data_wait;
1001
1002 #ifdef DEBUG
1003 if (siop_debug & 1)
1004 printf ("siop%d: tt_read blk %x\n", slave, blk);
1005 #endif
1006 siop_data_wait = 300000;
1007 bzero(&cdb, sizeof(cdb));
1008 cdb.cmd = CMD_READ_EXT;
1009 cdb.lun = unit;
1010 blk >>= bshift;
1011 cdb.lbah = blk >> 24;
1012 cdb.lbahm = blk >> 16;
1013 cdb.lbalm = blk >> 8;
1014 cdb.lbal = blk;
1015 cdb.lenh = len >> (8 + DEV_BSHIFT + bshift);
1016 cdb.lenl = len >> (DEV_BSHIFT + bshift);
1017 stat = siopicmd(dev, slave, (u_char *) &cdb, sizeof(cdb), buf, len);
1018 siop_data_wait = old_wait;
1019 return (stat);
1020 }
1021
1022 int
1023 siop_tt_write(ctlr, slave, unit, buf, len, blk, bshift)
1024 int ctlr, slave, unit;
1025 u_char *buf;
1026 u_int len;
1027 daddr_t blk;
1028 int bshift;
1029 {
1030 register struct siop_softc *dev = &siop_softc[ctlr];
1031 struct scsi_cdb10 cdb;
1032 int stat;
1033 int old_wait = siop_data_wait;
1034
1035 #ifdef DEBUG
1036 if (siop_debug)
1037 printf ("siop%d: tt_write blk %d from %08x\n", slave,
1038 blk, kvtop(buf));
1039 if (blk < 604)
1040 panic("siop_tt_write: writing block < 604");
1041 #endif
1042 siop_data_wait = 300000;
1043
1044 bzero(&cdb, sizeof(cdb));
1045 cdb.cmd = CMD_WRITE_EXT;
1046 cdb.lun = unit;
1047 blk >>= bshift;
1048 cdb.lbah = blk >> 24;
1049 cdb.lbahm = blk >> 16;
1050 cdb.lbalm = blk >> 8;
1051 cdb.lbal = blk;
1052 cdb.lenh = len >> (8 + DEV_BSHIFT + bshift);
1053 cdb.lenl = len >> (DEV_BSHIFT + bshift);
1054 stat = siopicmd(dev, slave, (u_char *) &cdb, sizeof(cdb), buf, len);
1055 siop_data_wait = old_wait;
1056 return (stat);
1057 }
1058
1059 int
1060 siopreq(dq)
1061 register struct devqueue *dq;
1062 {
1063 register struct devqueue *hq;
1064
1065 hq = &siop_softc[dq->dq_ctlr].sc_sq;
1066 insque(dq, hq->dq_back);
1067 #ifdef DEBUG
1068 if (siop_debug & 1)
1069 printf ("siopreq %d ", dq->dq_back == hq ? 1 : 0);
1070 #endif
1071 if (dq->dq_back == hq)
1072 return(1);
1073 return(0);
1074 }
1075
1076 int
1077 siopustart (int unit)
1078 {
1079 register struct siop_softc *dev = &siop_softc[unit];
1080
1081 #ifdef DEBUG
1082 if (siop_debug & 1)
1083 printf ("siop%d: ustart ", unit);
1084 #endif
1085 return(1);
1086 }
1087
1088 void
1089 siopstart (int unit)
1090 {
1091 register struct devqueue *dq;
1092
1093 #ifdef DEBUG
1094 if (siop_debug & 1)
1095 printf ("siop%d: start ", unit);
1096 #endif
1097 dq = siop_softc[unit].sc_sq.dq_forw;
1098 (dq->dq_driver->d_go)(dq->dq_unit);
1099 }
1100
1101 int
1102 siopgo(ctlr, slave, unit, bp, cdb, pad)
1103 int ctlr, slave, unit;
1104 struct buf *bp;
1105 struct scsi_fmt_cdb *cdb;
1106 int pad;
1107 {
1108 register struct siop_softc *dev = &siop_softc[ctlr];
1109 volatile register siop_regmap_t *regs =
1110 (siop_regmap_t *)dev->sc_ac->amiga_addr;
1111 int i;
1112 int nchain;
1113 int count, tcount;
1114 char *addr, *dmaend;
1115
1116 #ifdef DEBUG
1117 if (siop_debug & 1)
1118 printf ("siop%d: go ", slave);
1119 if ((cdb->cdb[1] & 1) == 0 &&
1120 ((cdb->cdb[0] == CMD_WRITE && cdb->cdb[2] == 0 && cdb->cdb[3] == 0) ||
1121 (cdb->cdb[0] == CMD_WRITE_EXT && cdb->cdb[2] == 0 && cdb->cdb[3] == 0
1122 && cdb->cdb[4] == 0)))
1123 panic ("siopgo: attempted write to block < 0x100");
1124 #endif
1125 cdb->cdb[1] |= unit << 5;
1126
1127 if (dev->sc_flags & SIOP_SELECTED) {
1128 printf ("siopgo%d: bus busy\n", slave);
1129 return 1;
1130 }
1131
1132 if (siop_no_dma) {
1133 register struct devqueue *dq;
1134
1135 /* in this case do the transfer with programmed I/O :-( This is
1136 probably still faster than doing the transfer with DMA into a
1137 buffer and copying it later to its final destination, comments? */
1138 /* XXX - 53C710 uses DMA, but non-interrupt */
1139 siopicmd (dev, slave, (u_char *) cdb->cdb, cdb->len,
1140 bp->b_un.b_addr, bp->b_bcount);
1141
1142 dq = dev->sc_sq.dq_forw;
1143 (dq->dq_driver->d_intr)(dq->dq_unit, dev->sc_stat[0]);
1144 return dev->sc_stat[0];
1145 }
1146
1147 dev->sc_flags |= SIOP_SELECTED | SIOP_DMA;
1148 dev->sc_slave = slave;
1149 /* enable SCSI and DMA interrupts */
1150 regs->siop_sien = SIOP_SIEN_M_A | SIOP_SIEN_STO | SIOP_SIEN_SEL | SIOP_SIEN_SGE |
1151 SIOP_SIEN_UDC | SIOP_SIEN_RST | SIOP_SIEN_PAR;
1152 regs->siop_dien = 0x20 | SIOP_DIEN_ABRT | SIOP_DIEN_SIR | SIOP_DIEN_WTD |
1153 SIOP_DIEN_OPC;
1154 #ifdef DEBUG
1155 if (siop_debug & 1)
1156 printf ("siopgo: target %x cmd %02x ds %x\n", slave, cdb->cdb[0], &dev->sc_ds);
1157 #endif
1158
1159 siop_setup(dev, slave, cdb->cdb, cdb->len, bp->b_un.b_addr, bp->b_bcount);
1160
1161 return (0);
1162 }
1163
1164 void
1165 siopdone (int unit)
1166 {
1167 volatile register siop_regmap_t *regs =
1168 (siop_regmap_t *)siop_softc[unit].sc_ac->amiga_addr;
1169
1170 #ifdef DEBUG
1171 if (siop_debug & 1)
1172 printf("siop%d: done called!\n", unit);
1173 #endif
1174 }
1175
1176 /*
1177 * Level 6 interrupt processing for the Progressive Peripherals Inc
1178 * Zeus SCSI. Because the level 6 interrupt is above splbio, the
1179 * interrupt status is saved and the INTF_PORTS interrupt is set.
1180 * This way, the actual processing of the interrupt can be deferred
1181 * until splbio is unblocked
1182 */
1183
1184 #if NZEUSSCSI > 0
1185 int
1186 siopintr6 ()
1187 {
1188 register struct siop_softc *dev;
1189 volatile register siop_regmap_t *regs;
1190 register u_char istat;
1191 int unit;
1192 int found = 0;
1193
1194 for (unit = 0, dev = siop_softc; unit < NSIOP; unit++, dev++) {
1195 if (!initialized[dev->sc_ac->amiga_unit])
1196 continue;
1197 if (dev->sc_ac->amiga_ipl != 6)
1198 continue;
1199 regs = (siop_regmap_t *)dev->sc_ac->amiga_addr;
1200 istat = regs->siop_istat;
1201 if ((istat & (SIOP_ISTAT_SIP | SIOP_ISTAT_DIP)) == 0)
1202 continue;
1203 if ((dev->sc_flags & (SIOP_DMA | SIOP_SELECTED)) == SIOP_SELECTED)
1204 continue; /* doing non-interrupt I/O */
1205 found++;
1206 dev->sc_istat = istat;
1207 dev->sc_dstat = regs->siop_dstat;
1208 dev->sc_sstat0 = regs->siop_sstat0;
1209 custom.intreq = INTF_EXTER;
1210 custom.intreq = INTF_SETCLR | INTF_PORTS;
1211 }
1212 return (found);
1213 }
1214 #endif
1215
1216 /*
1217 * Check for 53C710 interrupts
1218 */
1219
1220 int
1221 siopintr2 ()
1222 {
1223 register struct siop_softc *dev;
1224 volatile register siop_regmap_t *regs;
1225 register u_char istat, dstat, sstat0;
1226 register struct devqueue *dq;
1227 int unit;
1228 int status;
1229 int found = 0;
1230
1231 for (unit = 0, dev = siop_softc; unit < NSIOP; unit++, dev++) {
1232 if (!initialized[dev->sc_ac->amiga_unit])
1233 continue;
1234 regs = (siop_regmap_t *)dev->sc_ac->amiga_addr;
1235 if (dev->sc_ac->amiga_ipl == 6)
1236 istat = dev->sc_istat;
1237 else
1238 istat = regs->siop_istat;
1239 if ((istat & (SIOP_ISTAT_SIP | SIOP_ISTAT_DIP)) == 0)
1240 continue;
1241 if ((dev->sc_flags & (SIOP_DMA | SIOP_SELECTED)) == SIOP_SELECTED)
1242 continue; /* doing non-interrupt I/O */
1243 /* Got a valid interrupt on this device */
1244 found++;
1245 if (dev->sc_ac->amiga_ipl == 6) {
1246 dstat = dev->sc_dstat;
1247 sstat0 = dev->sc_sstat0;
1248 dev->sc_istat = 0;
1249 }
1250 else {
1251 dstat = regs->siop_dstat;
1252 sstat0 = regs->siop_sstat0;
1253 }
1254 #ifdef DEBUG
1255 if (siop_debug & 1)
1256 printf ("siop%d: intr istat %x dstat %x sstat0 %x\n",
1257 unit, istat, dstat, sstat0);
1258 if ((dev->sc_flags & SIOP_DMA) == 0) {
1259 printf ("siop%d: spurious interrupt? istat %x dstat %x sstat0 %x\n",
1260 unit, istat, dstat, sstat0);
1261 }
1262 #endif
1263
1264 #ifdef DEBUG
1265 if (siop_debug & 5) {
1266 DCIAS(kvtop(&dev->sc_stat));
1267 printf ("siopintr%d: istat %x dstat %x sstat0 %x dsps %x sbcl %x sts %x msg %x\n",
1268 unit, istat, dstat, sstat0, regs->siop_dsps,
1269 regs->siop_sbcl, dev->sc_stat[0], dev->sc_msg[0]);
1270 }
1271 #endif
1272 if (siop_checkintr (dev, istat, dstat, sstat0, &status)) {
1273 #if 1
1274 regs->siop_sien = 0;
1275 regs->siop_dien = 0;
1276 if (status == 0xff)
1277 printf ("siopintr: status == 0xff\n");
1278 #endif
1279 dev->sc_flags &= ~(SIOP_DMA | SIOP_SELECTED);
1280 dq = dev->sc_sq.dq_forw;
1281 (dq->dq_driver->d_intr)(dq->dq_unit, status);
1282 }
1283 }
1284 return (found);
1285 }
1286
1287 void
1288 siopfree(dq)
1289 register struct devqueue *dq;
1290 {
1291 register struct devqueue *hq;
1292
1293 #ifdef DEBUG
1294 if (siop_debug & 1)
1295 printf ("siopfree\n");
1296 #endif
1297 hq = &siop_softc[dq->dq_ctlr].sc_sq;
1298 remque(dq);
1299 if ((dq = hq->dq_forw) != hq)
1300 (dq->dq_driver->d_start)(dq->dq_unit);
1301 }
1302
1303 /*
1304 * (XXX) The following routine is needed for the SCSI tape driver
1305 * to read odd-size records.
1306 */
1307
1308 /* XXX - probably not needed for the 53C710 (and not implemented yet!) */
1309
1310 #if NST > 0
1311 int
1312 siop_tt_oddio(ctlr, slave, unit, buf, len, b_flags, freedma)
1313 int ctlr, slave, unit, b_flags;
1314 u_char *buf;
1315 u_int len;
1316 {
1317 register struct siop_softc *dev = &siop_softc[ctlr];
1318 struct scsi_cdb6 cdb;
1319 u_char iphase;
1320 int stat;
1321
1322 printf ("siop%d: tt_oddio\n", slave);
1323 #if 0
1324 /*
1325 * First free any DMA channel that was allocated.
1326 * We can't use DMA to do this transfer.
1327 */
1328 if (freedma)
1329 dev->dmafree(&dev->sc_dq);
1330 /*
1331 * Initialize command block
1332 */
1333 bzero(&cdb, sizeof(cdb));
1334 cdb.lun = unit;
1335 cdb.lbam = (len >> 16) & 0xff;
1336 cdb.lbal = (len >> 8) & 0xff;
1337 cdb.len = len & 0xff;
1338 if (buf == 0) {
1339 cdb.cmd = CMD_SPACE;
1340 cdb.lun |= 0x00;
1341 len = 0;
1342 iphase = MESG_IN_PHASE;
1343 } else if (b_flags & B_READ) {
1344 cdb.cmd = CMD_READ;
1345 iphase = DATA_IN_PHASE;
1346 } else {
1347 cdb.cmd = CMD_WRITE;
1348 iphase = DATA_OUT_PHASE;
1349 }
1350 /*
1351 * Perform command (with very long delays)
1352 */
1353 scsi_delay(30000000);
1354 stat = siopicmd(dev, slave, (u_char *) &cdb, sizeof(cdb), buf, len, iphase);
1355 scsi_delay(0);
1356 return (stat);
1357 #endif
1358 return -1;
1359 }
1360 #endif
1361 #endif
1362