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