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