esiop.c revision 1.11 1 /* $NetBSD: esiop.c,v 1.11 2002/04/27 17:39:51 bouyer Exp $ */
2
3 /*
4 * Copyright (c) 2002 Manuel Bouyer.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Manuel Bouyer.
17 * 4. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 *
31 */
32
33 /* SYM53c7/8xx PCI-SCSI I/O Processors driver */
34
35 #include <sys/cdefs.h>
36 __KERNEL_RCSID(0, "$NetBSD: esiop.c,v 1.11 2002/04/27 17:39:51 bouyer Exp $");
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/device.h>
41 #include <sys/malloc.h>
42 #include <sys/buf.h>
43 #include <sys/kernel.h>
44
45 #include <uvm/uvm_extern.h>
46
47 #include <machine/endian.h>
48 #include <machine/bus.h>
49
50 #include <dev/microcode/siop/esiop.out>
51
52 #include <dev/scsipi/scsi_all.h>
53 #include <dev/scsipi/scsi_message.h>
54 #include <dev/scsipi/scsipi_all.h>
55
56 #include <dev/scsipi/scsiconf.h>
57
58 #include <dev/ic/siopreg.h>
59 #include <dev/ic/siopvar_common.h>
60 #include <dev/ic/esiopvar.h>
61
62 #include "opt_siop.h"
63
64 #ifndef DEBUG
65 #undef DEBUG
66 #endif
67 #undef SIOP_DEBUG
68 #undef SIOP_DEBUG_DR
69 #undef SIOP_DEBUG_INTR
70 #undef SIOP_DEBUG_SCHED
71 #undef DUMP_SCRIPT
72
73 #define SIOP_STATS
74
75 #ifndef SIOP_DEFAULT_TARGET
76 #define SIOP_DEFAULT_TARGET 7
77 #endif
78
79 /* number of cmd descriptors per block */
80 #define SIOP_NCMDPB (PAGE_SIZE / sizeof(struct esiop_xfer))
81
82 void esiop_reset __P((struct esiop_softc *));
83 void esiop_checkdone __P((struct esiop_softc *));
84 void esiop_handle_reset __P((struct esiop_softc *));
85 void esiop_scsicmd_end __P((struct esiop_cmd *));
86 void esiop_unqueue __P((struct esiop_softc *, int, int));
87 int esiop_handle_qtag_reject __P((struct esiop_cmd *));
88 static void esiop_start __P((struct esiop_softc *, struct esiop_cmd *));
89 void esiop_timeout __P((void *));
90 int esiop_scsicmd __P((struct scsipi_xfer *));
91 void esiop_scsipi_request __P((struct scsipi_channel *,
92 scsipi_adapter_req_t, void *));
93 void esiop_dump_script __P((struct esiop_softc *));
94 void esiop_morecbd __P((struct esiop_softc *));
95 void esiop_moretagtbl __P((struct esiop_softc *));
96 void siop_add_reselsw __P((struct esiop_softc *, int));
97 void esiop_target_register __P((struct esiop_softc *, u_int32_t));
98
99 void esiop_update_scntl3 __P((struct esiop_softc *,
100 struct siop_common_target *));
101
102 #ifdef SIOP_STATS
103 static int esiop_stat_intr = 0;
104 static int esiop_stat_intr_shortxfer = 0;
105 static int esiop_stat_intr_sdp = 0;
106 static int esiop_stat_intr_done = 0;
107 static int esiop_stat_intr_xferdisc = 0;
108 static int esiop_stat_intr_lunresel = 0;
109 static int esiop_stat_intr_qfull = 0;
110 void esiop_printstats __P((void));
111 #define INCSTAT(x) x++
112 #else
113 #define INCSTAT(x)
114 #endif
115
116 static __inline__ void esiop_script_sync __P((struct esiop_softc *, int));
117 static __inline__ void
118 esiop_script_sync(sc, ops)
119 struct esiop_softc *sc;
120 int ops;
121 {
122 if ((sc->sc_c.features & SF_CHIP_RAM) == 0)
123 bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,
124 PAGE_SIZE, ops);
125 }
126
127 static __inline__ u_int32_t esiop_script_read __P((struct esiop_softc *, u_int));
128 static __inline__ u_int32_t
129 esiop_script_read(sc, offset)
130 struct esiop_softc *sc;
131 u_int offset;
132 {
133 if (sc->sc_c.features & SF_CHIP_RAM) {
134 return bus_space_read_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
135 offset * 4);
136 } else {
137 return le32toh(sc->sc_c.sc_script[offset]);
138 }
139 }
140
141 static __inline__ void esiop_script_write __P((struct esiop_softc *, u_int,
142 u_int32_t));
143 static __inline__ void
144 esiop_script_write(sc, offset, val)
145 struct esiop_softc *sc;
146 u_int offset;
147 u_int32_t val;
148 {
149 if (sc->sc_c.features & SF_CHIP_RAM) {
150 bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
151 offset * 4, val);
152 } else {
153 sc->sc_c.sc_script[offset] = htole32(val);
154 }
155 }
156
157 void
158 esiop_attach(sc)
159 struct esiop_softc *sc;
160 {
161 struct esiop_dsatbl *tagtbl_donering;
162
163 if (siop_common_attach(&sc->sc_c) != 0 )
164 return;
165
166 TAILQ_INIT(&sc->free_list);
167 TAILQ_INIT(&sc->cmds);
168 TAILQ_INIT(&sc->free_tagtbl);
169 TAILQ_INIT(&sc->tag_tblblk);
170 sc->sc_currschedslot = 0;
171 #ifdef SIOP_DEBUG
172 printf("%s: script size = %d, PHY addr=0x%x, VIRT=%p\n",
173 sc->sc_c.sc_dev.dv_xname, (int)sizeof(esiop_script),
174 (u_int32_t)sc->sc_c.sc_scriptaddr, sc->sc_c.sc_script);
175 #endif
176
177 sc->sc_c.sc_adapt.adapt_max_periph = ESIOP_NTAG;
178 sc->sc_c.sc_adapt.adapt_request = esiop_scsipi_request;
179
180 /*
181 * get space for the CMD done slot. For this we use a tag table entry.
182 * It's the same size and allows us to not waste 3/4 of a page
183 */
184 #ifdef DIAGNOSTIC
185 if (ESIOP_NTAG != A_ndone_slots) {
186 printf("%s: size of tag DSA table different from the done"
187 "ring\n", sc->sc_c.sc_dev.dv_xname);
188 return;
189 }
190 #endif
191 esiop_moretagtbl(sc);
192 tagtbl_donering = TAILQ_FIRST(&sc->free_tagtbl);
193 if (tagtbl_donering == NULL) {
194 printf("%s: no memory for command done ring\n",
195 "ring\n", sc->sc_c.sc_dev.dv_xname);
196 return;
197 }
198 TAILQ_REMOVE(&sc->free_tagtbl, tagtbl_donering, next);
199 sc->sc_done_map = tagtbl_donering->tblblk->blkmap;
200 sc->sc_done_offset = tagtbl_donering->tbl_offset;
201 sc->sc_done_slot = &tagtbl_donering->tbl[0];
202
203 /* Do a bus reset, so that devices fall back to narrow/async */
204 siop_resetbus(&sc->sc_c);
205 /*
206 * siop_reset() will reset the chip, thus clearing pending interrupts
207 */
208 esiop_reset(sc);
209 #ifdef DUMP_SCRIPT
210 esiop_dump_script(sc);
211 #endif
212
213 config_found((struct device*)sc, &sc->sc_c.sc_chan, scsiprint);
214 }
215
216 void
217 esiop_reset(sc)
218 struct esiop_softc *sc;
219 {
220 int i, j;
221 u_int32_t addr;
222 u_int32_t msgin_addr;
223
224 siop_common_reset(&sc->sc_c);
225
226 /*
227 * we copy the script at the beggining of RAM. Then there is 8 bytes
228 * for messages in.
229 */
230 sc->sc_free_offset = sizeof(esiop_script) / sizeof(esiop_script[0]);
231 msgin_addr =
232 sc->sc_free_offset * sizeof(u_int32_t) + sc->sc_c.sc_scriptaddr;
233 sc->sc_free_offset += 2;
234 /* then we have the scheduler ring */
235 sc->sc_shedoffset = sc->sc_free_offset;
236 sc->sc_free_offset += A_ncmd_slots * CMD_SLOTSIZE;
237 /* then the targets DSA table */
238 sc->sc_target_table_offset = sc->sc_free_offset;
239 sc->sc_free_offset += sc->sc_c.sc_chan.chan_ntargets;
240 /* copy and patch the script */
241 if (sc->sc_c.features & SF_CHIP_RAM) {
242 bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 0,
243 esiop_script,
244 sizeof(esiop_script) / sizeof(esiop_script[0]));
245 for (j = 0; j <
246 (sizeof(E_tlq_offset_Used) / sizeof(E_tlq_offset_Used[0]));
247 j++) {
248 bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
249 E_tlq_offset_Used[j] * 4,
250 sizeof(struct siop_common_xfer));
251 }
252 for (j = 0; j <
253 (sizeof(E_abs_msgin2_Used) / sizeof(E_abs_msgin2_Used[0]));
254 j++) {
255 bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
256 E_abs_msgin2_Used[j] * 4, msgin_addr);
257 }
258
259 if (sc->sc_c.features & SF_CHIP_LED0) {
260 bus_space_write_region_4(sc->sc_c.sc_ramt,
261 sc->sc_c.sc_ramh,
262 Ent_led_on1, esiop_led_on,
263 sizeof(esiop_led_on) / sizeof(esiop_led_on[0]));
264 bus_space_write_region_4(sc->sc_c.sc_ramt,
265 sc->sc_c.sc_ramh,
266 Ent_led_on2, esiop_led_on,
267 sizeof(esiop_led_on) / sizeof(esiop_led_on[0]));
268 bus_space_write_region_4(sc->sc_c.sc_ramt,
269 sc->sc_c.sc_ramh,
270 Ent_led_off, esiop_led_off,
271 sizeof(esiop_led_off) / sizeof(esiop_led_off[0]));
272 }
273 } else {
274 for (j = 0;
275 j < (sizeof(esiop_script) / sizeof(esiop_script[0])); j++) {
276 sc->sc_c.sc_script[j] = htole32(esiop_script[j]);
277 }
278 for (j = 0; j <
279 (sizeof(E_tlq_offset_Used) / sizeof(E_tlq_offset_Used[0]));
280 j++) {
281 sc->sc_c.sc_script[E_tlq_offset_Used[j]] =
282 htole32(sizeof(struct siop_common_xfer));
283 }
284 for (j = 0; j <
285 (sizeof(E_abs_msgin2_Used) / sizeof(E_abs_msgin2_Used[0]));
286 j++) {
287 sc->sc_c.sc_script[E_abs_msgin2_Used[j]] =
288 htole32(msgin_addr);
289 }
290
291 if (sc->sc_c.features & SF_CHIP_LED0) {
292 for (j = 0; j < (sizeof(esiop_led_on) /
293 sizeof(esiop_led_on[0])); j++)
294 sc->sc_c.sc_script[
295 Ent_led_on1 / sizeof(esiop_led_on[0]) + j
296 ] = htole32(esiop_led_on[j]);
297 for (j = 0; j < (sizeof(esiop_led_on) /
298 sizeof(esiop_led_on[0])); j++)
299 sc->sc_c.sc_script[
300 Ent_led_on2 / sizeof(esiop_led_on[0]) + j
301 ] = htole32(esiop_led_on[j]);
302 for (j = 0; j < (sizeof(esiop_led_off) /
303 sizeof(esiop_led_off[0])); j++)
304 sc->sc_c.sc_script[
305 Ent_led_off / sizeof(esiop_led_off[0]) + j
306 ] = htole32(esiop_led_off[j]);
307 }
308 }
309 /* get base of scheduler ring */
310 addr = sc->sc_c.sc_scriptaddr + sc->sc_shedoffset * sizeof(u_int32_t);
311 /* init scheduler */
312 for (i = 0; i < A_ncmd_slots; i++) {
313 esiop_script_write(sc,
314 sc->sc_shedoffset + i * CMD_SLOTSIZE, A_f_cmd_free);
315 }
316 sc->sc_currschedslot = 0;
317 bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHE, 0);
318 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHD, addr);
319 /*
320 * 0x78000000 is a 'move data8 to reg'. data8 is the second
321 * octet, reg offset is the third.
322 */
323 esiop_script_write(sc, Ent_cmdr0 / 4,
324 0x78640000 | ((addr & 0x000000ff) << 8));
325 esiop_script_write(sc, Ent_cmdr1 / 4,
326 0x78650000 | ((addr & 0x0000ff00) ));
327 esiop_script_write(sc, Ent_cmdr2 / 4,
328 0x78660000 | ((addr & 0x00ff0000) >> 8));
329 esiop_script_write(sc, Ent_cmdr3 / 4,
330 0x78670000 | ((addr & 0xff000000) >> 16));
331 /* done ring */
332 for (i = 0; i < A_ndone_slots; i++)
333 sc->sc_done_slot[i] = 0;
334 bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_done_map,
335 sc->sc_done_offset, A_ndone_slots * sizeof(u_int32_t),
336 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
337 addr = sc->sc_done_map->dm_segs[0].ds_addr + sc->sc_done_offset;
338 sc->sc_currdoneslot = 0;
339 bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHE + 2, 0);
340 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHF, addr);
341 esiop_script_write(sc, Ent_doner0 / 4,
342 0x786c0000 | ((addr & 0x000000ff) << 8));
343 esiop_script_write(sc, Ent_doner1 / 4,
344 0x786d0000 | ((addr & 0x0000ff00) ));
345 esiop_script_write(sc, Ent_doner2 / 4,
346 0x786e0000 | ((addr & 0x00ff0000) >> 8));
347 esiop_script_write(sc, Ent_doner3 / 4,
348 0x786f0000 | ((addr & 0xff000000) >> 16));
349
350 /* set flags */
351 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_SCRATCHC, 0);
352 /* write pointer of base of target DSA table */
353 addr = (sc->sc_target_table_offset * sizeof(u_int32_t)) +
354 sc->sc_c.sc_scriptaddr;
355 esiop_script_write(sc, (Ent_load_targtable / 4) + 0,
356 esiop_script_read(sc,(Ent_load_targtable / 4) + 0) |
357 ((addr & 0x000000ff) << 8));
358 esiop_script_write(sc, (Ent_load_targtable / 4) + 2,
359 esiop_script_read(sc,(Ent_load_targtable / 4) + 2) |
360 ((addr & 0x0000ff00) ));
361 esiop_script_write(sc, (Ent_load_targtable / 4) + 4,
362 esiop_script_read(sc,(Ent_load_targtable / 4) + 4) |
363 ((addr & 0x00ff0000) >> 8));
364 esiop_script_write(sc, (Ent_load_targtable / 4) + 6,
365 esiop_script_read(sc,(Ent_load_targtable / 4) + 6) |
366 ((addr & 0xff000000) >> 16));
367 #ifdef SIOP_DEBUG
368 printf("%s: target table offset %d free offset %d\n",
369 sc->sc_c.sc_dev.dv_xname, sc->sc_target_table_offset,
370 sc->sc_free_offset);
371 #endif
372
373 /* register existing targets */
374 for (i = 0; i < sc->sc_c.sc_chan.chan_ntargets; i++) {
375 if (sc->sc_c.targets[i])
376 esiop_target_register(sc, i);
377 }
378 /* start script */
379 if ((sc->sc_c.features & SF_CHIP_RAM) == 0) {
380 bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,
381 PAGE_SIZE, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
382 }
383 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP,
384 sc->sc_c.sc_scriptaddr + Ent_reselect);
385 }
386
387 #if 0
388 #define CALL_SCRIPT(ent) do {\
389 printf ("start script DSA 0x%lx DSP 0x%lx\n", \
390 esiop_cmd->cmd_c.dsa, \
391 sc->sc_c.sc_scriptaddr + ent); \
392 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \
393 } while (0)
394 #else
395 #define CALL_SCRIPT(ent) do {\
396 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \
397 } while (0)
398 #endif
399
400 int
401 esiop_intr(v)
402 void *v;
403 {
404 struct esiop_softc *sc = v;
405 struct esiop_target *esiop_target;
406 struct esiop_cmd *esiop_cmd;
407 struct esiop_lun *esiop_lun;
408 struct scsipi_xfer *xs;
409 int istat, sist, sstat1, dstat;
410 u_int32_t irqcode;
411 int need_reset = 0;
412 int offset, target, lun, tag;
413 u_int32_t tflags;
414 u_int32_t addr;
415 int freetarget = 0;
416 int slot;
417 int retval = 0;
418
419 again:
420 istat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT);
421 if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0) {
422 return retval;
423 }
424 retval = 1;
425 INCSTAT(esiop_stat_intr);
426 if (istat & ISTAT_INTF) {
427 bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
428 SIOP_ISTAT, ISTAT_INTF);
429 esiop_checkdone(sc);
430 if (sc->sc_flags & SCF_CHAN_NOSLOT) {
431 /*
432 * at last one command terminated,
433 * so we should have free slots now
434 */
435 sc->sc_flags &= ~SCF_CHAN_NOSLOT;
436 scsipi_channel_thaw(&sc->sc_c.sc_chan, 1);
437 }
438 goto again;
439 }
440
441 if ((istat &(ISTAT_DIP | ISTAT_SIP | ISTAT_ABRT)) ==
442 (ISTAT_DIP | ISTAT_ABRT)) {
443 /* clear abort */
444 bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
445 SIOP_ISTAT, 0);
446 }
447
448 /* get CMD from T/L/Q */
449 tflags = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
450 SIOP_SCRATCHC);
451 #ifdef SIOP_DEBUG_INTR
452 printf("interrupt, istat=0x%x tflags=0x%x "
453 "DSA=0x%x DSP=0x%lx\n", istat, tflags,
454 bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
455 (u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
456 SIOP_DSP) -
457 sc->sc_c.sc_scriptaddr));
458 #endif
459 target = (tflags & A_f_c_target) ? ((tflags >> 8) & 0xff) : -1;
460 if (target > sc->sc_c.sc_chan.chan_ntargets) target = -1;
461 lun = (tflags & A_f_c_lun) ? ((tflags >> 16) & 0xff) : -1;
462 if (lun > sc->sc_c.sc_chan.chan_nluns) lun = -1;
463 tag = (tflags & A_f_c_tag) ? ((tflags >> 24) & 0xff) : -1;
464
465 if (target >= 0 && lun >= 0) {
466 esiop_target = (struct esiop_target *)sc->sc_c.targets[target];
467 if (esiop_target == NULL) {
468 printf("esiop_target (target %d) not valid\n", target);
469 goto none;
470 }
471 esiop_lun = esiop_target->esiop_lun[lun];
472 if (esiop_lun == NULL) {
473 printf("esiop_lun (target %d lun %d) not valid\n",
474 target, lun);
475 goto none;
476 }
477 esiop_cmd =
478 (tag >= 0) ? esiop_lun->tactive[tag] : esiop_lun->active;
479 if (esiop_cmd == NULL) {
480 printf("esiop_cmd (target %d lun %d tag %d) not valid\n",
481 target, lun, tag);
482 goto none;
483 }
484 xs = esiop_cmd->cmd_c.xs;
485 #ifdef DIAGNOSTIC
486 if (esiop_cmd->cmd_c.status != CMDST_ACTIVE) {
487 printf("esiop_cmd (target %d lun %d) "
488 "not active (%d)\n", target, lun,
489 esiop_cmd->cmd_c.status);
490 goto none;
491 }
492 #endif
493 esiop_table_sync(esiop_cmd,
494 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
495 } else {
496 none:
497 xs = NULL;
498 esiop_target = NULL;
499 esiop_lun = NULL;
500 esiop_cmd = NULL;
501 }
502 if (istat & ISTAT_DIP) {
503 dstat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
504 SIOP_DSTAT);
505 if (dstat & DSTAT_ABRT) {
506 /* was probably generated by a bus reset IOCTL */
507 if ((dstat & DSTAT_DFE) == 0)
508 siop_clearfifo(&sc->sc_c);
509 goto reset;
510 }
511 if (dstat & DSTAT_SSI) {
512 printf("single step dsp 0x%08x dsa 0x08%x\n",
513 (int)(bus_space_read_4(sc->sc_c.sc_rt,
514 sc->sc_c.sc_rh, SIOP_DSP) -
515 sc->sc_c.sc_scriptaddr),
516 bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
517 SIOP_DSA));
518 if ((dstat & ~(DSTAT_DFE | DSTAT_SSI)) == 0 &&
519 (istat & ISTAT_SIP) == 0) {
520 bus_space_write_1(sc->sc_c.sc_rt,
521 sc->sc_c.sc_rh, SIOP_DCNTL,
522 bus_space_read_1(sc->sc_c.sc_rt,
523 sc->sc_c.sc_rh, SIOP_DCNTL) | DCNTL_STD);
524 }
525 return 1;
526 }
527
528 if (dstat & ~(DSTAT_SIR | DSTAT_DFE | DSTAT_SSI)) {
529 printf("%s: DMA IRQ:", sc->sc_c.sc_dev.dv_xname);
530 if (dstat & DSTAT_IID)
531 printf(" Illegal instruction");
532 if (dstat & DSTAT_BF)
533 printf(" bus fault");
534 if (dstat & DSTAT_MDPE)
535 printf(" parity");
536 if (dstat & DSTAT_DFE)
537 printf(" dma fifo empty");
538 else
539 siop_clearfifo(&sc->sc_c);
540 printf(", DSP=0x%x DSA=0x%x: ",
541 (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
542 SIOP_DSP) - sc->sc_c.sc_scriptaddr),
543 bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA));
544 if (esiop_cmd)
545 printf("T/L/Q=%d/%d/%d last msg_in=0x%x status=0x%x\n",
546 target, lun, tag, esiop_cmd->cmd_tables->msg_in[0],
547 le32toh(esiop_cmd->cmd_tables->status));
548 else
549 printf(" current T/L/Q invalid\n");
550 need_reset = 1;
551 }
552 }
553 if (istat & ISTAT_SIP) {
554 if (istat & ISTAT_DIP)
555 delay(10);
556 /*
557 * Can't read sist0 & sist1 independantly, or we have to
558 * insert delay
559 */
560 sist = bus_space_read_2(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
561 SIOP_SIST0);
562 sstat1 = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
563 SIOP_SSTAT1);
564 #ifdef SIOP_DEBUG_INTR
565 printf("scsi interrupt, sist=0x%x sstat1=0x%x "
566 "DSA=0x%x DSP=0x%lx\n", sist, sstat1,
567 bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
568 (u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
569 SIOP_DSP) -
570 sc->sc_c.sc_scriptaddr));
571 #endif
572 if (sist & SIST0_RST) {
573 esiop_handle_reset(sc);
574 /* no table to flush here */
575 return 1;
576 }
577 if (sist & SIST0_SGE) {
578 if (esiop_cmd)
579 scsipi_printaddr(xs->xs_periph);
580 else
581 printf("%s:", sc->sc_c.sc_dev.dv_xname);
582 printf("scsi gross error\n");
583 if (esiop_target)
584 esiop_target->target_c.flags &= ~TARF_DT;
585 goto reset;
586 }
587 if ((sist & SIST0_MA) && need_reset == 0) {
588 if (esiop_cmd) {
589 int scratchc0;
590 dstat = bus_space_read_1(sc->sc_c.sc_rt,
591 sc->sc_c.sc_rh, SIOP_DSTAT);
592 /*
593 * first restore DSA, in case we were in a S/G
594 * operation.
595 */
596 bus_space_write_4(sc->sc_c.sc_rt,
597 sc->sc_c.sc_rh,
598 SIOP_DSA, esiop_cmd->cmd_c.dsa);
599 scratchc0 = bus_space_read_1(sc->sc_c.sc_rt,
600 sc->sc_c.sc_rh, SIOP_SCRATCHC);
601 switch (sstat1 & SSTAT1_PHASE_MASK) {
602 case SSTAT1_PHASE_STATUS:
603 /*
604 * previous phase may be aborted for any reason
605 * ( for example, the target has less data to
606 * transfer than requested). Just go to status
607 * and the command should terminate.
608 */
609 INCSTAT(esiop_stat_intr_shortxfer);
610 if ((dstat & DSTAT_DFE) == 0)
611 siop_clearfifo(&sc->sc_c);
612 /* no table to flush here */
613 CALL_SCRIPT(Ent_status);
614 return 1;
615 case SSTAT1_PHASE_MSGIN:
616 /*
617 * target may be ready to disconnect
618 * Save data pointers just in case.
619 */
620 INCSTAT(esiop_stat_intr_xferdisc);
621 if (scratchc0 & A_f_c_data)
622 siop_sdp(&esiop_cmd->cmd_c);
623 else if ((dstat & DSTAT_DFE) == 0)
624 siop_clearfifo(&sc->sc_c);
625 bus_space_write_1(sc->sc_c.sc_rt,
626 sc->sc_c.sc_rh, SIOP_SCRATCHC,
627 scratchc0 & ~A_f_c_data);
628 esiop_table_sync(esiop_cmd,
629 BUS_DMASYNC_PREREAD |
630 BUS_DMASYNC_PREWRITE);
631 CALL_SCRIPT(Ent_msgin);
632 return 1;
633 }
634 printf("%s: unexpected phase mismatch %d\n",
635 sc->sc_c.sc_dev.dv_xname,
636 sstat1 & SSTAT1_PHASE_MASK);
637 } else {
638 printf("%s: phase mismatch without command\n",
639 sc->sc_c.sc_dev.dv_xname);
640 }
641 need_reset = 1;
642 }
643 if (sist & SIST0_PAR) {
644 /* parity error, reset */
645 if (esiop_cmd)
646 scsipi_printaddr(xs->xs_periph);
647 else
648 printf("%s:", sc->sc_c.sc_dev.dv_xname);
649 printf("parity error\n");
650 if (esiop_target)
651 esiop_target->target_c.flags &= ~TARF_DT;
652 goto reset;
653 }
654 if ((sist & (SIST1_STO << 8)) && need_reset == 0) {
655 /*
656 * selection time out, assume there's no device here
657 * We also have to update the ring pointer ourselve
658 */
659 slot = bus_space_read_1(sc->sc_c.sc_rt,
660 sc->sc_c.sc_rh, SIOP_SCRATCHE);
661 esiop_script_sync(sc,
662 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
663 #ifdef SIOP_DEBUG_SCHED
664 printf("sel timeout target %d, slot %d\n", target, slot);
665 #endif
666 /*
667 * mark this slot as free, and advance to next slot
668 */
669 esiop_script_write(sc,
670 sc->sc_shedoffset + slot * CMD_SLOTSIZE,
671 A_f_cmd_free);
672 addr = bus_space_read_4(sc->sc_c.sc_rt,
673 sc->sc_c.sc_rh, SIOP_SCRATCHD);
674 if (slot < (A_ncmd_slots - 1)) {
675 bus_space_write_1(sc->sc_c.sc_rt,
676 sc->sc_c.sc_rh, SIOP_SCRATCHE, slot + 1);
677 addr = addr + sizeof(struct esiop_slot);
678 } else {
679 bus_space_write_1(sc->sc_c.sc_rt,
680 sc->sc_c.sc_rh, SIOP_SCRATCHE, 0);
681 addr = sc->sc_c.sc_scriptaddr +
682 sc->sc_shedoffset * sizeof(u_int32_t);
683 }
684 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
685 SIOP_SCRATCHD, addr);
686 esiop_script_sync(sc,
687 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
688 if (esiop_cmd) {
689 esiop_cmd->cmd_c.status = CMDST_DONE;
690 xs->error = XS_SELTIMEOUT;
691 freetarget = 1;
692 goto end;
693 } else {
694 printf("%s: selection timeout without "
695 "command, target %d (sdid 0x%x), "
696 "slot %d\n",
697 sc->sc_c.sc_dev.dv_xname, target,
698 bus_space_read_1(sc->sc_c.sc_rt,
699 sc->sc_c.sc_rh, SIOP_SDID), slot);
700 need_reset = 1;
701 }
702 }
703 if (sist & SIST0_UDC) {
704 /*
705 * unexpected disconnect. Usually the target signals
706 * a fatal condition this way. Attempt to get sense.
707 */
708 if (esiop_cmd) {
709 esiop_cmd->cmd_tables->status =
710 htole32(SCSI_CHECK);
711 goto end;
712 }
713 printf("%s: unexpected disconnect without "
714 "command\n", sc->sc_c.sc_dev.dv_xname);
715 goto reset;
716 }
717 if (sist & (SIST1_SBMC << 8)) {
718 /* SCSI bus mode change */
719 if (siop_modechange(&sc->sc_c) == 0 || need_reset == 1)
720 goto reset;
721 if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) {
722 /*
723 * we have a script interrupt, it will
724 * restart the script.
725 */
726 goto scintr;
727 }
728 /*
729 * else we have to restart it ourselve, at the
730 * interrupted instruction.
731 */
732 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
733 SIOP_DSP,
734 bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
735 SIOP_DSP) - 8);
736 return 1;
737 }
738 /* Else it's an unhandled exeption (for now). */
739 printf("%s: unhandled scsi interrupt, sist=0x%x sstat1=0x%x "
740 "DSA=0x%x DSP=0x%x\n", sc->sc_c.sc_dev.dv_xname, sist,
741 bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
742 SIOP_SSTAT1),
743 bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
744 (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
745 SIOP_DSP) - sc->sc_c.sc_scriptaddr));
746 if (esiop_cmd) {
747 esiop_cmd->cmd_c.status = CMDST_DONE;
748 xs->error = XS_SELTIMEOUT;
749 goto end;
750 }
751 need_reset = 1;
752 }
753 if (need_reset) {
754 reset:
755 /* fatal error, reset the bus */
756 siop_resetbus(&sc->sc_c);
757 /* no table to flush here */
758 return 1;
759 }
760
761 scintr:
762 if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) { /* script interrupt */
763 irqcode = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
764 SIOP_DSPS);
765 #ifdef SIOP_DEBUG_INTR
766 printf("script interrupt 0x%x\n", irqcode);
767 #endif
768 /*
769 * no command, or an inactive command is only valid for a
770 * reselect interrupt
771 */
772 if ((irqcode & 0x80) == 0) {
773 if (esiop_cmd == NULL) {
774 printf(
775 "%s: script interrupt (0x%x) with invalid DSA !!!\n",
776 sc->sc_c.sc_dev.dv_xname, irqcode);
777 goto reset;
778 }
779 if (esiop_cmd->cmd_c.status != CMDST_ACTIVE) {
780 printf("%s: command with invalid status "
781 "(IRQ code 0x%x current status %d) !\n",
782 sc->sc_c.sc_dev.dv_xname,
783 irqcode, esiop_cmd->cmd_c.status);
784 xs = NULL;
785 }
786 }
787 switch(irqcode) {
788 case A_int_err:
789 printf("error, DSP=0x%x\n",
790 (int)(bus_space_read_4(sc->sc_c.sc_rt,
791 sc->sc_c.sc_rh, SIOP_DSP) - sc->sc_c.sc_scriptaddr));
792 if (xs) {
793 xs->error = XS_SELTIMEOUT;
794 goto end;
795 } else {
796 goto reset;
797 }
798 case A_int_msgin:
799 {
800 int msgin = bus_space_read_1(sc->sc_c.sc_rt,
801 sc->sc_c.sc_rh, SIOP_SFBR);
802 if (msgin == MSG_MESSAGE_REJECT) {
803 int msg, extmsg;
804 if (esiop_cmd->cmd_tables->msg_out[0] & 0x80) {
805 /*
806 * message was part of a identify +
807 * something else. Identify shoudl't
808 * have been rejected.
809 */
810 msg =
811 esiop_cmd->cmd_tables->msg_out[1];
812 extmsg =
813 esiop_cmd->cmd_tables->msg_out[3];
814 } else {
815 msg =
816 esiop_cmd->cmd_tables->msg_out[0];
817 extmsg =
818 esiop_cmd->cmd_tables->msg_out[2];
819 }
820 if (msg == MSG_MESSAGE_REJECT) {
821 /* MSG_REJECT for a MSG_REJECT !*/
822 if (xs)
823 scsipi_printaddr(xs->xs_periph);
824 else
825 printf("%s: ",
826 sc->sc_c.sc_dev.dv_xname);
827 printf("our reject message was "
828 "rejected\n");
829 goto reset;
830 }
831 if (msg == MSG_EXTENDED &&
832 extmsg == MSG_EXT_WDTR) {
833 /* WDTR rejected, initiate sync */
834 if ((esiop_target->target_c.flags &
835 TARF_SYNC) == 0) {
836 esiop_target->target_c.status =
837 TARST_OK;
838 siop_update_xfer_mode(&sc->sc_c,
839 target);
840 /* no table to flush here */
841 CALL_SCRIPT(Ent_msgin_ack);
842 return 1;
843 }
844 esiop_target->target_c.status =
845 TARST_SYNC_NEG;
846 siop_sdtr_msg(&esiop_cmd->cmd_c, 0,
847 sc->sc_c.st_minsync,
848 sc->sc_c.maxoff);
849 esiop_table_sync(esiop_cmd,
850 BUS_DMASYNC_PREREAD |
851 BUS_DMASYNC_PREWRITE);
852 CALL_SCRIPT(Ent_send_msgout);
853 return 1;
854 } else if (msg == MSG_EXTENDED &&
855 extmsg == MSG_EXT_SDTR) {
856 /* sync rejected */
857 esiop_target->target_c.offset = 0;
858 esiop_target->target_c.period = 0;
859 esiop_target->target_c.status =
860 TARST_OK;
861 siop_update_xfer_mode(&sc->sc_c,
862 target);
863 /* no table to flush here */
864 CALL_SCRIPT(Ent_msgin_ack);
865 return 1;
866 } else if (msg == MSG_EXTENDED &&
867 extmsg == MSG_EXT_PPR) {
868 /* PPR rejected */
869 esiop_target->target_c.offset = 0;
870 esiop_target->target_c.period = 0;
871 esiop_target->target_c.status =
872 TARST_OK;
873 siop_update_xfer_mode(&sc->sc_c,
874 target);
875 /* no table to flush here */
876 CALL_SCRIPT(Ent_msgin_ack);
877 return 1;
878 } else if (msg == MSG_SIMPLE_Q_TAG ||
879 msg == MSG_HEAD_OF_Q_TAG ||
880 msg == MSG_ORDERED_Q_TAG) {
881 if (esiop_handle_qtag_reject(
882 esiop_cmd) == -1)
883 goto reset;
884 CALL_SCRIPT(Ent_msgin_ack);
885 return 1;
886 }
887 if (xs)
888 scsipi_printaddr(xs->xs_periph);
889 else
890 printf("%s: ",
891 sc->sc_c.sc_dev.dv_xname);
892 if (msg == MSG_EXTENDED) {
893 printf("scsi message reject, extended "
894 "message sent was 0x%x\n", extmsg);
895 } else {
896 printf("scsi message reject, message "
897 "sent was 0x%x\n", msg);
898 }
899 /* no table to flush here */
900 CALL_SCRIPT(Ent_msgin_ack);
901 return 1;
902 }
903 if (xs)
904 scsipi_printaddr(xs->xs_periph);
905 else
906 printf("%s: ", sc->sc_c.sc_dev.dv_xname);
907 printf("unhandled message 0x%x\n",
908 esiop_cmd->cmd_tables->msg_in[0]);
909 esiop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT;
910 esiop_cmd->cmd_tables->t_msgout.count= htole32(1);
911 esiop_table_sync(esiop_cmd,
912 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
913 CALL_SCRIPT(Ent_send_msgout);
914 return 1;
915 }
916 case A_int_extmsgin:
917 #ifdef SIOP_DEBUG_INTR
918 printf("extended message: msg 0x%x len %d\n",
919 esiop_cmd->cmd_tables->msg_in[2],
920 esiop_cmd->cmd_tables->msg_in[1]);
921 #endif
922 if (esiop_cmd->cmd_tables->msg_in[1] >
923 sizeof(esiop_cmd->cmd_tables->msg_in) - 2)
924 printf("%s: extended message too big (%d)\n",
925 sc->sc_c.sc_dev.dv_xname,
926 esiop_cmd->cmd_tables->msg_in[1]);
927 esiop_cmd->cmd_tables->t_extmsgdata.count =
928 htole32(esiop_cmd->cmd_tables->msg_in[1] - 1);
929 esiop_table_sync(esiop_cmd,
930 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
931 CALL_SCRIPT(Ent_get_extmsgdata);
932 return 1;
933 case A_int_extmsgdata:
934 #ifdef SIOP_DEBUG_INTR
935 {
936 int i;
937 printf("extended message: 0x%x, data:",
938 esiop_cmd->cmd_tables->msg_in[2]);
939 for (i = 3; i < 2 + esiop_cmd->cmd_tables->msg_in[1];
940 i++)
941 printf(" 0x%x",
942 esiop_cmd->cmd_tables->msg_in[i]);
943 printf("\n");
944 }
945 #endif
946 if (esiop_cmd->cmd_tables->msg_in[2] == MSG_EXT_PPR) {
947 switch (siop_ppr_neg(&esiop_cmd->cmd_c)) {
948 case SIOP_NEG_MSGOUT:
949 esiop_update_scntl3(sc,
950 esiop_cmd->cmd_c.siop_target);
951 esiop_table_sync(esiop_cmd,
952 BUS_DMASYNC_PREREAD |
953 BUS_DMASYNC_PREWRITE);
954 CALL_SCRIPT(Ent_send_msgout);
955 return 1;
956 case SIOP_NEG_ACK:
957 esiop_update_scntl3(sc,
958 esiop_cmd->cmd_c.siop_target);
959 CALL_SCRIPT(Ent_msgin_ack);
960 return 1;
961 default:
962 panic("invalid retval from "
963 "siop_wdtr_neg()");
964 }
965 return 1;
966 }
967 if (esiop_cmd->cmd_tables->msg_in[2] == MSG_EXT_WDTR) {
968 switch (siop_wdtr_neg(&esiop_cmd->cmd_c)) {
969 case SIOP_NEG_MSGOUT:
970 esiop_update_scntl3(sc,
971 esiop_cmd->cmd_c.siop_target);
972 esiop_table_sync(esiop_cmd,
973 BUS_DMASYNC_PREREAD |
974 BUS_DMASYNC_PREWRITE);
975 CALL_SCRIPT(Ent_send_msgout);
976 return 1;
977 case SIOP_NEG_ACK:
978 esiop_update_scntl3(sc,
979 esiop_cmd->cmd_c.siop_target);
980 CALL_SCRIPT(Ent_msgin_ack);
981 return 1;
982 default:
983 panic("invalid retval from "
984 "siop_wdtr_neg()");
985 }
986 return 1;
987 }
988 if (esiop_cmd->cmd_tables->msg_in[2] == MSG_EXT_SDTR) {
989 switch (siop_sdtr_neg(&esiop_cmd->cmd_c)) {
990 case SIOP_NEG_MSGOUT:
991 esiop_update_scntl3(sc,
992 esiop_cmd->cmd_c.siop_target);
993 esiop_table_sync(esiop_cmd,
994 BUS_DMASYNC_PREREAD |
995 BUS_DMASYNC_PREWRITE);
996 CALL_SCRIPT(Ent_send_msgout);
997 return 1;
998 case SIOP_NEG_ACK:
999 esiop_update_scntl3(sc,
1000 esiop_cmd->cmd_c.siop_target);
1001 CALL_SCRIPT(Ent_msgin_ack);
1002 return 1;
1003 default:
1004 panic("invalid retval from "
1005 "siop_wdtr_neg()");
1006 }
1007 return 1;
1008 }
1009 /* send a message reject */
1010 esiop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT;
1011 esiop_cmd->cmd_tables->t_msgout.count = htole32(1);
1012 esiop_table_sync(esiop_cmd,
1013 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1014 CALL_SCRIPT(Ent_send_msgout);
1015 return 1;
1016 case A_int_disc:
1017 INCSTAT(esiop_stat_intr_sdp);
1018 offset = bus_space_read_1(sc->sc_c.sc_rt,
1019 sc->sc_c.sc_rh, SIOP_SCRATCHA + 1);
1020 #ifdef SIOP_DEBUG_DR
1021 printf("disconnect offset %d\n", offset);
1022 #endif
1023 if (offset > SIOP_NSG) {
1024 printf("%s: bad offset for disconnect (%d)\n",
1025 sc->sc_c.sc_dev.dv_xname, offset);
1026 goto reset;
1027 }
1028 /*
1029 * offset == SIOP_NSG may be a valid condition if
1030 * we get a sdp when the xfer is done.
1031 * Don't call memmove in this case.
1032 */
1033 if (offset < SIOP_NSG) {
1034 memmove(&esiop_cmd->cmd_tables->data[0],
1035 &esiop_cmd->cmd_tables->data[offset],
1036 (SIOP_NSG - offset) * sizeof(scr_table_t));
1037 esiop_table_sync(esiop_cmd,
1038 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1039 }
1040 CALL_SCRIPT(Ent_script_sched);
1041 return 1;
1042 case A_int_resfail:
1043 printf("reselect failed\n");
1044 CALL_SCRIPT(Ent_script_sched);
1045 return 1;
1046 case A_int_done:
1047 if (xs == NULL) {
1048 printf("%s: done without command\n",
1049 sc->sc_c.sc_dev.dv_xname);
1050 CALL_SCRIPT(Ent_script_sched);
1051 return 1;
1052 }
1053 #ifdef SIOP_DEBUG_INTR
1054 printf("done, DSA=0x%lx target id 0x%x last msg "
1055 "in=0x%x status=0x%x\n", (u_long)esiop_cmd->cmd_c.dsa,
1056 le32toh(esiop_cmd->cmd_tables->id),
1057 esiop_cmd->cmd_tables->msg_in[0],
1058 le32toh(esiop_cmd->cmd_tables->status));
1059 #endif
1060 INCSTAT(esiop_stat_intr_done);
1061 esiop_cmd->cmd_c.status = CMDST_DONE;
1062 goto end;
1063 default:
1064 printf("unknown irqcode %x\n", irqcode);
1065 if (xs) {
1066 xs->error = XS_SELTIMEOUT;
1067 goto end;
1068 }
1069 goto reset;
1070 }
1071 return 1;
1072 }
1073 /* We just should't get there */
1074 panic("siop_intr: I shouldn't be there !");
1075
1076 end:
1077 /*
1078 * restart the script now if command completed properly
1079 * Otherwise wait for siop_scsicmd_end(), we may need to cleanup the
1080 * queue
1081 */
1082 xs->status = le32toh(esiop_cmd->cmd_tables->status);
1083 #ifdef SIOP_DEBUG_INTR
1084 printf("esiop_intr end: status %d\n", xs->status);
1085 #endif
1086 if (tag >= 0)
1087 esiop_lun->tactive[tag] = NULL;
1088 else
1089 esiop_lun->active = NULL;
1090 esiop_scsicmd_end(esiop_cmd);
1091 if (freetarget && esiop_target->target_c.status == TARST_PROBING)
1092 esiop_del_dev(sc, target, lun);
1093 CALL_SCRIPT(Ent_script_sched);
1094 if (sc->sc_flags & SCF_CHAN_NOSLOT) {
1095 /* a command terminated, so we have free slots now */
1096 sc->sc_flags &= ~SCF_CHAN_NOSLOT;
1097 scsipi_channel_thaw(&sc->sc_c.sc_chan, 1);
1098 }
1099
1100 return 1;
1101 }
1102
1103 void
1104 esiop_scsicmd_end(esiop_cmd)
1105 struct esiop_cmd *esiop_cmd;
1106 {
1107 struct scsipi_xfer *xs = esiop_cmd->cmd_c.xs;
1108 struct esiop_softc *sc = (struct esiop_softc *)esiop_cmd->cmd_c.siop_sc;
1109
1110 switch(xs->status) {
1111 case SCSI_OK:
1112 xs->error = XS_NOERROR;
1113 break;
1114 case SCSI_BUSY:
1115 xs->error = XS_BUSY;
1116 break;
1117 case SCSI_CHECK:
1118 xs->error = XS_BUSY;
1119 /* remove commands in the queue and scheduler */
1120 esiop_unqueue(sc, xs->xs_periph->periph_target,
1121 xs->xs_periph->periph_lun);
1122 break;
1123 case SCSI_QUEUE_FULL:
1124 INCSTAT(esiop_stat_intr_qfull);
1125 #ifdef SIOP_DEBUG
1126 printf("%s:%d:%d: queue full (tag %d)\n",
1127 sc->sc_c.sc_dev.dv_xname,
1128 xs->xs_periph->periph_target,
1129 xs->xs_periph->periph_lun, esiop_cmd->cmd_c.tag);
1130 #endif
1131 xs->error = XS_BUSY;
1132 break;
1133 case SCSI_SIOP_NOCHECK:
1134 /*
1135 * don't check status, xs->error is already valid
1136 */
1137 break;
1138 case SCSI_SIOP_NOSTATUS:
1139 /*
1140 * the status byte was not updated, cmd was
1141 * aborted
1142 */
1143 xs->error = XS_SELTIMEOUT;
1144 break;
1145 default:
1146 xs->error = XS_DRIVER_STUFFUP;
1147 }
1148 if (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
1149 bus_dmamap_sync(sc->sc_c.sc_dmat,
1150 esiop_cmd->cmd_c.dmamap_data, 0,
1151 esiop_cmd->cmd_c.dmamap_data->dm_mapsize,
1152 (xs->xs_control & XS_CTL_DATA_IN) ?
1153 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1154 bus_dmamap_unload(sc->sc_c.sc_dmat,
1155 esiop_cmd->cmd_c.dmamap_data);
1156 }
1157 bus_dmamap_unload(sc->sc_c.sc_dmat, esiop_cmd->cmd_c.dmamap_cmd);
1158 callout_stop(&esiop_cmd->cmd_c.xs->xs_callout);
1159 esiop_cmd->cmd_c.status = CMDST_FREE;
1160 TAILQ_INSERT_TAIL(&sc->free_list, esiop_cmd, next);
1161 xs->resid = 0;
1162 scsipi_done (xs);
1163 }
1164
1165 void
1166 esiop_checkdone(sc)
1167 struct esiop_softc *sc;
1168 {
1169 int target, lun, tag;
1170 struct esiop_target *esiop_target;
1171 struct esiop_lun *esiop_lun;
1172 struct esiop_cmd *esiop_cmd;
1173 u_int32_t slot;
1174 int needsync = 0;
1175 int status;
1176
1177 bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_done_map,
1178 sc->sc_done_offset, A_ndone_slots * sizeof(u_int32_t),
1179 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1180 next:
1181 if (sc->sc_done_slot[sc->sc_currdoneslot] == 0) {
1182 if (needsync)
1183 bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_done_map,
1184 sc->sc_done_offset,
1185 A_ndone_slots * sizeof(u_int32_t),
1186 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1187 return;
1188 }
1189
1190 needsync = 1;
1191
1192 slot = htole32(sc->sc_done_slot[sc->sc_currdoneslot]);
1193 sc->sc_done_slot[sc->sc_currdoneslot] = 0;
1194 sc->sc_currdoneslot += 1;
1195 if (sc->sc_currdoneslot == A_ndone_slots)
1196 sc->sc_currdoneslot = 0;
1197
1198 target = (slot & A_f_c_target) ? (slot >> 8) & 0xff : -1;
1199 lun = (slot & A_f_c_lun) ? (slot >> 16) & 0xff : -1;
1200 tag = (slot & A_f_c_tag) ? (slot >> 24) & 0xff : -1;
1201
1202 esiop_target = (target >= 0) ?
1203 (struct esiop_target *)sc->sc_c.targets[target] : NULL;
1204 if (esiop_target == NULL) {
1205 printf("esiop_target (target %d) not valid\n", target);
1206 goto next;
1207 }
1208 esiop_lun = (lun >= 0) ? esiop_target->esiop_lun[lun] : NULL;
1209 if (esiop_lun == NULL) {
1210 printf("esiop_lun (target %d lun %d) not valid\n",
1211 target, lun);
1212 goto next;
1213 }
1214 esiop_cmd = (tag >= 0) ? esiop_lun->tactive[tag] : esiop_lun->active;
1215 if (esiop_cmd == NULL) {
1216 printf("esiop_cmd (target %d lun %d tag %d) not valid\n",
1217 target, lun, tag);
1218 goto next;
1219 }
1220
1221 esiop_table_sync(esiop_cmd,
1222 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1223 status = le32toh(esiop_cmd->cmd_tables->status);
1224 #ifdef DIAGNOSTIC
1225 if (status != SCSI_OK) {
1226 printf("command for T/L/Q %d/%d/%d status %d\n",
1227 target, lun, tag, status);
1228 goto next;
1229 }
1230
1231 #endif
1232 /* Ok, this command has been handled */
1233 esiop_cmd->cmd_c.xs->status = status;
1234 if (tag >= 0)
1235 esiop_lun->tactive[tag] = NULL;
1236 else
1237 esiop_lun->active = NULL;
1238 esiop_scsicmd_end(esiop_cmd);
1239 goto next;
1240 }
1241
1242 void
1243 esiop_unqueue(sc, target, lun)
1244 struct esiop_softc *sc;
1245 int target;
1246 int lun;
1247 {
1248 int slot, tag;
1249 u_int32_t slotdsa;
1250 struct esiop_cmd *esiop_cmd;
1251 struct esiop_lun *esiop_lun =
1252 ((struct esiop_target *)sc->sc_c.targets[target])->esiop_lun[lun];
1253
1254 /* first make sure to read valid data */
1255 esiop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1256
1257 for (tag = 0; tag < ESIOP_NTAG; tag++) {
1258 /* look for commands in the scheduler, not yet started */
1259 if (esiop_lun->tactive[tag] == NULL)
1260 continue;
1261 esiop_cmd = esiop_lun->tactive[tag];
1262 for (slot = 0; slot < A_ncmd_slots; slot++) {
1263 slotdsa = esiop_script_read(sc,
1264 sc->sc_shedoffset + slot * CMD_SLOTSIZE);
1265 /* if the slot has any flag, it won't match the DSA */
1266 if (slotdsa == esiop_cmd->cmd_c.dsa) { /* found it */
1267 /* Mark this slot as ignore */
1268 esiop_script_write(sc,
1269 sc->sc_shedoffset + slot * CMD_SLOTSIZE,
1270 esiop_cmd->cmd_c.dsa | A_f_cmd_ignore);
1271 /* ask to requeue */
1272 esiop_cmd->cmd_c.xs->error = XS_REQUEUE;
1273 esiop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK;
1274 esiop_lun->tactive[tag] = NULL;
1275 esiop_scsicmd_end(esiop_cmd);
1276 break;
1277 }
1278 }
1279 }
1280 esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1281 }
1282
1283 /*
1284 * handle a rejected queue tag message: the command will run untagged,
1285 * has to adjust the reselect script.
1286 */
1287
1288
1289 int
1290 esiop_handle_qtag_reject(esiop_cmd)
1291 struct esiop_cmd *esiop_cmd;
1292 {
1293 struct esiop_softc *sc = (struct esiop_softc *)esiop_cmd->cmd_c.siop_sc;
1294 int target = esiop_cmd->cmd_c.xs->xs_periph->periph_target;
1295 int lun = esiop_cmd->cmd_c.xs->xs_periph->periph_lun;
1296 int tag = esiop_cmd->cmd_tables->msg_out[2];
1297 struct esiop_target *esiop_target =
1298 (struct esiop_target*)sc->sc_c.targets[target];
1299 struct esiop_lun *esiop_lun = esiop_target->esiop_lun[lun];
1300
1301 #ifdef SIOP_DEBUG
1302 printf("%s:%d:%d: tag message %d (%d) rejected (status %d)\n",
1303 sc->sc_c.sc_dev.dv_xname, target, lun, tag, esiop_cmd->cmd_c.tag,
1304 esiop_cmd->cmd_c.status);
1305 #endif
1306
1307 if (esiop_lun->active != NULL) {
1308 printf("%s: untagged command already running for target %d "
1309 "lun %d (status %d)\n", sc->sc_c.sc_dev.dv_xname,
1310 target, lun, esiop_lun->active->cmd_c.status);
1311 return -1;
1312 }
1313 /* clear tag slot */
1314 esiop_lun->tactive[tag] = NULL;
1315 /* add command to non-tagged slot */
1316 esiop_lun->active = esiop_cmd;
1317 esiop_cmd->cmd_c.flags &= ~CMDFL_TAG;
1318 esiop_cmd->cmd_c.tag = -1;
1319 /* update DSA table */
1320 esiop_script_write(sc, esiop_target->lun_table_offset +
1321 lun * 2 + A_target_luntbl / sizeof(u_int32_t),
1322 esiop_cmd->cmd_c.dsa);
1323 esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1324 return 0;
1325 }
1326
1327 /*
1328 * handle a bus reset: reset chip, unqueue all active commands, free all
1329 * target struct and report loosage to upper layer.
1330 * As the upper layer may requeue immediatly we have to first store
1331 * all active commands in a temporary queue.
1332 */
1333 void
1334 esiop_handle_reset(sc)
1335 struct esiop_softc *sc;
1336 {
1337 struct esiop_cmd *esiop_cmd;
1338 struct esiop_lun *esiop_lun;
1339 int target, lun, tag;
1340 /*
1341 * scsi bus reset. reset the chip and restart
1342 * the queue. Need to clean up all active commands
1343 */
1344 printf("%s: scsi bus reset\n", sc->sc_c.sc_dev.dv_xname);
1345 /* stop, reset and restart the chip */
1346 esiop_reset(sc);
1347
1348 if (sc->sc_flags & SCF_CHAN_NOSLOT) {
1349 /* chip has been reset, all slots are free now */
1350 sc->sc_flags &= ~SCF_CHAN_NOSLOT;
1351 scsipi_channel_thaw(&sc->sc_c.sc_chan, 1);
1352 }
1353 /*
1354 * Process all commands: first commmands completes, then commands
1355 * being executed
1356 */
1357 esiop_checkdone(sc);
1358 for (target = 0; target < sc->sc_c.sc_chan.chan_ntargets;
1359 target++) {
1360 struct esiop_target *esiop_target =
1361 (struct esiop_target *)sc->sc_c.targets[target];
1362 if (esiop_target == NULL)
1363 continue;
1364 for (lun = 0; lun < 8; lun++) {
1365 esiop_lun = esiop_target->esiop_lun[lun];
1366 if (esiop_lun == NULL)
1367 continue;
1368 for (tag = -1; tag <
1369 ((sc->sc_c.targets[target]->flags & TARF_TAG) ?
1370 ESIOP_NTAG : 0);
1371 tag++) {
1372 if (tag >= 0)
1373 esiop_cmd = esiop_lun->tactive[tag];
1374 else
1375 esiop_cmd = esiop_lun->active;
1376 if (esiop_cmd == NULL)
1377 continue;
1378 scsipi_printaddr(esiop_cmd->cmd_c.xs->xs_periph);
1379 printf("command with tag id %d reset\n", tag);
1380 esiop_cmd->cmd_c.xs->error =
1381 (esiop_cmd->cmd_c.flags & CMDFL_TIMEOUT) ?
1382 XS_TIMEOUT : XS_RESET;
1383 esiop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK;
1384 if (tag >= 0)
1385 esiop_lun->tactive[tag] = NULL;
1386 else
1387 esiop_lun->active = NULL;
1388 esiop_cmd->cmd_c.status = CMDST_DONE;
1389 esiop_scsicmd_end(esiop_cmd);
1390 }
1391 }
1392 sc->sc_c.targets[target]->status = TARST_ASYNC;
1393 sc->sc_c.targets[target]->flags &= ~(TARF_ISWIDE | TARF_ISDT);
1394 sc->sc_c.targets[target]->period =
1395 sc->sc_c.targets[target]->offset = 0;
1396 siop_update_xfer_mode(&sc->sc_c, target);
1397 }
1398
1399 scsipi_async_event(&sc->sc_c.sc_chan, ASYNC_EVENT_RESET, NULL);
1400 }
1401
1402 void
1403 esiop_scsipi_request(chan, req, arg)
1404 struct scsipi_channel *chan;
1405 scsipi_adapter_req_t req;
1406 void *arg;
1407 {
1408 struct scsipi_xfer *xs;
1409 struct scsipi_periph *periph;
1410 struct esiop_softc *sc = (void *)chan->chan_adapter->adapt_dev;
1411 struct esiop_cmd *esiop_cmd;
1412 struct esiop_target *esiop_target;
1413 int s, error, i;
1414 int target;
1415 int lun;
1416
1417 switch (req) {
1418 case ADAPTER_REQ_RUN_XFER:
1419 xs = arg;
1420 periph = xs->xs_periph;
1421 target = periph->periph_target;
1422 lun = periph->periph_lun;
1423
1424 s = splbio();
1425 #ifdef SIOP_DEBUG_SCHED
1426 printf("starting cmd for %d:%d tag %d(%d)\n", target, lun,
1427 xs->xs_tag_type, xs->xs_tag_id);
1428 #endif
1429 esiop_cmd = TAILQ_FIRST(&sc->free_list);
1430 if (esiop_cmd == NULL) {
1431 xs->error = XS_RESOURCE_SHORTAGE;
1432 scsipi_done(xs);
1433 splx(s);
1434 return;
1435 }
1436 TAILQ_REMOVE(&sc->free_list, esiop_cmd, next);
1437 #ifdef DIAGNOSTIC
1438 if (esiop_cmd->cmd_c.status != CMDST_FREE)
1439 panic("siop_scsicmd: new cmd not free");
1440 #endif
1441 esiop_target = (struct esiop_target*)sc->sc_c.targets[target];
1442 if (esiop_target == NULL) {
1443 #ifdef SIOP_DEBUG
1444 printf("%s: alloc siop_target for target %d\n",
1445 sc->sc_c.sc_dev.dv_xname, target);
1446 #endif
1447 sc->sc_c.targets[target] =
1448 malloc(sizeof(struct esiop_target),
1449 M_DEVBUF, M_NOWAIT | M_ZERO);
1450 if (sc->sc_c.targets[target] == NULL) {
1451 printf("%s: can't malloc memory for "
1452 "target %d\n", sc->sc_c.sc_dev.dv_xname,
1453 target);
1454 xs->error = XS_RESOURCE_SHORTAGE;
1455 scsipi_done(xs);
1456 splx(s);
1457 return;
1458 }
1459 esiop_target =
1460 (struct esiop_target*)sc->sc_c.targets[target];
1461 esiop_target->target_c.status = TARST_PROBING;
1462 esiop_target->target_c.flags = 0;
1463 esiop_target->target_c.id =
1464 sc->sc_c.clock_div << 24; /* scntl3 */
1465 esiop_target->target_c.id |= target << 16; /* id */
1466 /* esiop_target->target_c.id |= 0x0 << 8; scxfer is 0 */
1467
1468 for (i=0; i < 8; i++)
1469 esiop_target->esiop_lun[i] = NULL;
1470 esiop_target_register(sc, target);
1471 }
1472 if (esiop_target->esiop_lun[lun] == NULL) {
1473 esiop_target->esiop_lun[lun] =
1474 malloc(sizeof(struct esiop_lun), M_DEVBUF,
1475 M_NOWAIT|M_ZERO);
1476 if (esiop_target->esiop_lun[lun] == NULL) {
1477 printf("%s: can't alloc esiop_lun for "
1478 "target %d lun %d\n",
1479 sc->sc_c.sc_dev.dv_xname, target, lun);
1480 xs->error = XS_RESOURCE_SHORTAGE;
1481 scsipi_done(xs);
1482 splx(s);
1483 return;
1484 }
1485 }
1486 esiop_cmd->cmd_c.siop_target = sc->sc_c.targets[target];
1487 esiop_cmd->cmd_c.xs = xs;
1488 esiop_cmd->cmd_c.flags = 0;
1489 esiop_cmd->cmd_c.status = CMDST_READY;
1490
1491 /* load the DMA maps */
1492 error = bus_dmamap_load(sc->sc_c.sc_dmat,
1493 esiop_cmd->cmd_c.dmamap_cmd,
1494 xs->cmd, xs->cmdlen, NULL, BUS_DMA_NOWAIT);
1495 if (error) {
1496 printf("%s: unable to load cmd DMA map: %d\n",
1497 sc->sc_c.sc_dev.dv_xname, error);
1498 xs->error = XS_DRIVER_STUFFUP;
1499 scsipi_done(xs);
1500 splx(s);
1501 return;
1502 }
1503 if (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
1504 error = bus_dmamap_load(sc->sc_c.sc_dmat,
1505 esiop_cmd->cmd_c.dmamap_data, xs->data, xs->datalen,
1506 NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
1507 ((xs->xs_control & XS_CTL_DATA_IN) ?
1508 BUS_DMA_READ : BUS_DMA_WRITE));
1509 if (error) {
1510 printf("%s: unable to load cmd DMA map: %d",
1511 sc->sc_c.sc_dev.dv_xname, error);
1512 xs->error = XS_DRIVER_STUFFUP;
1513 scsipi_done(xs);
1514 bus_dmamap_unload(sc->sc_c.sc_dmat,
1515 esiop_cmd->cmd_c.dmamap_cmd);
1516 splx(s);
1517 return;
1518 }
1519 bus_dmamap_sync(sc->sc_c.sc_dmat,
1520 esiop_cmd->cmd_c.dmamap_data, 0,
1521 esiop_cmd->cmd_c.dmamap_data->dm_mapsize,
1522 (xs->xs_control & XS_CTL_DATA_IN) ?
1523 BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
1524 }
1525 bus_dmamap_sync(sc->sc_c.sc_dmat, esiop_cmd->cmd_c.dmamap_cmd,
1526 0, esiop_cmd->cmd_c.dmamap_cmd->dm_mapsize,
1527 BUS_DMASYNC_PREWRITE);
1528
1529 if (xs->xs_tag_type)
1530 esiop_cmd->cmd_c.tag = xs->xs_tag_id;
1531 else
1532 esiop_cmd->cmd_c.tag = -1;
1533 siop_setuptables(&esiop_cmd->cmd_c);
1534 ((struct esiop_xfer *)esiop_cmd->cmd_tables)->tlq =
1535 htole32(A_f_c_target | A_f_c_lun);
1536 ((struct esiop_xfer *)esiop_cmd->cmd_tables)->tlq |=
1537 htole32((target << 8) | (lun << 16));
1538 if (esiop_cmd->cmd_c.flags & CMDFL_TAG) {
1539 ((struct esiop_xfer *)esiop_cmd->cmd_tables)->tlq |=
1540 htole32(A_f_c_tag);
1541 ((struct esiop_xfer *)esiop_cmd->cmd_tables)->tlq |=
1542 htole32(esiop_cmd->cmd_c.tag << 24);
1543 }
1544
1545 esiop_table_sync(esiop_cmd,
1546 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1547 esiop_start(sc, esiop_cmd);
1548 if (xs->xs_control & XS_CTL_POLL) {
1549 /* poll for command completion */
1550 while ((xs->xs_status & XS_STS_DONE) == 0) {
1551 delay(1000);
1552 esiop_intr(sc);
1553 }
1554 }
1555 splx(s);
1556 return;
1557
1558 case ADAPTER_REQ_GROW_RESOURCES:
1559 #ifdef SIOP_DEBUG
1560 printf("%s grow resources (%d)\n", sc->sc_c.sc_dev.dv_xname,
1561 sc->sc_c.sc_adapt.adapt_openings);
1562 #endif
1563 esiop_morecbd(sc);
1564 return;
1565
1566 case ADAPTER_REQ_SET_XFER_MODE:
1567 {
1568 struct scsipi_xfer_mode *xm = arg;
1569 if (sc->sc_c.targets[xm->xm_target] == NULL)
1570 return;
1571 s = splbio();
1572 if ((xm->xm_mode & PERIPH_CAP_TQING) &&
1573 (sc->sc_c.targets[xm->xm_target]->flags & TARF_TAG) == 0) {
1574 sc->sc_c.targets[xm->xm_target]->flags |= TARF_TAG;
1575 /* allocate tag tables for this device */
1576 for (lun = 0;
1577 lun < sc->sc_c.sc_chan.chan_nluns; lun++) {
1578 if (sc->sc_c.sc_chan.chan_periphs[
1579 xm->xm_target][lun])
1580 esiop_add_dev(sc, xm->xm_target, lun);
1581 }
1582 }
1583 if ((xm->xm_mode & PERIPH_CAP_WIDE16) &&
1584 (sc->sc_c.features & SF_BUS_WIDE))
1585 sc->sc_c.targets[xm->xm_target]->flags |= TARF_WIDE;
1586 if (xm->xm_mode & PERIPH_CAP_SYNC)
1587 sc->sc_c.targets[xm->xm_target]->flags |= TARF_SYNC;
1588 if ((xm->xm_mode & PERIPH_CAP_DT) &&
1589 (sc->sc_c.features & SF_CHIP_DT))
1590 sc->sc_c.targets[xm->xm_target]->flags |= TARF_DT;
1591 if ((xm->xm_mode &
1592 (PERIPH_CAP_SYNC | PERIPH_CAP_WIDE16 | PERIPH_CAP_DT)) ||
1593 sc->sc_c.targets[xm->xm_target]->status == TARST_PROBING)
1594 sc->sc_c.targets[xm->xm_target]->status = TARST_ASYNC;
1595
1596 splx(s);
1597 }
1598 }
1599 }
1600
1601 static void
1602 esiop_start(sc, esiop_cmd)
1603 struct esiop_softc *sc;
1604 struct esiop_cmd *esiop_cmd;
1605 {
1606 struct esiop_lun *esiop_lun;
1607 struct esiop_target *esiop_target;
1608 int timeout;
1609 int target, lun, slot;
1610
1611 /*
1612 * first make sure to read valid data
1613 */
1614 esiop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1615
1616 /*
1617 * We use a circular queue here. sc->sc_currschedslot points to a
1618 * free slot, unless we have filled the queue. Check this.
1619 */
1620 slot = sc->sc_currschedslot;
1621 if ((esiop_script_read(sc, sc->sc_shedoffset + slot * CMD_SLOTSIZE) &
1622 A_f_cmd_free) == 0) {
1623 /*
1624 * no more free slot, no need to continue. freeze the queue
1625 * and requeue this command.
1626 */
1627 scsipi_channel_freeze(&sc->sc_c.sc_chan, 1);
1628 sc->sc_flags |= SCF_CHAN_NOSLOT;
1629 esiop_cmd->cmd_c.xs->error = XS_REQUEUE;
1630 esiop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK;
1631 esiop_scsicmd_end(esiop_cmd);
1632 return;
1633 }
1634 /* OK, we can use this slot */
1635
1636 target = esiop_cmd->cmd_c.xs->xs_periph->periph_target;
1637 lun = esiop_cmd->cmd_c.xs->xs_periph->periph_lun;
1638 esiop_target = (struct esiop_target*)sc->sc_c.targets[target];
1639 esiop_lun = esiop_target->esiop_lun[lun];
1640 /* if non-tagged command active, panic: this shouldn't happen */
1641 if (esiop_lun->active != NULL) {
1642 panic("esiop_start: tagged cmd while untagged running");
1643 }
1644 #ifdef DIAGNOSTIC
1645 /* sanity check the tag if needed */
1646 if (esiop_cmd->cmd_c.flags & CMDFL_TAG) {
1647 if (esiop_lun->tactive[esiop_cmd->cmd_c.tag] != NULL)
1648 panic("esiop_start: tag not free");
1649 if (esiop_cmd->cmd_c.tag >= ESIOP_NTAG ||
1650 esiop_cmd->cmd_c.tag < 0) {
1651 scsipi_printaddr(esiop_cmd->cmd_c.xs->xs_periph);
1652 printf(": tag id %d\n", esiop_cmd->cmd_c.tag);
1653 panic("esiop_start: invalid tag id");
1654 }
1655 }
1656 #endif
1657 #ifdef SIOP_DEBUG_SCHED
1658 printf("using slot %d for DSA 0x%lx\n", slot,
1659 (u_long)esiop_cmd->cmd_c.dsa);
1660 #endif
1661 /* mark command as active */
1662 if (esiop_cmd->cmd_c.status == CMDST_READY)
1663 esiop_cmd->cmd_c.status = CMDST_ACTIVE;
1664 else
1665 panic("esiop_start: bad status");
1666 /* DSA table for reselect */
1667 if (esiop_cmd->cmd_c.flags & CMDFL_TAG) {
1668 esiop_lun->tactive[esiop_cmd->cmd_c.tag] = esiop_cmd;
1669 /* DSA table for reselect */
1670 esiop_lun->lun_tagtbl->tbl[esiop_cmd->cmd_c.tag] =
1671 htole32(esiop_cmd->cmd_c.dsa);
1672 bus_dmamap_sync(sc->sc_c.sc_dmat,
1673 esiop_lun->lun_tagtbl->tblblk->blkmap,
1674 esiop_lun->lun_tagtbl->tbl_offset,
1675 sizeof(u_int32_t) * ESIOP_NTAG, BUS_DMASYNC_PREWRITE);
1676 } else {
1677 esiop_lun->active = esiop_cmd;
1678 esiop_script_write(sc,
1679 esiop_target->lun_table_offset +
1680 lun * 2 + A_target_luntbl / sizeof(u_int32_t),
1681 esiop_cmd->cmd_c.dsa);
1682 }
1683 /* scheduler slot: DSA */
1684 esiop_script_write(sc, sc->sc_shedoffset + slot * CMD_SLOTSIZE,
1685 esiop_cmd->cmd_c.dsa);
1686 /* make sure SCRIPT processor will read valid data */
1687 esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1688 /* handle timeout */
1689 if ((esiop_cmd->cmd_c.xs->xs_control & XS_CTL_POLL) == 0) {
1690 /* start exire timer */
1691 timeout = mstohz(esiop_cmd->cmd_c.xs->timeout);
1692 if (timeout == 0)
1693 timeout = 1;
1694 callout_reset( &esiop_cmd->cmd_c.xs->xs_callout,
1695 timeout, esiop_timeout, esiop_cmd);
1696 }
1697 /* Signal script it has some work to do */
1698 bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
1699 SIOP_ISTAT, ISTAT_SIGP);
1700 /* update the current slot, and wait for IRQ */
1701 sc->sc_currschedslot++;
1702 if (sc->sc_currschedslot >= A_ncmd_slots)
1703 sc->sc_currschedslot = 0;
1704 return;
1705 }
1706
1707 void
1708 esiop_timeout(v)
1709 void *v;
1710 {
1711 struct esiop_cmd *esiop_cmd = v;
1712 struct esiop_softc *sc =
1713 (struct esiop_softc *)esiop_cmd->cmd_c.siop_sc;
1714 int s;
1715 #ifdef SIOP_DEBUG
1716 int slot, slotdsa;
1717 #endif
1718
1719 s = splbio();
1720 esiop_table_sync(esiop_cmd,
1721 BUS_DMASYNC_POSTREAD |
1722 BUS_DMASYNC_POSTWRITE);
1723 scsipi_printaddr(esiop_cmd->cmd_c.xs->xs_periph);
1724 #ifdef SIOP_DEBUG
1725 printf("command timeout (status %d)\n", le32toh(esiop_cmd->cmd_tables->status));
1726
1727 esiop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1728 for (slot = 0; slot < A_ncmd_slots; slot++) {
1729 slotdsa = esiop_script_read(sc,
1730 sc->sc_shedoffset + slot * CMD_SLOTSIZE);
1731 if ((slotdsa & 0x01) == 0)
1732 printf("slot %d not free (0x%x)\n", slot, slotdsa);
1733 }
1734 printf("istat 0x%x ", bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT));
1735 printf("DSP 0x%lx DSA 0x%x\n",
1736 (u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP) - sc->sc_c.sc_scriptaddr),
1737 bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA));
1738 bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_CTEST2);
1739 printf("istat 0x%x\n", bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT));
1740 #else
1741 printf("command timeout\n");
1742 #endif
1743 /* reset the scsi bus */
1744 siop_resetbus(&sc->sc_c);
1745
1746 /* deactivate callout */
1747 callout_stop(&esiop_cmd->cmd_c.xs->xs_callout);
1748 /*
1749 * mark command has being timed out and just return;
1750 * the bus reset will generate an interrupt,
1751 * it will be handled in siop_intr()
1752 */
1753 esiop_cmd->cmd_c.flags |= CMDFL_TIMEOUT;
1754 splx(s);
1755 return;
1756
1757 }
1758
1759 void
1760 esiop_dump_script(sc)
1761 struct esiop_softc *sc;
1762 {
1763 int i;
1764 for (i = 0; i < PAGE_SIZE / 4; i += 2) {
1765 printf("0x%04x: 0x%08x 0x%08x", i * 4,
1766 le32toh(sc->sc_c.sc_script[i]),
1767 le32toh(sc->sc_c.sc_script[i+1]));
1768 if ((le32toh(sc->sc_c.sc_script[i]) & 0xe0000000) ==
1769 0xc0000000) {
1770 i++;
1771 printf(" 0x%08x", le32toh(sc->sc_c.sc_script[i+1]));
1772 }
1773 printf("\n");
1774 }
1775 }
1776
1777 void
1778 esiop_morecbd(sc)
1779 struct esiop_softc *sc;
1780 {
1781 int error, i, s;
1782 bus_dma_segment_t seg;
1783 int rseg;
1784 struct esiop_cbd *newcbd;
1785 struct esiop_xfer *xfer;
1786 bus_addr_t dsa;
1787
1788 /* allocate a new list head */
1789 newcbd = malloc(sizeof(struct esiop_cbd), M_DEVBUF, M_NOWAIT|M_ZERO);
1790 if (newcbd == NULL) {
1791 printf("%s: can't allocate memory for command descriptors "
1792 "head\n", sc->sc_c.sc_dev.dv_xname);
1793 return;
1794 }
1795
1796 /* allocate cmd list */
1797 newcbd->cmds = malloc(sizeof(struct esiop_cmd) * SIOP_NCMDPB,
1798 M_DEVBUF, M_NOWAIT|M_ZERO);
1799 if (newcbd->cmds == NULL) {
1800 printf("%s: can't allocate memory for command descriptors\n",
1801 sc->sc_c.sc_dev.dv_xname);
1802 goto bad3;
1803 }
1804 error = bus_dmamem_alloc(sc->sc_c.sc_dmat, PAGE_SIZE, PAGE_SIZE, 0,
1805 &seg, 1, &rseg, BUS_DMA_NOWAIT);
1806 if (error) {
1807 printf("%s: unable to allocate cbd DMA memory, error = %d\n",
1808 sc->sc_c.sc_dev.dv_xname, error);
1809 goto bad2;
1810 }
1811 error = bus_dmamem_map(sc->sc_c.sc_dmat, &seg, rseg, PAGE_SIZE,
1812 (caddr_t *)&newcbd->xfers, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
1813 if (error) {
1814 printf("%s: unable to map cbd DMA memory, error = %d\n",
1815 sc->sc_c.sc_dev.dv_xname, error);
1816 goto bad2;
1817 }
1818 error = bus_dmamap_create(sc->sc_c.sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0,
1819 BUS_DMA_NOWAIT, &newcbd->xferdma);
1820 if (error) {
1821 printf("%s: unable to create cbd DMA map, error = %d\n",
1822 sc->sc_c.sc_dev.dv_xname, error);
1823 goto bad1;
1824 }
1825 error = bus_dmamap_load(sc->sc_c.sc_dmat, newcbd->xferdma,
1826 newcbd->xfers, PAGE_SIZE, NULL, BUS_DMA_NOWAIT);
1827 if (error) {
1828 printf("%s: unable to load cbd DMA map, error = %d\n",
1829 sc->sc_c.sc_dev.dv_xname, error);
1830 goto bad0;
1831 }
1832 #ifdef DEBUG
1833 printf("%s: alloc newcdb at PHY addr 0x%lx\n", sc->sc_c.sc_dev.dv_xname,
1834 (unsigned long)newcbd->xferdma->dm_segs[0].ds_addr);
1835 #endif
1836 for (i = 0; i < SIOP_NCMDPB; i++) {
1837 error = bus_dmamap_create(sc->sc_c.sc_dmat, MAXPHYS, SIOP_NSG,
1838 MAXPHYS, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
1839 &newcbd->cmds[i].cmd_c.dmamap_data);
1840 if (error) {
1841 printf("%s: unable to create data DMA map for cbd: "
1842 "error %d\n",
1843 sc->sc_c.sc_dev.dv_xname, error);
1844 goto bad0;
1845 }
1846 error = bus_dmamap_create(sc->sc_c.sc_dmat,
1847 sizeof(struct scsipi_generic), 1,
1848 sizeof(struct scsipi_generic), 0,
1849 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
1850 &newcbd->cmds[i].cmd_c.dmamap_cmd);
1851 if (error) {
1852 printf("%s: unable to create cmd DMA map for cbd %d\n",
1853 sc->sc_c.sc_dev.dv_xname, error);
1854 goto bad0;
1855 }
1856 newcbd->cmds[i].cmd_c.siop_sc = &sc->sc_c;
1857 newcbd->cmds[i].esiop_cbdp = newcbd;
1858 xfer = &newcbd->xfers[i];
1859 newcbd->cmds[i].cmd_tables = (struct siop_common_xfer *)xfer;
1860 memset(newcbd->cmds[i].cmd_tables, 0,
1861 sizeof(struct esiop_xfer));
1862 dsa = newcbd->xferdma->dm_segs[0].ds_addr +
1863 i * sizeof(struct esiop_xfer);
1864 newcbd->cmds[i].cmd_c.dsa = dsa;
1865 newcbd->cmds[i].cmd_c.status = CMDST_FREE;
1866 xfer->siop_tables.t_msgout.count= htole32(1);
1867 xfer->siop_tables.t_msgout.addr = htole32(dsa);
1868 xfer->siop_tables.t_msgin.count= htole32(1);
1869 xfer->siop_tables.t_msgin.addr = htole32(dsa +
1870 offsetof(struct siop_common_xfer, msg_in));
1871 xfer->siop_tables.t_extmsgin.count= htole32(2);
1872 xfer->siop_tables.t_extmsgin.addr = htole32(dsa +
1873 offsetof(struct siop_common_xfer, msg_in) + 1);
1874 xfer->siop_tables.t_extmsgdata.addr = htole32(dsa +
1875 offsetof(struct siop_common_xfer, msg_in) + 3);
1876 xfer->siop_tables.t_status.count= htole32(1);
1877 xfer->siop_tables.t_status.addr = htole32(dsa +
1878 offsetof(struct siop_common_xfer, status));
1879
1880 s = splbio();
1881 TAILQ_INSERT_TAIL(&sc->free_list, &newcbd->cmds[i], next);
1882 splx(s);
1883 #ifdef SIOP_DEBUG
1884 printf("tables[%d]: in=0x%x out=0x%x status=0x%x\n", i,
1885 le32toh(newcbd->cmds[i].cmd_tables->t_msgin.addr),
1886 le32toh(newcbd->cmds[i].cmd_tables->t_msgout.addr),
1887 le32toh(newcbd->cmds[i].cmd_tables->t_status.addr));
1888 #endif
1889 }
1890 s = splbio();
1891 TAILQ_INSERT_TAIL(&sc->cmds, newcbd, next);
1892 sc->sc_c.sc_adapt.adapt_openings += SIOP_NCMDPB;
1893 splx(s);
1894 return;
1895 bad0:
1896 bus_dmamap_unload(sc->sc_c.sc_dmat, newcbd->xferdma);
1897 bus_dmamap_destroy(sc->sc_c.sc_dmat, newcbd->xferdma);
1898 bad1:
1899 bus_dmamem_free(sc->sc_c.sc_dmat, &seg, rseg);
1900 bad2:
1901 free(newcbd->cmds, M_DEVBUF);
1902 bad3:
1903 free(newcbd, M_DEVBUF);
1904 return;
1905 }
1906
1907 void
1908 esiop_moretagtbl(sc)
1909 struct esiop_softc *sc;
1910 {
1911 int error, i, j, s;
1912 bus_dma_segment_t seg;
1913 int rseg;
1914 struct esiop_dsatblblk *newtblblk;
1915 struct esiop_dsatbl *newtbls;
1916 u_int32_t *tbls;
1917
1918 /* allocate a new list head */
1919 newtblblk = malloc(sizeof(struct esiop_dsatblblk),
1920 M_DEVBUF, M_NOWAIT|M_ZERO);
1921 if (newtblblk == NULL) {
1922 printf("%s: can't allocate memory for tag DSA table block\n",
1923 sc->sc_c.sc_dev.dv_xname);
1924 return;
1925 }
1926
1927 /* allocate tbl list */
1928 newtbls = malloc(sizeof(struct esiop_dsatbl) * ESIOP_NTPB,
1929 M_DEVBUF, M_NOWAIT|M_ZERO);
1930 if (newtbls == NULL) {
1931 printf("%s: can't allocate memory for command descriptors\n",
1932 sc->sc_c.sc_dev.dv_xname);
1933 goto bad3;
1934 }
1935 error = bus_dmamem_alloc(sc->sc_c.sc_dmat, PAGE_SIZE, PAGE_SIZE, 0,
1936 &seg, 1, &rseg, BUS_DMA_NOWAIT);
1937 if (error) {
1938 printf("%s: unable to allocate tbl DMA memory, error = %d\n",
1939 sc->sc_c.sc_dev.dv_xname, error);
1940 goto bad2;
1941 }
1942 error = bus_dmamem_map(sc->sc_c.sc_dmat, &seg, rseg, PAGE_SIZE,
1943 (caddr_t *)&tbls, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
1944 if (error) {
1945 printf("%s: unable to map tbls DMA memory, error = %d\n",
1946 sc->sc_c.sc_dev.dv_xname, error);
1947 goto bad2;
1948 }
1949 error = bus_dmamap_create(sc->sc_c.sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0,
1950 BUS_DMA_NOWAIT, &newtblblk->blkmap);
1951 if (error) {
1952 printf("%s: unable to create tbl DMA map, error = %d\n",
1953 sc->sc_c.sc_dev.dv_xname, error);
1954 goto bad1;
1955 }
1956 error = bus_dmamap_load(sc->sc_c.sc_dmat, newtblblk->blkmap,
1957 tbls, PAGE_SIZE, NULL, BUS_DMA_NOWAIT);
1958 if (error) {
1959 printf("%s: unable to load tbl DMA map, error = %d\n",
1960 sc->sc_c.sc_dev.dv_xname, error);
1961 goto bad0;
1962 }
1963 #ifdef DEBUG
1964 printf("%s: alloc new tag DSA table at PHY addr 0x%lx\n",
1965 sc->sc_c.sc_dev.dv_xname,
1966 (unsigned long)newtblblk->blkmap->dm_segs[0].ds_addr);
1967 #endif
1968 for (i = 0; i < ESIOP_NTPB; i++) {
1969 newtbls[i].tblblk = newtblblk;
1970 newtbls[i].tbl = &tbls[i * ESIOP_NTAG];
1971 newtbls[i].tbl_offset = i * ESIOP_NTAG * sizeof(u_int32_t);
1972 newtbls[i].tbl_dsa = newtblblk->blkmap->dm_segs[0].ds_addr +
1973 newtbls[i].tbl_offset;
1974 for (j = 0; j < ESIOP_NTAG; j++)
1975 newtbls[i].tbl[j] = j;
1976 s = splbio();
1977 TAILQ_INSERT_TAIL(&sc->free_tagtbl, &newtbls[i], next);
1978 splx(s);
1979 }
1980 s = splbio();
1981 TAILQ_INSERT_TAIL(&sc->tag_tblblk, newtblblk, next);
1982 splx(s);
1983 return;
1984 bad0:
1985 bus_dmamap_unload(sc->sc_c.sc_dmat, newtblblk->blkmap);
1986 bus_dmamap_destroy(sc->sc_c.sc_dmat, newtblblk->blkmap);
1987 bad1:
1988 bus_dmamem_free(sc->sc_c.sc_dmat, &seg, rseg);
1989 bad2:
1990 free(newtbls, M_DEVBUF);
1991 bad3:
1992 free(newtblblk, M_DEVBUF);
1993 return;
1994 }
1995
1996 void
1997 esiop_update_scntl3(sc, _siop_target)
1998 struct esiop_softc *sc;
1999 struct siop_common_target *_siop_target;
2000 {
2001 struct esiop_target *esiop_target = (struct esiop_target *)_siop_target;
2002 esiop_script_write(sc, esiop_target->lun_table_offset,
2003 esiop_target->target_c.id);
2004 }
2005
2006 void
2007 esiop_add_dev(sc, target, lun)
2008 struct esiop_softc *sc;
2009 int target;
2010 int lun;
2011 {
2012 struct esiop_target *esiop_target =
2013 (struct esiop_target *)sc->sc_c.targets[target];
2014 struct esiop_lun *esiop_lun = esiop_target->esiop_lun[lun];
2015
2016 /* we need a tag DSA table */
2017 esiop_lun->lun_tagtbl= TAILQ_FIRST(&sc->free_tagtbl);
2018 if (esiop_lun->lun_tagtbl == NULL) {
2019 esiop_moretagtbl(sc);
2020 esiop_lun->lun_tagtbl= TAILQ_FIRST(&sc->free_tagtbl);
2021 if (esiop_lun->lun_tagtbl == NULL) {
2022 /* no resources, run untagged */
2023 esiop_target->target_c.flags &= ~TARF_TAG;
2024 return;
2025 }
2026 }
2027 TAILQ_REMOVE(&sc->free_tagtbl, esiop_lun->lun_tagtbl, next);
2028 /* Update LUN DSA table */
2029 esiop_script_write(sc, esiop_target->lun_table_offset +
2030 lun * 2 + A_target_luntbl_tag / sizeof(u_int32_t),
2031 esiop_lun->lun_tagtbl->tbl_dsa);
2032 esiop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2033 }
2034
2035 void
2036 esiop_del_dev(sc, target, lun)
2037 struct esiop_softc *sc;
2038 int target;
2039 int lun;
2040 {
2041 struct esiop_target *esiop_target;
2042 #ifdef SIOP_DEBUG
2043 printf("%s:%d:%d: free lun sw entry\n",
2044 sc->sc_c.sc_dev.dv_xname, target, lun);
2045 #endif
2046 if (sc->sc_c.targets[target] == NULL)
2047 return;
2048 esiop_target = (struct esiop_target *)sc->sc_c.targets[target];
2049 free(esiop_target->esiop_lun[lun], M_DEVBUF);
2050 esiop_target->esiop_lun[lun] = NULL;
2051 }
2052
2053 void
2054 esiop_target_register(sc, target)
2055 struct esiop_softc *sc;
2056 u_int32_t target;
2057 {
2058 struct esiop_target *esiop_target =
2059 (struct esiop_target *)sc->sc_c.targets[target];
2060 struct esiop_lun *esiop_lun;
2061 int lun;
2062
2063 /* get a DSA table for this target */
2064 esiop_target->lun_table_offset = sc->sc_free_offset;
2065 sc->sc_free_offset += sc->sc_c.sc_chan.chan_nluns * 2 + 2;
2066 #ifdef SIOP_DEBUG
2067 printf("%s: lun table for target %d offset %d free offset %d\n",
2068 sc->sc_c.sc_dev.dv_xname, target, esiop_target->lun_table_offset,
2069 sc->sc_free_offset);
2070 #endif
2071 /* first 32 bytes are ID (for select) */
2072 esiop_script_write(sc, esiop_target->lun_table_offset,
2073 esiop_target->target_c.id);
2074 /* Record this table in the target DSA table */
2075 esiop_script_write(sc,
2076 sc->sc_target_table_offset + target,
2077 (esiop_target->lun_table_offset * sizeof(u_int32_t)) +
2078 sc->sc_c.sc_scriptaddr);
2079 /* if we have a tag table, register it */
2080 for (lun = 0; lun < sc->sc_c.sc_chan.chan_nluns; lun++) {
2081 esiop_lun = esiop_target->esiop_lun[lun];
2082 if (esiop_lun == NULL)
2083 continue;
2084 if (esiop_lun->lun_tagtbl)
2085 esiop_script_write(sc, esiop_target->lun_table_offset +
2086 lun * 2 + A_target_luntbl_tag / sizeof(u_int32_t),
2087 esiop_lun->lun_tagtbl->tbl_dsa);
2088 }
2089 esiop_script_sync(sc,
2090 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2091 }
2092
2093 #ifdef SIOP_STATS
2094 void
2095 esiop_printstats()
2096 {
2097 printf("esiop_stat_intr %d\n", esiop_stat_intr);
2098 printf("esiop_stat_intr_shortxfer %d\n", esiop_stat_intr_shortxfer);
2099 printf("esiop_stat_intr_xferdisc %d\n", esiop_stat_intr_xferdisc);
2100 printf("esiop_stat_intr_sdp %d\n", esiop_stat_intr_sdp);
2101 printf("esiop_stat_intr_done %d\n", esiop_stat_intr_done);
2102 printf("esiop_stat_intr_lunresel %d\n", esiop_stat_intr_lunresel);
2103 printf("esiop_stat_intr_qfull %d\n", esiop_stat_intr_qfull);
2104 }
2105 #endif
2106