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