This source file includes following definitions.
- siop_table_sync
- siop_script_sync
- siop_script_read
- siop_script_write
- siop_attach
- siop_reset
- siop_intr
- siop_scsicmd_end
- siop_handle_qtag_reject
- siop_handle_reset
- siop_scsicmd
- siop_start
- siop_timeout
- siop_dump_script
- siop_morecbd
- siop_get_lunsw
- siop_add_reselsw
- siop_update_scntl3
- siop_add_dev
- siop_del_dev
- siop_printstats
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/device.h>
39 #include <sys/malloc.h>
40 #include <sys/buf.h>
41 #include <sys/kernel.h>
42
43 #include <machine/endian.h>
44 #include <machine/bus.h>
45
46 #include <dev/microcode/siop/siop.out>
47
48 #include <scsi/scsi_all.h>
49 #include <scsi/scsi_message.h>
50 #include <scsi/scsiconf.h>
51
52 #include <dev/ic/siopreg.h>
53 #include <dev/ic/siopvar_common.h>
54 #include <dev/ic/siopvar.h>
55
56 #ifndef SIOP_DEBUG
57 #undef SIOP_DEBUG
58 #undef SIOP_DEBUG_DR
59 #undef SIOP_DEBUG_INTR
60 #undef SIOP_DEBUG_SCHED
61 #undef DUMP_SCRIPT
62 #else
63 #define SIOP_DEBUG_DR
64 #define SIOP_DEBUG_INTR
65 #define SIOP_DEBUG_SCHED
66 #define DUMP_SCRIPT
67 #endif
68
69
70 #undef SIOP_STATS
71
72 #ifndef SIOP_DEFAULT_TARGET
73 #define SIOP_DEFAULT_TARGET 7
74 #endif
75
76
77 #define SIOP_NCMDPB (PAGE_SIZE / sizeof(struct siop_xfer))
78
79
80 #define SIOP_NSLOTS 40
81
82 void siop_table_sync(struct siop_cmd *, int);
83 void siop_script_sync(struct siop_softc *, int);
84 u_int32_t siop_script_read(struct siop_softc *, u_int);
85 void siop_script_write(struct siop_softc *, u_int, u_int32_t);
86 void siop_reset(struct siop_softc *);
87 void siop_handle_reset(struct siop_softc *);
88 int siop_handle_qtag_reject(struct siop_cmd *);
89 void siop_scsicmd_end(struct siop_cmd *);
90 void siop_start(struct siop_softc *);
91 void siop_timeout(void *);
92 int siop_scsicmd(struct scsi_xfer *);
93 #ifdef DUMP_SCRIPT
94 void siop_dump_script(struct siop_softc *);
95 #endif
96 void siop_morecbd(struct siop_softc *);
97 struct siop_lunsw *siop_get_lunsw(struct siop_softc *);
98 void siop_add_reselsw(struct siop_softc *, int);
99 void siop_update_scntl3(struct siop_softc *, struct siop_common_target *);
100
101 struct cfdriver siop_cd = {
102 NULL, "siop", DV_DULL
103 };
104
105 struct scsi_adapter siop_adapter = {
106 siop_scsicmd,
107 siop_minphys,
108 NULL,
109 NULL,
110 };
111
112 struct scsi_device siop_dev = {
113 NULL,
114 NULL,
115 NULL,
116 NULL,
117 };
118
119 #ifdef SIOP_STATS
120 static int siop_stat_intr = 0;
121 static int siop_stat_intr_shortxfer = 0;
122 static int siop_stat_intr_sdp = 0;
123 static int siop_stat_intr_saveoffset = 0;
124 static int siop_stat_intr_done = 0;
125 static int siop_stat_intr_xferdisc = 0;
126 static int siop_stat_intr_lunresel = 0;
127 static int siop_stat_intr_qfull = 0;
128 void siop_printstats(void);
129 #define INCSTAT(x) x++
130 #else
131 #define INCSTAT(x)
132 #endif
133
134 void
135 siop_table_sync(siop_cmd, ops)
136 struct siop_cmd *siop_cmd;
137 int ops;
138 {
139 struct siop_common_softc *sc = siop_cmd->cmd_c.siop_sc;
140 bus_addr_t offset;
141
142 offset = siop_cmd->cmd_c.dsa -
143 siop_cmd->siop_cbdp->xferdma->dm_segs[0].ds_addr;
144 bus_dmamap_sync(sc->sc_dmat, siop_cmd->siop_cbdp->xferdma, offset,
145 sizeof(struct siop_xfer), ops);
146 }
147
148 void
149 siop_script_sync(sc, ops)
150 struct siop_softc *sc;
151 int ops;
152 {
153 if ((sc->sc_c.features & SF_CHIP_RAM) == 0)
154 bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,
155 PAGE_SIZE, ops);
156 }
157
158 u_int32_t
159 siop_script_read(sc, offset)
160 struct siop_softc *sc;
161 u_int offset;
162 {
163 if (sc->sc_c.features & SF_CHIP_RAM) {
164 return bus_space_read_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
165 offset * 4);
166 } else {
167 return siop_ctoh32(&sc->sc_c, sc->sc_c.sc_script[offset]);
168 }
169 }
170
171 void
172 siop_script_write(sc, offset, val)
173 struct siop_softc *sc;
174 u_int offset;
175 u_int32_t val;
176 {
177 if (sc->sc_c.features & SF_CHIP_RAM) {
178 bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
179 offset * 4, val);
180 } else {
181 sc->sc_c.sc_script[offset] = siop_htoc32(&sc->sc_c, val);
182 }
183 }
184
185 void
186 siop_attach(sc)
187 struct siop_softc *sc;
188 {
189 struct scsibus_attach_args saa;
190
191 if (siop_common_attach(&sc->sc_c) != 0)
192 return;
193
194 TAILQ_INIT(&sc->free_list);
195 TAILQ_INIT(&sc->ready_list);
196 TAILQ_INIT(&sc->urgent_list);
197 TAILQ_INIT(&sc->cmds);
198 TAILQ_INIT(&sc->lunsw_list);
199 sc->sc_currschedslot = 0;
200 sc->sc_c.sc_link.adapter = &siop_adapter;
201 sc->sc_c.sc_link.device = &siop_dev;
202 sc->sc_c.sc_link.openings = SIOP_NTAG;
203
204
205 siop_morecbd(sc);
206
207 #ifdef SIOP_DEBUG
208 printf("%s: script size = %d, PHY addr=0x%x, VIRT=%p\n",
209 sc->sc_c.sc_dev.dv_xname, (int)sizeof(siop_script),
210 (u_int32_t)sc->sc_c.sc_scriptaddr, sc->sc_c.sc_script);
211 #endif
212
213
214 siop_resetbus(&sc->sc_c);
215
216
217
218 siop_reset(sc);
219 #ifdef DUMP_SCRIPT
220 siop_dump_script(sc);
221 #endif
222
223 bzero(&saa, sizeof(saa));
224 saa.saa_sc_link = &sc->sc_c.sc_link;
225
226 config_found((struct device*)sc, &saa, scsiprint);
227 }
228
229 void
230 siop_reset(sc)
231 struct siop_softc *sc;
232 {
233 int i, j;
234 struct siop_lunsw *lunsw;
235
236 siop_common_reset(&sc->sc_c);
237
238
239 if (sc->sc_c.features & SF_CHIP_RAM) {
240 bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 0,
241 siop_script, sizeof(siop_script) / sizeof(siop_script[0]));
242 for (j = 0; j <
243 (sizeof(E_abs_msgin_Used) / sizeof(E_abs_msgin_Used[0]));
244 j++) {
245 bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
246 E_abs_msgin_Used[j] * 4,
247 sc->sc_c.sc_scriptaddr + Ent_msgin_space);
248 }
249 if (sc->sc_c.features & SF_CHIP_LED0) {
250 bus_space_write_region_4(sc->sc_c.sc_ramt,
251 sc->sc_c.sc_ramh,
252 Ent_led_on1, siop_led_on,
253 sizeof(siop_led_on) / sizeof(siop_led_on[0]));
254 bus_space_write_region_4(sc->sc_c.sc_ramt,
255 sc->sc_c.sc_ramh,
256 Ent_led_on2, siop_led_on,
257 sizeof(siop_led_on) / sizeof(siop_led_on[0]));
258 bus_space_write_region_4(sc->sc_c.sc_ramt,
259 sc->sc_c.sc_ramh,
260 Ent_led_off, siop_led_off,
261 sizeof(siop_led_off) / sizeof(siop_led_off[0]));
262 }
263 } else {
264 for (j = 0;
265 j < (sizeof(siop_script) / sizeof(siop_script[0])); j++) {
266 sc->sc_c.sc_script[j] =
267 siop_htoc32(&sc->sc_c, siop_script[j]);
268 }
269 for (j = 0; j <
270 (sizeof(E_abs_msgin_Used) / sizeof(E_abs_msgin_Used[0]));
271 j++) {
272 sc->sc_c.sc_script[E_abs_msgin_Used[j]] =
273 siop_htoc32(&sc->sc_c,
274 sc->sc_c.sc_scriptaddr + Ent_msgin_space);
275 }
276 if (sc->sc_c.features & SF_CHIP_LED0) {
277 for (j = 0; j < (sizeof(siop_led_on) /
278 sizeof(siop_led_on[0])); j++)
279 sc->sc_c.sc_script[
280 Ent_led_on1 / sizeof(siop_led_on[0]) + j
281 ] = siop_htoc32(&sc->sc_c, siop_led_on[j]);
282 for (j = 0; j < (sizeof(siop_led_on) /
283 sizeof(siop_led_on[0])); j++)
284 sc->sc_c.sc_script[
285 Ent_led_on2 / sizeof(siop_led_on[0]) + j
286 ] = siop_htoc32(&sc->sc_c, siop_led_on[j]);
287 for (j = 0; j < (sizeof(siop_led_off) /
288 sizeof(siop_led_off[0])); j++)
289 sc->sc_c.sc_script[
290 Ent_led_off / sizeof(siop_led_off[0]) + j
291 ] = siop_htoc32(&sc->sc_c, siop_led_off[j]);
292 }
293 }
294 sc->script_free_lo = sizeof(siop_script) / sizeof(siop_script[0]);
295 sc->script_free_hi = sc->sc_c.ram_size / 4;
296 sc->sc_ntargets = 0;
297
298
299 while((lunsw = TAILQ_FIRST(&sc->lunsw_list)) != NULL) {
300 #ifdef SIOP_DEBUG
301 printf("%s: free lunsw at offset %d\n",
302 sc->sc_c.sc_dev.dv_xname, lunsw->lunsw_off);
303 #endif
304 TAILQ_REMOVE(&sc->lunsw_list, lunsw, next);
305 free(lunsw, M_DEVBUF);
306 }
307 TAILQ_INIT(&sc->lunsw_list);
308
309 for (i = 0; i < sc->sc_c.sc_link.adapter_buswidth; i++) {
310 struct siop_target *target;
311 if (sc->sc_c.targets[i] == NULL)
312 continue;
313 #ifdef SIOP_DEBUG
314 printf("%s: restore sw for target %d\n",
315 sc->sc_c.sc_dev.dv_xname, i);
316 #endif
317 target = (struct siop_target *)sc->sc_c.targets[i];
318 free(target->lunsw, M_DEVBUF);
319 target->lunsw = siop_get_lunsw(sc);
320 if (target->lunsw == NULL) {
321 printf("%s: can't alloc lunsw for target %d\n",
322 sc->sc_c.sc_dev.dv_xname, i);
323 break;
324 }
325 siop_add_reselsw(sc, i);
326 }
327
328
329 if ((sc->sc_c.features & SF_CHIP_RAM) == 0) {
330 bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,
331 PAGE_SIZE, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
332 }
333 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP,
334 sc->sc_c.sc_scriptaddr + Ent_reselect);
335 }
336
337 #if 0
338 #define CALL_SCRIPT(ent) do {\
339 printf ("start script DSA 0x%lx DSP 0x%lx\n", \
340 siop_cmd->cmd_c.dsa, \
341 sc->sc_c.sc_scriptaddr + ent); \
342 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \
343 } while (0)
344 #else
345 #define CALL_SCRIPT(ent) do {\
346 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \
347 } while (0)
348 #endif
349
350 int
351 siop_intr(v)
352 void *v;
353 {
354 struct siop_softc *sc = v;
355 struct siop_target *siop_target;
356 struct siop_cmd *siop_cmd;
357 struct siop_lun *siop_lun;
358 struct scsi_xfer *xs;
359 int istat, sist, sstat1, dstat = 0;
360 u_int32_t irqcode;
361 int need_reset = 0;
362 int offset, target, lun, tag;
363 bus_addr_t dsa;
364 struct siop_cbd *cbdp;
365 int freetarget = 0;
366 int restart = 0;
367
368 istat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT);
369 if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0)
370 return 0;
371 INCSTAT(siop_stat_intr);
372 if (istat & ISTAT_INTF) {
373 printf("INTRF\n");
374 bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
375 SIOP_ISTAT, ISTAT_INTF);
376 }
377 if ((istat &(ISTAT_DIP | ISTAT_SIP | ISTAT_ABRT)) ==
378 (ISTAT_DIP | ISTAT_ABRT)) {
379
380 bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
381 SIOP_ISTAT, 0);
382 }
383
384 siop_cmd = NULL;
385 dsa = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA);
386 TAILQ_FOREACH(cbdp, &sc->cmds, next) {
387 if (dsa >= cbdp->xferdma->dm_segs[0].ds_addr &&
388 dsa < cbdp->xferdma->dm_segs[0].ds_addr + PAGE_SIZE) {
389 dsa -= cbdp->xferdma->dm_segs[0].ds_addr;
390 siop_cmd = &cbdp->cmds[dsa / sizeof(struct siop_xfer)];
391 siop_table_sync(siop_cmd,
392 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
393 break;
394 }
395 }
396 if (siop_cmd) {
397 xs = siop_cmd->cmd_c.xs;
398 siop_target = (struct siop_target *)siop_cmd->cmd_c.siop_target;
399 target = siop_cmd->cmd_c.xs->sc_link->target;
400 lun = siop_cmd->cmd_c.xs->sc_link->lun;
401 tag = siop_cmd->cmd_c.tag;
402 siop_lun = siop_target->siop_lun[lun];
403 #ifdef DIAGNOSTIC
404 if (siop_cmd->cmd_c.status != CMDST_ACTIVE &&
405 siop_cmd->cmd_c.status != CMDST_SENSE_ACTIVE) {
406 printf("siop_cmd (lun %d) for DSA 0x%x "
407 "not active (%d)\n", lun, (u_int)dsa,
408 siop_cmd->cmd_c.status);
409 xs = NULL;
410 siop_target = NULL;
411 target = -1;
412 lun = -1;
413 tag = -1;
414 siop_lun = NULL;
415 siop_cmd = NULL;
416 } else if (siop_lun->siop_tag[tag].active != siop_cmd) {
417 printf("siop_cmd (lun %d tag %d) not in siop_lun "
418 "active (%p != %p)\n", lun, tag, siop_cmd,
419 siop_lun->siop_tag[tag].active);
420 }
421 #endif
422 } else {
423 xs = NULL;
424 siop_target = NULL;
425 target = -1;
426 lun = -1;
427 tag = -1;
428 siop_lun = NULL;
429 }
430 if (istat & ISTAT_DIP) {
431 dstat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
432 SIOP_DSTAT);
433 if (dstat & DSTAT_ABRT) {
434
435 if ((dstat & DSTAT_DFE) == 0)
436 siop_clearfifo(&sc->sc_c);
437 goto reset;
438 }
439 if (dstat & DSTAT_SSI) {
440 printf("single step dsp 0x%08x dsa 0x08%x\n",
441 (int)(bus_space_read_4(sc->sc_c.sc_rt,
442 sc->sc_c.sc_rh, SIOP_DSP) -
443 sc->sc_c.sc_scriptaddr),
444 bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
445 SIOP_DSA));
446 if ((dstat & ~(DSTAT_DFE | DSTAT_SSI)) == 0 &&
447 (istat & ISTAT_SIP) == 0) {
448 bus_space_write_1(sc->sc_c.sc_rt,
449 sc->sc_c.sc_rh, SIOP_DCNTL,
450 bus_space_read_1(sc->sc_c.sc_rt,
451 sc->sc_c.sc_rh, SIOP_DCNTL) | DCNTL_STD);
452 }
453 return 1;
454 }
455
456 if (dstat & ~(DSTAT_SIR | DSTAT_DFE | DSTAT_SSI)) {
457 printf("%s: DMA IRQ:", sc->sc_c.sc_dev.dv_xname);
458 if (dstat & DSTAT_IID)
459 printf(" illegal instruction");
460 if (dstat & DSTAT_BF)
461 printf(" bus fault");
462 if (dstat & DSTAT_MDPE)
463 printf(" parity");
464 if (dstat & DSTAT_DFE)
465 printf(" DMA fifo empty");
466 else
467 siop_clearfifo(&sc->sc_c);
468 printf(", DSP=0x%x DSA=0x%x: ",
469 (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
470 SIOP_DSP) - sc->sc_c.sc_scriptaddr),
471 bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA));
472 if (siop_cmd)
473 printf("last msg_in=0x%x status=0x%x\n",
474 siop_cmd->cmd_tables->msg_in[0],
475 siop_ctoh32(&sc->sc_c,
476 siop_cmd->cmd_tables->status));
477 else
478 printf("current DSA invalid\n");
479 need_reset = 1;
480 }
481 }
482 if (istat & ISTAT_SIP) {
483 if (istat & ISTAT_DIP)
484 delay(10);
485
486
487
488
489 sist = bus_space_read_2(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
490 SIOP_SIST0);
491 sstat1 = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
492 SIOP_SSTAT1);
493 #ifdef SIOP_DEBUG_INTR
494 printf("scsi interrupt, sist=0x%x sstat1=0x%x "
495 "DSA=0x%x DSP=0x%lx\n", sist, sstat1,
496 bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
497 (u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
498 SIOP_DSP) -
499 sc->sc_c.sc_scriptaddr));
500 #endif
501 if (sist & SIST0_RST) {
502 siop_handle_reset(sc);
503 siop_start(sc);
504
505 return 1;
506 }
507 if (sist & SIST0_SGE) {
508 if (siop_cmd)
509 sc_print_addr(xs->sc_link);
510 else
511 printf("%s:", sc->sc_c.sc_dev.dv_xname);
512 printf("scsi gross error\n");
513 goto reset;
514 }
515 if ((sist & SIST0_MA) && need_reset == 0) {
516 if (siop_cmd) {
517 int scratcha0;
518
519 dstat = bus_space_read_1(sc->sc_c.sc_rt,
520 sc->sc_c.sc_rh, SIOP_DSTAT);
521
522
523
524
525 bus_space_write_4(sc->sc_c.sc_rt,
526 sc->sc_c.sc_rh,
527 SIOP_DSA, siop_cmd->cmd_c.dsa);
528 scratcha0 = bus_space_read_1(sc->sc_c.sc_rt,
529 sc->sc_c.sc_rh, SIOP_SCRATCHA);
530 switch (sstat1 & SSTAT1_PHASE_MASK) {
531 case SSTAT1_PHASE_STATUS:
532
533
534
535
536
537
538
539 INCSTAT(siop_stat_intr_shortxfer);
540 if (scratcha0 & A_flag_data)
541 siop_ma(&siop_cmd->cmd_c);
542 else if ((dstat & DSTAT_DFE) == 0)
543 siop_clearfifo(&sc->sc_c);
544 CALL_SCRIPT(Ent_status);
545 return 1;
546 case SSTAT1_PHASE_MSGIN:
547
548
549
550
551
552 INCSTAT(siop_stat_intr_xferdisc);
553 if (scratcha0 & A_flag_data)
554 siop_ma(&siop_cmd->cmd_c);
555 else if ((dstat & DSTAT_DFE) == 0)
556 siop_clearfifo(&sc->sc_c);
557 bus_space_write_1(sc->sc_c.sc_rt,
558 sc->sc_c.sc_rh, SIOP_SCRATCHA,
559 scratcha0 & ~A_flag_data);
560 CALL_SCRIPT(Ent_msgin);
561 return 1;
562 }
563 printf("%s: unexpected phase mismatch %d\n",
564 sc->sc_c.sc_dev.dv_xname,
565 sstat1 & SSTAT1_PHASE_MASK);
566 } else {
567 printf("%s: phase mismatch without command\n",
568 sc->sc_c.sc_dev.dv_xname);
569 }
570 need_reset = 1;
571 }
572 if (sist & SIST0_PAR) {
573
574 if (siop_cmd)
575 sc_print_addr(xs->sc_link);
576 else
577 printf("%s:", sc->sc_c.sc_dev.dv_xname);
578 printf("parity error\n");
579 goto reset;
580 }
581 if ((sist & (SIST1_STO << 8)) && need_reset == 0) {
582
583 if (siop_cmd) {
584 siop_cmd->cmd_c.status = CMDST_DONE;
585 xs->error = XS_SELTIMEOUT;
586 freetarget = 1;
587 goto end;
588 } else {
589 printf("%s: selection timeout without "
590 "command\n", sc->sc_c.sc_dev.dv_xname);
591 need_reset = 1;
592 }
593 }
594 if (sist & SIST0_UDC) {
595
596
597
598
599 if (siop_cmd) {
600 siop_cmd->cmd_tables->status =
601 siop_htoc32(&sc->sc_c, SCSI_CHECK);
602 goto end;
603 }
604 printf("%s: unexpected disconnect without "
605 "command\n", sc->sc_c.sc_dev.dv_xname);
606 goto reset;
607 }
608 if (sist & (SIST1_SBMC << 8)) {
609
610 if (siop_modechange(&sc->sc_c) == 0 || need_reset == 1)
611 goto reset;
612 if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) {
613
614
615
616
617 goto scintr;
618 }
619
620
621
622
623 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
624 SIOP_DSP,
625 bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
626 SIOP_DSP) - 8);
627 return 1;
628 }
629
630 printf("%s: unhandled scsi interrupt, sist=0x%x sstat1=0x%x "
631 "DSA=0x%x DSP=0x%x\n", sc->sc_c.sc_dev.dv_xname,
632 sist, sstat1,
633 bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
634 (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
635 SIOP_DSP) - sc->sc_c.sc_scriptaddr));
636 if (siop_cmd) {
637 siop_cmd->cmd_c.status = CMDST_DONE;
638 xs->error = XS_SELTIMEOUT;
639 goto end;
640 }
641 need_reset = 1;
642 }
643 if (need_reset) {
644 reset:
645
646 siop_resetbus(&sc->sc_c);
647
648 return 1;
649 }
650
651 scintr:
652 if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) {
653 irqcode = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
654 SIOP_DSPS);
655 #ifdef SIOP_DEBUG_INTR
656 printf("script interrupt 0x%x\n", irqcode);
657 #endif
658
659
660
661
662 if ((irqcode & 0x80) == 0) {
663 if (siop_cmd == NULL) {
664 printf(
665 "%s: script interrupt (0x%x) with invalid DSA !!!\n",
666 sc->sc_c.sc_dev.dv_xname, irqcode);
667 goto reset;
668 }
669 if (siop_cmd->cmd_c.status != CMDST_ACTIVE &&
670 siop_cmd->cmd_c.status != CMDST_SENSE_ACTIVE) {
671 printf("%s: command with invalid status "
672 "(IRQ code 0x%x current status %d) !\n",
673 sc->sc_c.sc_dev.dv_xname,
674 irqcode, siop_cmd->cmd_c.status);
675 xs = NULL;
676 }
677 }
678 switch(irqcode) {
679 case A_int_err:
680 printf("error, DSP=0x%x\n",
681 (int)(bus_space_read_4(sc->sc_c.sc_rt,
682 sc->sc_c.sc_rh, SIOP_DSP) - sc->sc_c.sc_scriptaddr));
683 if (xs) {
684 xs->error = XS_SELTIMEOUT;
685 goto end;
686 } else {
687 goto reset;
688 }
689 case A_int_reseltarg:
690 printf("%s: reselect with invalid target\n",
691 sc->sc_c.sc_dev.dv_xname);
692 goto reset;
693 case A_int_resellun:
694 INCSTAT(siop_stat_intr_lunresel);
695 target = bus_space_read_1(sc->sc_c.sc_rt,
696 sc->sc_c.sc_rh, SIOP_SCRATCHA) & 0xf;
697 lun = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
698 SIOP_SCRATCHA + 1);
699 tag = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
700 SIOP_SCRATCHA + 2);
701 siop_target =
702 (struct siop_target *)sc->sc_c.targets[target];
703 if (siop_target == NULL) {
704 printf("%s: reselect with invalid target %d\n",
705 sc->sc_c.sc_dev.dv_xname, target);
706 goto reset;
707 }
708 siop_lun = siop_target->siop_lun[lun];
709 if (siop_lun == NULL) {
710 printf("%s: target %d reselect with invalid "
711 "lun %d\n", sc->sc_c.sc_dev.dv_xname,
712 target, lun);
713 goto reset;
714 }
715 if (siop_lun->siop_tag[tag].active == NULL) {
716 printf("%s: target %d lun %d tag %d reselect "
717 "without command\n",
718 sc->sc_c.sc_dev.dv_xname,
719 target, lun, tag);
720 goto reset;
721 }
722 siop_cmd = siop_lun->siop_tag[tag].active;
723 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
724 SIOP_DSP, siop_cmd->cmd_c.dsa +
725 sizeof(struct siop_common_xfer) +
726 Ent_ldsa_reload_dsa);
727 siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);
728 return 1;
729 case A_int_reseltag:
730 printf("%s: reselect with invalid tag\n",
731 sc->sc_c.sc_dev.dv_xname);
732 goto reset;
733 case A_int_msgin:
734 {
735 int msgin = bus_space_read_1(sc->sc_c.sc_rt,
736 sc->sc_c.sc_rh, SIOP_SFBR);
737 if (msgin == MSG_MESSAGE_REJECT) {
738 int msg, extmsg;
739 if (siop_cmd->cmd_tables->msg_out[0] & 0x80) {
740
741
742
743
744
745 msg =
746 siop_cmd->cmd_tables->msg_out[1];
747 extmsg =
748 siop_cmd->cmd_tables->msg_out[3];
749 } else {
750 msg = siop_cmd->cmd_tables->msg_out[0];
751 extmsg =
752 siop_cmd->cmd_tables->msg_out[2];
753 }
754 if (msg == MSG_MESSAGE_REJECT) {
755
756 if (xs)
757 sc_print_addr(xs->sc_link);
758 else
759 printf("%s: ",
760 sc->sc_c.sc_dev.dv_xname);
761 printf("our reject message was "
762 "rejected\n");
763 goto reset;
764 }
765 if (msg == MSG_EXTENDED &&
766 extmsg == MSG_EXT_WDTR) {
767
768 if ((siop_target->target_c.flags &
769 TARF_SYNC) == 0) {
770 siop_target->target_c.status =
771 TARST_OK;
772 siop_update_xfer_mode(&sc->sc_c,
773 target);
774
775 CALL_SCRIPT(Ent_msgin_ack);
776 return 1;
777 }
778 siop_target->target_c.status =
779 TARST_SYNC_NEG;
780 siop_sdtr_msg(&siop_cmd->cmd_c, 0,
781 sc->sc_c.st_minsync,
782 sc->sc_c.maxoff);
783 siop_table_sync(siop_cmd,
784 BUS_DMASYNC_PREREAD |
785 BUS_DMASYNC_PREWRITE);
786 CALL_SCRIPT(Ent_send_msgout);
787 return 1;
788 } else if (msg == MSG_EXTENDED &&
789 extmsg == MSG_EXT_SDTR) {
790
791 siop_target->target_c.offset = 0;
792 siop_target->target_c.period = 0;
793 siop_target->target_c.status = TARST_OK;
794 siop_update_xfer_mode(&sc->sc_c,
795 target);
796
797 CALL_SCRIPT(Ent_msgin_ack);
798 return 1;
799 } else if (msg == MSG_EXTENDED &&
800 extmsg == MSG_EXT_PPR) {
801
802 siop_target->target_c.offset = 0;
803 siop_target->target_c.period = 0;
804 siop_target->target_c.status = TARST_ASYNC;
805 siop_target->target_c.flags &= ~(TARF_DT | TARF_ISDT);
806 CALL_SCRIPT(Ent_msgin_ack);
807 return 1;
808 } else if (msg == MSG_SIMPLE_Q_TAG ||
809 msg == MSG_HEAD_OF_Q_TAG ||
810 msg == MSG_ORDERED_Q_TAG) {
811 if (siop_handle_qtag_reject(
812 siop_cmd) == -1)
813 goto reset;
814 CALL_SCRIPT(Ent_msgin_ack);
815 return 1;
816 }
817 if (xs)
818 sc_print_addr(xs->sc_link);
819 else
820 printf("%s: ",
821 sc->sc_c.sc_dev.dv_xname);
822 if (msg == MSG_EXTENDED) {
823 printf("scsi message reject, extended "
824 "message sent was 0x%x\n", extmsg);
825 } else {
826 printf("scsi message reject, message "
827 "sent was 0x%x\n", msg);
828 }
829
830 CALL_SCRIPT(Ent_msgin_ack);
831 return 1;
832 }
833 if (msgin == MSG_IGN_WIDE_RESIDUE) {
834
835 siop_cmd->cmd_tables->t_extmsgdata.count =
836 siop_htoc32(&sc->sc_c, 1);
837 siop_table_sync(siop_cmd,
838 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
839 CALL_SCRIPT(Ent_get_extmsgdata);
840 return 1;
841 }
842 if (xs)
843 sc_print_addr(xs->sc_link);
844 else
845 printf("%s: ", sc->sc_c.sc_dev.dv_xname);
846 printf("unhandled message 0x%x\n",
847 siop_cmd->cmd_tables->msg_in[0]);
848 siop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT;
849 siop_cmd->cmd_tables->t_msgout.count =
850 siop_htoc32(&sc->sc_c, 1);
851 siop_table_sync(siop_cmd,
852 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
853 CALL_SCRIPT(Ent_send_msgout);
854 return 1;
855 }
856 case A_int_extmsgin:
857 #ifdef SIOP_DEBUG_INTR
858 printf("extended message: msg 0x%x len %d\n",
859 siop_cmd->cmd_tables->msg_in[2],
860 siop_cmd->cmd_tables->msg_in[1]);
861 #endif
862 if (siop_cmd->cmd_tables->msg_in[1] >
863 sizeof(siop_cmd->cmd_tables->msg_in) - 2)
864 printf("%s: extended message too big (%d)\n",
865 sc->sc_c.sc_dev.dv_xname,
866 siop_cmd->cmd_tables->msg_in[1]);
867 siop_cmd->cmd_tables->t_extmsgdata.count =
868 siop_htoc32(&sc->sc_c,
869 siop_cmd->cmd_tables->msg_in[1] - 1);
870 siop_table_sync(siop_cmd,
871 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
872 CALL_SCRIPT(Ent_get_extmsgdata);
873 return 1;
874 case A_int_extmsgdata:
875 #ifdef SIOP_DEBUG_INTR
876 {
877 int i;
878 printf("extended message: 0x%x, data:",
879 siop_cmd->cmd_tables->msg_in[2]);
880 for (i = 3; i < 2 + siop_cmd->cmd_tables->msg_in[1];
881 i++)
882 printf(" 0x%x",
883 siop_cmd->cmd_tables->msg_in[i]);
884 printf("\n");
885 }
886 #endif
887 if (siop_cmd->cmd_tables->msg_in[0] ==
888 MSG_IGN_WIDE_RESIDUE) {
889
890 if (siop_cmd->cmd_tables->msg_in[3] != 1)
891 printf("MSG_IGN_WIDE_RESIDUE: "
892 "bad len %d\n",
893 siop_cmd->cmd_tables->msg_in[3]);
894 switch (siop_iwr(&siop_cmd->cmd_c)) {
895 case SIOP_NEG_MSGOUT:
896 siop_table_sync(siop_cmd,
897 BUS_DMASYNC_PREREAD |
898 BUS_DMASYNC_PREWRITE);
899 CALL_SCRIPT(Ent_send_msgout);
900 return(1);
901 case SIOP_NEG_ACK:
902 CALL_SCRIPT(Ent_msgin_ack);
903 return(1);
904 default:
905 panic("invalid retval from "
906 "siop_iwr()");
907 }
908 return(1);
909 }
910 if (siop_cmd->cmd_tables->msg_in[2] == MSG_EXT_WDTR) {
911 switch (siop_wdtr_neg(&siop_cmd->cmd_c)) {
912 case SIOP_NEG_MSGOUT:
913 siop_update_scntl3(sc,
914 siop_cmd->cmd_c.siop_target);
915 siop_table_sync(siop_cmd,
916 BUS_DMASYNC_PREREAD |
917 BUS_DMASYNC_PREWRITE);
918 CALL_SCRIPT(Ent_send_msgout);
919 return(1);
920 case SIOP_NEG_ACK:
921 siop_update_scntl3(sc,
922 siop_cmd->cmd_c.siop_target);
923 CALL_SCRIPT(Ent_msgin_ack);
924 return(1);
925 default:
926 panic("invalid retval from "
927 "siop_wdtr_neg()");
928 }
929 return(1);
930 }
931 if (siop_cmd->cmd_tables->msg_in[2] == MSG_EXT_SDTR) {
932 switch (siop_sdtr_neg(&siop_cmd->cmd_c)) {
933 case SIOP_NEG_MSGOUT:
934 siop_update_scntl3(sc,
935 siop_cmd->cmd_c.siop_target);
936 siop_table_sync(siop_cmd,
937 BUS_DMASYNC_PREREAD |
938 BUS_DMASYNC_PREWRITE);
939 CALL_SCRIPT(Ent_send_msgout);
940 return(1);
941 case SIOP_NEG_ACK:
942 siop_update_scntl3(sc,
943 siop_cmd->cmd_c.siop_target);
944 CALL_SCRIPT(Ent_msgin_ack);
945 return(1);
946 default:
947 panic("invalid retval from "
948 "siop_sdtr_neg()");
949 }
950 return(1);
951 }
952 if (siop_cmd->cmd_tables->msg_in[2] == MSG_EXT_PPR) {
953 switch (siop_ppr_neg(&siop_cmd->cmd_c)) {
954 case SIOP_NEG_MSGOUT:
955 siop_update_scntl3(sc,
956 siop_cmd->cmd_c.siop_target);
957 siop_table_sync(siop_cmd,
958 BUS_DMASYNC_PREREAD |
959 BUS_DMASYNC_PREWRITE);
960 CALL_SCRIPT(Ent_send_msgout);
961 return(1);
962 case SIOP_NEG_ACK:
963 siop_update_scntl3(sc,
964 siop_cmd->cmd_c.siop_target);
965 CALL_SCRIPT(Ent_msgin_ack);
966 return(1);
967 default:
968 panic("invalid retval from "
969 "siop_wdtr_neg()");
970 }
971 return(1);
972 }
973
974 siop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT;
975 siop_cmd->cmd_tables->t_msgout.count =
976 siop_htoc32(&sc->sc_c, 1);
977 siop_table_sync(siop_cmd,
978 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
979 CALL_SCRIPT(Ent_send_msgout);
980 return 1;
981 case A_int_disc:
982 INCSTAT(siop_stat_intr_sdp);
983 offset = bus_space_read_1(sc->sc_c.sc_rt,
984 sc->sc_c.sc_rh, SIOP_SCRATCHA + 1);
985 #ifdef SIOP_DEBUG_DR
986 printf("disconnect offset %d\n", offset);
987 #endif
988 siop_sdp(&siop_cmd->cmd_c, offset);
989
990 siop_cmd->saved_offset = SIOP_NOOFFSET;
991 siop_table_sync(siop_cmd,
992 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
993 CALL_SCRIPT(Ent_script_sched);
994 return 1;
995 case A_int_saveoffset:
996 INCSTAT(siop_stat_intr_saveoffset);
997 offset = bus_space_read_1(sc->sc_c.sc_rt,
998 sc->sc_c.sc_rh, SIOP_SCRATCHA + 1);
999 #ifdef SIOP_DEBUG_DR
1000 printf("saveoffset offset %d\n", offset);
1001 #endif
1002 siop_cmd->saved_offset = offset;
1003 CALL_SCRIPT(Ent_script_sched);
1004 return 1;
1005 case A_int_resfail:
1006 printf("reselect failed\n");
1007
1008 siop_start(sc);
1009 CALL_SCRIPT(Ent_script_sched);
1010 return 1;
1011 case A_int_done:
1012 if (xs == NULL) {
1013 printf("%s: done without command, DSA=0x%lx\n",
1014 sc->sc_c.sc_dev.dv_xname,
1015 (u_long)siop_cmd->cmd_c.dsa);
1016 siop_cmd->cmd_c.status = CMDST_FREE;
1017 siop_start(sc);
1018 CALL_SCRIPT(Ent_script_sched);
1019 return 1;
1020 }
1021 #ifdef SIOP_DEBUG_INTR
1022 printf("done, DSA=0x%lx target id 0x%x last msg "
1023 "in=0x%x status=0x%x\n", (u_long)siop_cmd->cmd_c.dsa,
1024 siop_ctoh32(&sc->sc_c, siop_cmd->cmd_tables->id),
1025 siop_cmd->cmd_tables->msg_in[0],
1026 siop_ctoh32(&sc->sc_c,
1027 siop_cmd->cmd_tables->status));
1028 #endif
1029 INCSTAT(siop_stat_intr_done);
1030
1031 offset = bus_space_read_1(sc->sc_c.sc_rt,
1032 sc->sc_c.sc_rh, SIOP_SCRATCHA + 1);
1033
1034
1035
1036
1037
1038
1039 if (offset == 0 &&
1040 siop_cmd->saved_offset != SIOP_NOOFFSET)
1041 offset = siop_cmd->saved_offset;
1042 siop_update_resid(&siop_cmd->cmd_c, offset);
1043 if (siop_cmd->cmd_c.status == CMDST_SENSE_ACTIVE)
1044 siop_cmd->cmd_c.status = CMDST_SENSE_DONE;
1045 else
1046 siop_cmd->cmd_c.status = CMDST_DONE;
1047 goto end;
1048 default:
1049 printf("unknown irqcode %x\n", irqcode);
1050 if (xs) {
1051 xs->error = XS_SELTIMEOUT;
1052 goto end;
1053 }
1054 goto reset;
1055 }
1056 return 1;
1057 }
1058
1059
1060 printf("%s: siop_intr() - we should not be here!\n"
1061 " istat = 0x%x, dstat = 0x%x, sist = 0x%x, sstat1 = 0x%x\n"
1062 " need_reset = %x, irqcode = %x, siop_cmd %s\n",
1063 sc->sc_c.sc_dev.dv_xname,
1064 istat, dstat, sist, sstat1, need_reset, irqcode,
1065 (siop_cmd == NULL) ? "== NULL" : "!= NULL");
1066 goto reset;
1067 end:
1068
1069
1070
1071
1072
1073 xs->status = siop_ctoh32(&sc->sc_c, siop_cmd->cmd_tables->status);
1074 if (xs->status == SCSI_OK)
1075 CALL_SCRIPT(Ent_script_sched);
1076 else
1077 restart = 1;
1078 siop_lun->siop_tag[tag].active = NULL;
1079 siop_scsicmd_end(siop_cmd);
1080 if (freetarget && siop_target->target_c.status == TARST_PROBING)
1081 siop_del_dev(sc, target, lun);
1082 siop_start(sc);
1083 if (restart)
1084 CALL_SCRIPT(Ent_script_sched);
1085 return 1;
1086 }
1087
1088 void
1089 siop_scsicmd_end(siop_cmd)
1090 struct siop_cmd *siop_cmd;
1091 {
1092 struct scsi_xfer *xs = siop_cmd->cmd_c.xs;
1093 struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc;
1094 struct siop_lun *siop_lun =
1095 ((struct siop_target*)sc->sc_c.targets[xs->sc_link->target])->siop_lun[xs->sc_link->lun];
1096
1097
1098
1099
1100
1101 timeout_del(&siop_cmd->cmd_c.xs->stimeout);
1102
1103 switch(xs->status) {
1104 case SCSI_OK:
1105 xs->error = (siop_cmd->cmd_c.status == CMDST_DONE) ?
1106 XS_NOERROR : XS_SENSE;
1107 break;
1108 case SCSI_BUSY:
1109 xs->error = XS_BUSY;
1110 break;
1111 case SCSI_CHECK:
1112 if (siop_cmd->cmd_c.status == CMDST_SENSE_DONE) {
1113
1114 printf("%s: request sense failed\n",
1115 sc->sc_c.sc_dev.dv_xname);
1116 xs->error = XS_DRIVER_STUFFUP;
1117 } else {
1118 siop_cmd->cmd_c.status = CMDST_SENSE;
1119 }
1120 break;
1121 case SCSI_QUEUE_FULL:
1122
1123
1124
1125
1126
1127
1128
1129
1130 INCSTAT(siop_stat_intr_qfull);
1131 #ifdef SIOP_DEBUG
1132 printf("%s:%d:%d: queue full (tag %d)\n", sc->sc_c.sc_dev.dv_xname,
1133 xs->sc_link->target,
1134 xs->sc_link->lun, siop_cmd->cmd_c.tag);
1135 #endif
1136 siop_lun->lun_flags |= SIOP_LUNF_FULL;
1137 siop_cmd->cmd_c.status = CMDST_READY;
1138 siop_setuptables(&siop_cmd->cmd_c);
1139 siop_table_sync(siop_cmd, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1140 TAILQ_INSERT_TAIL(&sc->urgent_list, siop_cmd, next);
1141 return;
1142 case SCSI_SIOP_NOCHECK:
1143
1144
1145
1146 break;
1147 case SCSI_SIOP_NOSTATUS:
1148
1149
1150
1151
1152 xs->error = XS_SELTIMEOUT;
1153 break;
1154 default:
1155 xs->error = XS_DRIVER_STUFFUP;
1156 }
1157 if (siop_cmd->cmd_c.status != CMDST_SENSE_DONE &&
1158 xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
1159 bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data, 0,
1160 siop_cmd->cmd_c.dmamap_data->dm_mapsize,
1161 (xs->flags & SCSI_DATA_IN) ?
1162 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1163 bus_dmamap_unload(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data);
1164 }
1165 if (siop_cmd->cmd_c.status == CMDST_SENSE) {
1166
1167 struct scsi_sense *cmd = (struct scsi_sense *)&siop_cmd->cmd_c.siop_tables->xscmd;
1168 int error;
1169 bzero(cmd, sizeof(*cmd));
1170 siop_cmd->cmd_c.siop_tables->cmd.count =
1171 siop_htoc32(&sc->sc_c, sizeof(struct scsi_sense));
1172 cmd->opcode = REQUEST_SENSE;
1173 cmd->byte2 = xs->sc_link->lun << 5;
1174 cmd->unused[0] = cmd->unused[1] = 0;
1175 cmd->length = sizeof(struct scsi_sense_data);
1176 cmd->control = 0;
1177 siop_cmd->cmd_c.flags &= ~CMDFL_TAG;
1178 error = bus_dmamap_load(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data,
1179 &xs->sense, sizeof(struct scsi_sense_data),
1180 NULL, BUS_DMA_NOWAIT);
1181 if (error) {
1182 printf("%s: unable to load data DMA map "
1183 "(for SENSE): %d\n",
1184 sc->sc_c.sc_dev.dv_xname, error);
1185 xs->error = XS_DRIVER_STUFFUP;
1186 goto out;
1187 }
1188 bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data,
1189 0, siop_cmd->cmd_c.dmamap_data->dm_mapsize,
1190 BUS_DMASYNC_PREREAD);
1191
1192 siop_setuptables(&siop_cmd->cmd_c);
1193 siop_table_sync(siop_cmd, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1194
1195 TAILQ_INSERT_HEAD(&sc->urgent_list, siop_cmd, next);
1196 return;
1197 } else if (siop_cmd->cmd_c.status == CMDST_SENSE_DONE) {
1198 bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data,
1199 0, siop_cmd->cmd_c.dmamap_data->dm_mapsize,
1200 BUS_DMASYNC_POSTREAD);
1201 bus_dmamap_unload(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data);
1202 }
1203 out:
1204 siop_lun->lun_flags &= ~SIOP_LUNF_FULL;
1205 xs->flags |= ITSDONE;
1206 siop_cmd->cmd_c.status = CMDST_FREE;
1207 TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
1208 #if 0
1209 if (xs->resid != 0)
1210 printf("resid %d datalen %d\n", xs->resid, xs->datalen);
1211 #endif
1212 scsi_done(xs);
1213 }
1214
1215
1216
1217
1218
1219 int
1220 siop_handle_qtag_reject(siop_cmd)
1221 struct siop_cmd *siop_cmd;
1222 {
1223 struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc;
1224 int target = siop_cmd->cmd_c.xs->sc_link->target;
1225 int lun = siop_cmd->cmd_c.xs->sc_link->lun;
1226 int tag = siop_cmd->cmd_tables->msg_out[2];
1227 struct siop_lun *siop_lun =
1228 ((struct siop_target*)sc->sc_c.targets[target])->siop_lun[lun];
1229
1230 #ifdef SIOP_DEBUG
1231 printf("%s:%d:%d: tag message %d (%d) rejected (status %d)\n",
1232 sc->sc_c.sc_dev.dv_xname, target, lun, tag, siop_cmd->cmd_c.tag,
1233 siop_cmd->cmd_c.status);
1234 #endif
1235
1236 if (siop_lun->siop_tag[0].active != NULL) {
1237 printf("%s: untagged command already running for target %d "
1238 "lun %d (status %d)\n", sc->sc_c.sc_dev.dv_xname,
1239 target, lun, siop_lun->siop_tag[0].active->cmd_c.status);
1240 return -1;
1241 }
1242
1243 siop_lun->siop_tag[tag].active = NULL;
1244
1245 siop_lun->siop_tag[0].active = siop_cmd;
1246 siop_cmd->cmd_c.tag = 0;
1247
1248 if (siop_lun->siop_tag[0].reseloff > 0) {
1249 siop_script_write(sc,
1250 siop_lun->siop_tag[0].reseloff + 1,
1251 siop_cmd->cmd_c.dsa + sizeof(struct siop_common_xfer) +
1252 Ent_ldsa_reload_dsa);
1253 siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);
1254 }
1255 return 0;
1256 }
1257
1258
1259
1260
1261
1262
1263
1264 void
1265 siop_handle_reset(sc)
1266 struct siop_softc *sc;
1267 {
1268 struct cmd_list reset_list;
1269 struct siop_cmd *siop_cmd, *next_siop_cmd;
1270 struct siop_lun *siop_lun;
1271 int target, lun, tag;
1272
1273
1274
1275
1276 printf("%s: scsi bus reset\n", sc->sc_c.sc_dev.dv_xname);
1277
1278 siop_reset(sc);
1279 TAILQ_INIT(&reset_list);
1280
1281
1282
1283 for (target = 0; target < sc->sc_c.sc_link.adapter_buswidth;
1284 target++) {
1285 if (sc->sc_c.targets[target] == NULL)
1286 continue;
1287 for (lun = 0; lun < 8; lun++) {
1288 struct siop_target *siop_target =
1289 (struct siop_target *)sc->sc_c.targets[target];
1290 siop_lun = siop_target->siop_lun[lun];
1291 if (siop_lun == NULL)
1292 continue;
1293 siop_lun->lun_flags &= ~SIOP_LUNF_FULL;
1294 for (tag = 0; tag <
1295 ((sc->sc_c.targets[target]->flags & TARF_TAG) ?
1296 SIOP_NTAG : 1);
1297 tag++) {
1298 siop_cmd = siop_lun->siop_tag[tag].active;
1299 if (siop_cmd == NULL)
1300 continue;
1301 siop_lun->siop_tag[tag].active = NULL;
1302 TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);
1303 sc_print_addr(siop_cmd->cmd_c.xs->sc_link);
1304 printf("cmd %p (tag %d) added to reset list\n",
1305 siop_cmd, tag);
1306 }
1307 }
1308 if (sc->sc_c.targets[target]->status != TARST_PROBING) {
1309 sc->sc_c.targets[target]->status = TARST_ASYNC;
1310 sc->sc_c.targets[target]->flags &= ~TARF_ISWIDE;
1311 sc->sc_c.targets[target]->period =
1312 sc->sc_c.targets[target]->offset = 0;
1313 siop_update_xfer_mode(&sc->sc_c, target);
1314 }
1315 }
1316
1317 for (siop_cmd = TAILQ_FIRST(&sc->urgent_list); siop_cmd != NULL;
1318 siop_cmd = next_siop_cmd) {
1319 next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
1320 TAILQ_REMOVE(&sc->urgent_list, siop_cmd, next);
1321 TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);
1322 sc_print_addr(siop_cmd->cmd_c.xs->sc_link);
1323 printf("cmd %p added to reset list from urgent list\n",
1324 siop_cmd);
1325 }
1326
1327 for (siop_cmd = TAILQ_FIRST(&sc->ready_list); siop_cmd != NULL;
1328 siop_cmd = next_siop_cmd) {
1329 next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
1330 TAILQ_REMOVE(&sc->ready_list, siop_cmd, next);
1331 TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);
1332 sc_print_addr(siop_cmd->cmd_c.xs->sc_link);
1333 printf("cmd %p added to reset list from ready list\n",
1334 siop_cmd);
1335 }
1336
1337 for (siop_cmd = TAILQ_FIRST(&reset_list); siop_cmd != NULL;
1338 siop_cmd = next_siop_cmd) {
1339 next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
1340 siop_cmd->cmd_c.flags &= ~CMDFL_TAG;
1341 siop_cmd->cmd_c.xs->error =
1342 (siop_cmd->cmd_c.flags & CMDFL_TIMEOUT)
1343 ? XS_TIMEOUT : XS_RESET;
1344 siop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK;
1345 sc_print_addr(siop_cmd->cmd_c.xs->sc_link);
1346 printf("cmd %p (status %d) reset",
1347 siop_cmd, siop_cmd->cmd_c.status);
1348 if (siop_cmd->cmd_c.status == CMDST_SENSE ||
1349 siop_cmd->cmd_c.status == CMDST_SENSE_ACTIVE)
1350 siop_cmd->cmd_c.status = CMDST_SENSE_DONE;
1351 else
1352 siop_cmd->cmd_c.status = CMDST_DONE;
1353 printf(" with status %d, xs->error %d\n",
1354 siop_cmd->cmd_c.status, siop_cmd->cmd_c.xs->error);
1355 TAILQ_REMOVE(&reset_list, siop_cmd, next);
1356 siop_scsicmd_end(siop_cmd);
1357 }
1358 }
1359
1360 int
1361 siop_scsicmd(xs)
1362 struct scsi_xfer *xs;
1363 {
1364 struct siop_softc *sc = (struct siop_softc *)xs->sc_link->adapter_softc;
1365 struct siop_cmd *siop_cmd;
1366 struct siop_target *siop_target;
1367 int s, error, i, j;
1368 const int target = xs->sc_link->target;
1369 const int lun = xs->sc_link->lun;
1370
1371 s = splbio();
1372 #ifdef SIOP_DEBUG_SCHED
1373 printf("starting cmd for %d:%d\n", target, lun);
1374 #endif
1375 siop_cmd = TAILQ_FIRST(&sc->free_list);
1376 if (siop_cmd == NULL) {
1377 splx(s);
1378 return(TRY_AGAIN_LATER);
1379 }
1380 TAILQ_REMOVE(&sc->free_list, siop_cmd, next);
1381
1382
1383 timeout_set(&xs->stimeout, siop_timeout, siop_cmd);
1384
1385 #ifdef DIAGNOSTIC
1386 if (siop_cmd->cmd_c.status != CMDST_FREE)
1387 panic("siop_scsicmd: new cmd not free");
1388 #endif
1389 siop_target = (struct siop_target*)sc->sc_c.targets[target];
1390 if (siop_target == NULL) {
1391 #ifdef SIOP_DEBUG
1392 printf("%s: alloc siop_target for target %d\n",
1393 sc->sc_c.sc_dev.dv_xname, target);
1394 #endif
1395 sc->sc_c.targets[target] =
1396 malloc(sizeof(struct siop_target),
1397 M_DEVBUF, M_NOWAIT);
1398 if (sc->sc_c.targets[target] == NULL) {
1399 printf("%s: can't malloc memory for "
1400 "target %d\n", sc->sc_c.sc_dev.dv_xname,
1401 target);
1402 splx(s);
1403 return(TRY_AGAIN_LATER);
1404 }
1405 bzero(sc->sc_c.targets[target], sizeof(struct siop_target));
1406 siop_target =
1407 (struct siop_target*)sc->sc_c.targets[target];
1408 siop_target->target_c.status = TARST_PROBING;
1409 siop_target->target_c.flags = 0;
1410 siop_target->target_c.id =
1411 sc->sc_c.clock_div << 24;
1412 siop_target->target_c.id |= target << 16;
1413
1414
1415
1416 siop_target->lunsw = siop_get_lunsw(sc);
1417 if (siop_target->lunsw == NULL) {
1418 printf("%s: can't alloc lunsw for target %d\n",
1419 sc->sc_c.sc_dev.dv_xname, target);
1420 splx(s);
1421 return(TRY_AGAIN_LATER);
1422 }
1423 for (i=0; i < 8; i++)
1424 siop_target->siop_lun[i] = NULL;
1425 siop_add_reselsw(sc, target);
1426 }
1427 if (siop_target->siop_lun[lun] == NULL) {
1428 siop_target->siop_lun[lun] =
1429 malloc(sizeof(struct siop_lun), M_DEVBUF,
1430 M_NOWAIT);
1431 if (siop_target->siop_lun[lun] == NULL) {
1432 printf("%s: can't alloc siop_lun for "
1433 "target %d lun %d\n",
1434 sc->sc_c.sc_dev.dv_xname, target, lun);
1435 splx(s);
1436 return(TRY_AGAIN_LATER);
1437 }
1438 bzero(siop_target->siop_lun[lun], sizeof(struct siop_lun));
1439 }
1440 siop_cmd->cmd_c.siop_target = sc->sc_c.targets[target];
1441 siop_cmd->cmd_c.xs = xs;
1442 siop_cmd->cmd_c.flags = 0;
1443 siop_cmd->cmd_c.status = CMDST_READY;
1444
1445 bzero(&siop_cmd->cmd_c.siop_tables->xscmd,
1446 sizeof(siop_cmd->cmd_c.siop_tables->xscmd));
1447 bcopy(xs->cmd, &siop_cmd->cmd_c.siop_tables->xscmd, xs->cmdlen);
1448 siop_cmd->cmd_c.siop_tables->cmd.count =
1449 siop_htoc32(&sc->sc_c, xs->cmdlen);
1450
1451
1452 if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
1453 error = bus_dmamap_load(sc->sc_c.sc_dmat,
1454 siop_cmd->cmd_c.dmamap_data, xs->data, xs->datalen,
1455 NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
1456 ((xs->flags & SCSI_DATA_IN) ?
1457 BUS_DMA_READ : BUS_DMA_WRITE));
1458 if (error) {
1459 printf("%s: unable to load data DMA map: %d\n",
1460 sc->sc_c.sc_dev.dv_xname, error);
1461 splx(s);
1462 return(TRY_AGAIN_LATER);
1463 }
1464 bus_dmamap_sync(sc->sc_c.sc_dmat,
1465 siop_cmd->cmd_c.dmamap_data, 0,
1466 siop_cmd->cmd_c.dmamap_data->dm_mapsize,
1467 (xs->flags & SCSI_DATA_IN) ?
1468 BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
1469 }
1470
1471 siop_setuptables(&siop_cmd->cmd_c);
1472 siop_cmd->saved_offset = SIOP_NOOFFSET;
1473 siop_table_sync(siop_cmd,
1474 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1475
1476 TAILQ_INSERT_TAIL(&sc->ready_list, siop_cmd, next);
1477
1478
1479 if (((xs->flags & SCSI_POLL) == 0) &&
1480 siop_target->target_c.status == TARST_PROBING)
1481 siop_target->target_c.status = TARST_ASYNC;
1482
1483 siop_start(sc);
1484 if ((xs->flags & SCSI_POLL) == 0) {
1485 splx(s);
1486 return (SUCCESSFULLY_QUEUED);
1487 }
1488
1489
1490 for(i = xs->timeout; i > 0; i--) {
1491 siop_intr(sc);
1492 if ((xs->flags & ITSDONE) == 0) {
1493 delay(1000);
1494 continue;
1495 }
1496 if (xs->cmd->opcode == INQUIRY && xs->error == XS_NOERROR) {
1497 struct scsi_inquiry_data *inqbuf =
1498 (struct scsi_inquiry_data *)xs->data;
1499 if ((inqbuf->device & SID_QUAL) == SID_QUAL_BAD_LU)
1500 break;
1501
1502
1503
1504
1505
1506
1507 for (j = 0; j < SIOP_NTAG; j += SIOP_NCMDPB)
1508 siop_morecbd(sc);
1509
1510
1511
1512
1513
1514 if ((lun == 0) && (sc->sc_c.features & SF_BUS_ULTRA3))
1515 sc->sc_c.targets[target]->flags |= TARF_DT;
1516
1517
1518
1519
1520
1521 if (lun > 0)
1522 siop_add_dev(sc, target, lun);
1523 }
1524 break;
1525 }
1526 if (i == 0) {
1527 siop_timeout(siop_cmd);
1528 while ((xs->flags & ITSDONE) == 0)
1529 siop_intr(sc);
1530 }
1531
1532 splx(s);
1533 return (COMPLETE);
1534 }
1535
1536 void
1537 siop_start(sc)
1538 struct siop_softc *sc;
1539 {
1540 struct siop_cmd *siop_cmd, *next_siop_cmd;
1541 struct siop_lun *siop_lun;
1542 struct siop_xfer *siop_xfer;
1543 u_int32_t dsa;
1544 int timeout;
1545 int target, lun, tag, slot;
1546 int newcmd = 0;
1547 int doingready = 0;
1548
1549
1550
1551
1552 siop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565 slot = sc->sc_currschedslot;
1566
1567
1568
1569
1570
1571
1572 if (siop_script_read(sc, (Ent_script_sched_slot0 / 4) + slot * 2) ==
1573 0x80000000) {
1574 slot = sc->sc_currschedslot = 1;
1575 } else {
1576 slot++;
1577 }
1578
1579 siop_cmd = TAILQ_FIRST(&sc->urgent_list);
1580 again:
1581 for (; siop_cmd != NULL; siop_cmd = next_siop_cmd) {
1582 next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
1583 #ifdef DIAGNOSTIC
1584 if (siop_cmd->cmd_c.status != CMDST_READY &&
1585 siop_cmd->cmd_c.status != CMDST_SENSE)
1586 panic("siop: non-ready cmd in ready list");
1587 #endif
1588 target = siop_cmd->cmd_c.xs->sc_link->target;
1589 lun = siop_cmd->cmd_c.xs->sc_link->lun;
1590 siop_lun =
1591 ((struct siop_target*)sc->sc_c.targets[target])->siop_lun[lun];
1592
1593 if (siop_lun->siop_tag[0].active != NULL)
1594 continue;
1595
1596
1597
1598
1599 if ((siop_lun->lun_flags & SIOP_LUNF_FULL) &&
1600 siop_cmd->cmd_c.status == CMDST_READY)
1601 continue;
1602
1603 if (siop_cmd->cmd_c.flags & CMDFL_TAG) {
1604 for (tag = 1; tag < SIOP_NTAG; tag++) {
1605 if (siop_lun->siop_tag[tag].active == NULL)
1606 break;
1607 }
1608 if (tag == SIOP_NTAG)
1609 continue;
1610 } else {
1611 tag = 0;
1612 }
1613 siop_cmd->cmd_c.tag = tag;
1614
1615
1616
1617
1618 if (siop_cmd->cmd_c.status != CMDST_SENSE) {
1619 for (; slot < SIOP_NSLOTS; slot++) {
1620
1621
1622
1623 if (siop_script_read(sc,
1624 (Ent_script_sched_slot0 / 4) + slot * 2) ==
1625 0x80000000)
1626 break;
1627 }
1628
1629 if (slot == SIOP_NSLOTS) {
1630 goto end;
1631 }
1632 } else {
1633 slot = 0;
1634 if (siop_script_read(sc, Ent_script_sched_slot0 / 4)
1635 != 0x80000000)
1636 goto end;
1637 }
1638
1639 #ifdef SIOP_DEBUG_SCHED
1640 printf("using slot %d for DSA 0x%lx\n", slot,
1641 (u_long)siop_cmd->cmd_c.dsa);
1642 #endif
1643
1644 if (tag > 0) {
1645 #ifdef DIAGNOSTIC
1646 int msgcount = siop_ctoh32(&sc->sc_c,
1647 siop_cmd->cmd_tables->t_msgout.count);
1648 if (msgcount != 1)
1649 printf("%s:%d:%d: tag %d with msgcount %d\n",
1650 sc->sc_c.sc_dev.dv_xname, target, lun, tag,
1651 msgcount);
1652 #endif
1653 if (siop_cmd->cmd_c.xs->bp != NULL &&
1654 (siop_cmd->cmd_c.xs->bp->b_flags & B_ASYNC))
1655 siop_cmd->cmd_tables->msg_out[1] =
1656 MSG_SIMPLE_Q_TAG;
1657 else
1658 siop_cmd->cmd_tables->msg_out[1] =
1659 MSG_ORDERED_Q_TAG;
1660 siop_cmd->cmd_tables->msg_out[2] = tag;
1661 siop_cmd->cmd_tables->t_msgout.count =
1662 siop_htoc32(&sc->sc_c, 3);
1663 }
1664
1665 newcmd = 1;
1666
1667 if (siop_cmd->cmd_c.status == CMDST_READY) {
1668 siop_cmd->cmd_c.status = CMDST_ACTIVE;
1669 } else if (siop_cmd->cmd_c.status == CMDST_SENSE) {
1670 siop_cmd->cmd_c.status = CMDST_SENSE_ACTIVE;
1671 } else
1672 panic("siop_start: bad status");
1673 if (doingready)
1674 TAILQ_REMOVE(&sc->ready_list, siop_cmd, next);
1675 else
1676 TAILQ_REMOVE(&sc->urgent_list, siop_cmd, next);
1677 siop_lun->siop_tag[tag].active = siop_cmd;
1678
1679 dsa = siop_cmd->cmd_c.dsa;
1680
1681 if (siop_lun->siop_tag[tag].reseloff > 0)
1682 siop_script_write(sc,
1683 siop_lun->siop_tag[tag].reseloff + 1,
1684 dsa + sizeof(struct siop_common_xfer) +
1685 Ent_ldsa_reload_dsa);
1686
1687 siop_xfer = (struct siop_xfer*)siop_cmd->cmd_tables;
1688 siop_xfer->resel[E_ldsa_abs_slot_Used[0]] =
1689 siop_htoc32(&sc->sc_c, sc->sc_c.sc_scriptaddr +
1690 Ent_script_sched_slot0 + slot * 8);
1691 siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);
1692
1693 siop_script_write(sc,
1694 (Ent_script_sched_slot0 / 4) + slot * 2 + 1,
1695 dsa + sizeof(struct siop_common_xfer) + Ent_ldsa_select);
1696
1697 if (siop_cmd->cmd_c.status == CMDST_ACTIVE) {
1698 if ((siop_cmd->cmd_c.xs->flags & SCSI_POLL) == 0) {
1699
1700 timeout = (u_int64_t) siop_cmd->cmd_c.xs->timeout *
1701 (u_int64_t)hz / 1000;
1702 if (timeout == 0)
1703 timeout = 1;
1704 timeout_add(&siop_cmd->cmd_c.xs->stimeout, timeout);
1705 }
1706 }
1707
1708
1709
1710 siop_script_write(sc, (Ent_script_sched_slot0 / 4) + slot * 2,
1711 0x80080000);
1712
1713 if (slot == 0)
1714 goto end;
1715 sc->sc_currschedslot = slot;
1716 slot++;
1717 }
1718 if (doingready == 0) {
1719
1720 doingready = 1;
1721 siop_cmd = TAILQ_FIRST(&sc->ready_list);
1722 goto again;
1723 }
1724
1725 end:
1726
1727 if (newcmd == 0)
1728 return;
1729
1730 siop_script_sync(sc,BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1731
1732 bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
1733 SIOP_ISTAT, ISTAT_SIGP);
1734
1735 return;
1736 }
1737
1738 void
1739 siop_timeout(v)
1740 void *v;
1741 {
1742 struct siop_cmd *siop_cmd = v;
1743 struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc;
1744 int s;
1745
1746
1747 timeout_del(&siop_cmd->cmd_c.xs->stimeout);
1748
1749 sc_print_addr(siop_cmd->cmd_c.xs->sc_link);
1750 printf("timeout on SCSI command 0x%x\n",
1751 siop_cmd->cmd_c.xs->cmd->opcode);
1752
1753 s = splbio();
1754
1755 siop_resetbus(&sc->sc_c);
1756 siop_cmd->cmd_c.flags |= CMDFL_TIMEOUT;
1757 siop_handle_reset(sc);
1758 splx(s);
1759
1760 return;
1761 }
1762
1763 #ifdef DUMP_SCRIPT
1764 void
1765 siop_dump_script(sc)
1766 struct siop_softc *sc;
1767 {
1768 int i;
1769 for (i = 0; i < PAGE_SIZE / 4; i += 2) {
1770 printf("0x%04x: 0x%08x 0x%08x", i * 4,
1771 siop_ctoh32(&sc->sc_c, sc->sc_c.sc_script[i]),
1772 siop_ctoh32(&sc->sc_c, sc->sc_c.sc_script[i+1]));
1773 if ((siop_ctoh32(&sc->sc_c,
1774 sc->sc_c.sc_script[i]) & 0xe0000000) == 0xc0000000) {
1775 i++;
1776 printf(" 0x%08x", siop_ctoh32(&sc->sc_c,
1777 sc->sc_c.sc_script[i+1]));
1778 }
1779 printf("\n");
1780 }
1781 }
1782 #endif
1783
1784 void
1785 siop_morecbd(sc)
1786 struct siop_softc *sc;
1787 {
1788 int error, off, i, j, s;
1789 bus_dma_segment_t seg;
1790 int rseg;
1791 struct siop_cbd *newcbd;
1792 struct siop_xfer *xfer;
1793 bus_addr_t dsa;
1794 u_int32_t *scr;
1795
1796
1797 newcbd = malloc(sizeof(struct siop_cbd), M_DEVBUF, M_NOWAIT);
1798 if (newcbd == NULL) {
1799 printf("%s: can't allocate memory for command descriptors "
1800 "head\n", sc->sc_c.sc_dev.dv_xname);
1801 return;
1802 }
1803 bzero(newcbd, sizeof(struct siop_cbd));
1804
1805
1806 newcbd->cmds = malloc(sizeof(struct siop_cmd) * SIOP_NCMDPB,
1807 M_DEVBUF, M_NOWAIT);
1808 if (newcbd->cmds == NULL) {
1809 printf("%s: can't allocate memory for command descriptors\n",
1810 sc->sc_c.sc_dev.dv_xname);
1811 goto bad3;
1812 }
1813 bzero(newcbd->cmds, sizeof(struct siop_cmd) * SIOP_NCMDPB);
1814 error = bus_dmamem_alloc(sc->sc_c.sc_dmat, PAGE_SIZE, PAGE_SIZE, 0, &seg,
1815 1, &rseg, BUS_DMA_NOWAIT);
1816 if (error) {
1817 printf("%s: unable to allocate cbd DMA memory, error = %d\n",
1818 sc->sc_c.sc_dev.dv_xname, error);
1819 goto bad2;
1820 }
1821 error = bus_dmamem_map(sc->sc_c.sc_dmat, &seg, rseg, PAGE_SIZE,
1822 (caddr_t *)&newcbd->xfers, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
1823 if (error) {
1824 printf("%s: unable to map cbd DMA memory, error = %d\n",
1825 sc->sc_c.sc_dev.dv_xname, error);
1826 goto bad2;
1827 }
1828 error = bus_dmamap_create(sc->sc_c.sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0,
1829 BUS_DMA_NOWAIT, &newcbd->xferdma);
1830 if (error) {
1831 printf("%s: unable to create cbd DMA map, error = %d\n",
1832 sc->sc_c.sc_dev.dv_xname, error);
1833 goto bad1;
1834 }
1835 error = bus_dmamap_load(sc->sc_c.sc_dmat, newcbd->xferdma, newcbd->xfers,
1836 PAGE_SIZE, NULL, BUS_DMA_NOWAIT);
1837 if (error) {
1838 printf("%s: unable to load cbd DMA map, error = %d\n",
1839 sc->sc_c.sc_dev.dv_xname, error);
1840 goto bad0;
1841 }
1842 #ifdef SIOP_DEBUG
1843 printf("%s: alloc newcdb at PHY addr 0x%lx\n", sc->sc_c.sc_dev.dv_xname,
1844 (unsigned long)newcbd->xferdma->dm_segs[0].ds_addr);
1845 #endif
1846 for (i = 0; i < SIOP_NCMDPB; i++) {
1847 error = bus_dmamap_create(sc->sc_c.sc_dmat, MAXPHYS, SIOP_NSG,
1848 MAXPHYS, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
1849 &newcbd->cmds[i].cmd_c.dmamap_data);
1850 if (error) {
1851 printf("%s: unable to create data DMA map for cbd: "
1852 "error %d\n",
1853 sc->sc_c.sc_dev.dv_xname, error);
1854 goto bad0;
1855 }
1856 }
1857
1858
1859 off = (sc->sc_c.features & SF_CHIP_BE) ? 3 : 0;
1860 for (i = 0; i < SIOP_NCMDPB; i++) {
1861 newcbd->cmds[i].cmd_c.siop_sc = &sc->sc_c;
1862 newcbd->cmds[i].siop_cbdp = newcbd;
1863 xfer = &newcbd->xfers[i];
1864 newcbd->cmds[i].cmd_tables = (struct siop_common_xfer *)xfer;
1865 bzero(newcbd->cmds[i].cmd_tables, sizeof(struct siop_xfer));
1866 dsa = newcbd->xferdma->dm_segs[0].ds_addr +
1867 i * sizeof(struct siop_xfer);
1868 newcbd->cmds[i].cmd_c.dsa = dsa;
1869 newcbd->cmds[i].cmd_c.status = CMDST_FREE;
1870 xfer->siop_tables.t_msgout.count= siop_htoc32(&sc->sc_c, 1);
1871 xfer->siop_tables.t_msgout.addr = siop_htoc32(&sc->sc_c, dsa);
1872 xfer->siop_tables.t_msgin.count= siop_htoc32(&sc->sc_c, 1);
1873 xfer->siop_tables.t_msgin.addr = siop_htoc32(&sc->sc_c,
1874 dsa + offsetof(struct siop_common_xfer, msg_in));
1875 xfer->siop_tables.t_extmsgin.count= siop_htoc32(&sc->sc_c, 2);
1876 xfer->siop_tables.t_extmsgin.addr = siop_htoc32(&sc->sc_c,
1877 dsa + offsetof(struct siop_common_xfer, msg_in) + 1);
1878 xfer->siop_tables.t_extmsgdata.addr = siop_htoc32(&sc->sc_c,
1879 dsa + offsetof(struct siop_common_xfer, msg_in) + 3);
1880 xfer->siop_tables.t_status.count= siop_htoc32(&sc->sc_c, 1);
1881 xfer->siop_tables.t_status.addr = siop_htoc32(&sc->sc_c,
1882 dsa + offsetof(struct siop_common_xfer, status) + off);
1883 xfer->siop_tables.cmd.count = siop_htoc32(&sc->sc_c, 0);
1884 xfer->siop_tables.cmd.addr = siop_htoc32(&sc->sc_c,
1885 dsa + offsetof(struct siop_common_xfer, xscmd));
1886
1887 scr = &xfer->resel[0];
1888 for (j = 0; j < sizeof(load_dsa) / sizeof(load_dsa[0]); j++)
1889 scr[j] = siop_htoc32(&sc->sc_c, load_dsa[j]);
1890
1891
1892
1893
1894 scr[Ent_rdsa0 / 4] = siop_htoc32(&sc->sc_c,
1895 0x78100000 | ((dsa & 0x000000ff) << 8));
1896 scr[Ent_rdsa1 / 4] = siop_htoc32(&sc->sc_c,
1897 0x78110000 | ( dsa & 0x0000ff00 ));
1898 scr[Ent_rdsa2 / 4] = siop_htoc32(&sc->sc_c,
1899 0x78120000 | ((dsa & 0x00ff0000) >> 8));
1900 scr[Ent_rdsa3 / 4] = siop_htoc32(&sc->sc_c,
1901 0x78130000 | ((dsa & 0xff000000) >> 16));
1902 scr[E_ldsa_abs_reselected_Used[0]] = siop_htoc32(&sc->sc_c,
1903 sc->sc_c.sc_scriptaddr + Ent_reselected);
1904 scr[E_ldsa_abs_reselect_Used[0]] = siop_htoc32(&sc->sc_c,
1905 sc->sc_c.sc_scriptaddr + Ent_reselect);
1906 scr[E_ldsa_abs_selected_Used[0]] = siop_htoc32(&sc->sc_c,
1907 sc->sc_c.sc_scriptaddr + Ent_selected);
1908 scr[E_ldsa_abs_data_Used[0]] = siop_htoc32(&sc->sc_c,
1909 dsa + sizeof(struct siop_common_xfer) + Ent_ldsa_data);
1910
1911 scr[Ent_ldsa_data / 4] = siop_htoc32(&sc->sc_c, 0x80000000);
1912 s = splbio();
1913 TAILQ_INSERT_TAIL(&sc->free_list, &newcbd->cmds[i], next);
1914 splx(s);
1915 #ifdef SIOP_DEBUG
1916 printf("tables[%d]: in=0x%x out=0x%x status=0x%x "
1917 "offset=0x%x\n", i,
1918 siop_ctoh32(&sc->sc_c,
1919 newcbd->cmds[i].cmd_tables->t_msgin.addr),
1920 siop_ctoh32(&sc->sc_c,
1921 newcbd->cmds[i].cmd_tables->t_msgout.addr),
1922 siop_ctoh32(&sc->sc_c,
1923 newcbd->cmds[i].cmd_tables->t_status.addr));
1924 #endif
1925 }
1926 s = splbio();
1927 TAILQ_INSERT_TAIL(&sc->cmds, newcbd, next);
1928 splx(s);
1929 return;
1930 bad0:
1931 bus_dmamap_unload(sc->sc_c.sc_dmat, newcbd->xferdma);
1932 bus_dmamap_destroy(sc->sc_c.sc_dmat, newcbd->xferdma);
1933 bad1:
1934 bus_dmamem_free(sc->sc_c.sc_dmat, &seg, rseg);
1935 bad2:
1936 free(newcbd->cmds, M_DEVBUF);
1937 bad3:
1938 free(newcbd, M_DEVBUF);
1939 return;
1940 }
1941
1942 struct siop_lunsw *
1943 siop_get_lunsw(sc)
1944 struct siop_softc *sc;
1945 {
1946 struct siop_lunsw *lunsw;
1947 int i;
1948
1949 if (sc->script_free_lo + (sizeof(lun_switch) / sizeof(lun_switch[0])) >=
1950 sc->script_free_hi)
1951 return NULL;
1952 lunsw = TAILQ_FIRST(&sc->lunsw_list);
1953 if (lunsw != NULL) {
1954 #ifdef SIOP_DEBUG
1955 printf("siop_get_lunsw got lunsw at offset %d\n",
1956 lunsw->lunsw_off);
1957 #endif
1958 TAILQ_REMOVE(&sc->lunsw_list, lunsw, next);
1959 return lunsw;
1960 }
1961 lunsw = malloc(sizeof(struct siop_lunsw), M_DEVBUF, M_NOWAIT);
1962 if (lunsw == NULL)
1963 return NULL;
1964 bzero(lunsw, sizeof(struct siop_lunsw));
1965 #ifdef SIOP_DEBUG
1966 printf("allocating lunsw at offset %d\n", sc->script_free_lo);
1967 #endif
1968 if (sc->sc_c.features & SF_CHIP_RAM) {
1969 bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
1970 sc->script_free_lo * 4, lun_switch,
1971 sizeof(lun_switch) / sizeof(lun_switch[0]));
1972 bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
1973 (sc->script_free_lo + E_abs_lunsw_return_Used[0]) * 4,
1974 sc->sc_c.sc_scriptaddr + Ent_lunsw_return);
1975 } else {
1976 for (i = 0; i < sizeof(lun_switch) / sizeof(lun_switch[0]);
1977 i++)
1978 sc->sc_c.sc_script[sc->script_free_lo + i] =
1979 siop_htoc32(&sc->sc_c, lun_switch[i]);
1980 sc->sc_c.sc_script[
1981 sc->script_free_lo + E_abs_lunsw_return_Used[0]] =
1982 siop_htoc32(&sc->sc_c,
1983 sc->sc_c.sc_scriptaddr + Ent_lunsw_return);
1984 }
1985 lunsw->lunsw_off = sc->script_free_lo;
1986 lunsw->lunsw_size = sizeof(lun_switch) / sizeof(lun_switch[0]);
1987 sc->script_free_lo += lunsw->lunsw_size;
1988 siop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1989 return lunsw;
1990 }
1991
1992 void
1993 siop_add_reselsw(sc, target)
1994 struct siop_softc *sc;
1995 int target;
1996 {
1997 int i,j;
1998 struct siop_target *siop_target;
1999 struct siop_lun *siop_lun;
2000
2001 siop_target = (struct siop_target *)sc->sc_c.targets[target];
2002
2003
2004
2005 siop_script_sync(sc, BUS_DMASYNC_POSTWRITE);
2006 for (i = 0; i < 15; i++) {
2007 siop_target->reseloff = Ent_resel_targ0 / 4 + i * 2;
2008 if ((siop_script_read(sc, siop_target->reseloff) & 0xff)
2009 == 0xff) {
2010 #ifdef SIOP_DEBUG
2011 printf("siop: target %d slot %d offset %d\n",
2012 target, i, siop_target->reseloff);
2013 #endif
2014
2015 siop_script_write(sc, siop_target->reseloff,
2016 0x800c0080 | target);
2017 siop_script_write(sc, siop_target->reseloff + 1,
2018 sc->sc_c.sc_scriptaddr +
2019 siop_target->lunsw->lunsw_off * 4 +
2020 Ent_lun_switch_entry);
2021 break;
2022 }
2023 }
2024 if (i == 15)
2025 panic("siop: resel switch full");
2026
2027 sc->sc_ntargets++;
2028 for (i = 0; i < 8; i++) {
2029 siop_lun = siop_target->siop_lun[i];
2030 if (siop_lun == NULL)
2031 continue;
2032 if (siop_lun->reseloff > 0) {
2033 siop_lun->reseloff = 0;
2034 for (j = 0; j < SIOP_NTAG; j++)
2035 siop_lun->siop_tag[j].reseloff = 0;
2036 siop_add_dev(sc, target, i);
2037 }
2038 }
2039 siop_update_scntl3(sc, sc->sc_c.targets[target]);
2040 siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
2041 }
2042
2043 void
2044 siop_update_scntl3(sc, _siop_target)
2045 struct siop_softc *sc;
2046 struct siop_common_target *_siop_target;
2047 {
2048 struct siop_target *siop_target = (struct siop_target *)_siop_target;
2049
2050 siop_script_write(sc,
2051 siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4),
2052 0x78030000 | ((siop_target->target_c.id >> 16) & 0x0000ff00));
2053
2054 siop_script_write(sc,
2055 siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4) + 2,
2056 0x78050000 | (siop_target->target_c.id & 0x0000ff00));
2057 siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
2058 }
2059
2060 void
2061 siop_add_dev(sc, target, lun)
2062 struct siop_softc *sc;
2063 int target;
2064 int lun;
2065 {
2066 struct siop_lunsw *lunsw;
2067 struct siop_target *siop_target =
2068 (struct siop_target *)sc->sc_c.targets[target];
2069 struct siop_lun *siop_lun = siop_target->siop_lun[lun];
2070 int i, ntargets;
2071
2072 if (siop_lun->reseloff > 0)
2073 return;
2074 lunsw = siop_target->lunsw;
2075 if ((lunsw->lunsw_off + lunsw->lunsw_size) < sc->script_free_lo) {
2076
2077
2078
2079
2080 #ifdef SIOP_DEBUG
2081 printf("%s:%d:%d: can't allocate a lun sw slot\n",
2082 sc->sc_c.sc_dev.dv_xname, target, lun);
2083 #endif
2084 return;
2085 }
2086
2087 ntargets = (sc->sc_c.sc_link.adapter_buswidth - 1) - 1 - sc->sc_ntargets;
2088
2089
2090
2091
2092
2093
2094
2095 if (sc->script_free_lo + 2 +
2096 (ntargets * sizeof(lun_switch) / sizeof(lun_switch[0])) >=
2097 ((siop_target->target_c.flags & TARF_TAG) ?
2098 sc->script_free_hi - (sizeof(tag_switch) / sizeof(tag_switch[0])) :
2099 sc->script_free_hi)) {
2100
2101
2102
2103
2104 #ifdef SIOP_DEBUG
2105 printf("%s:%d:%d: not enough memory for a lun sw slot\n",
2106 sc->sc_c.sc_dev.dv_xname, target, lun);
2107 #endif
2108 return;
2109 }
2110 #ifdef SIOP_DEBUG
2111 printf("%s:%d:%d: allocate lun sw entry\n",
2112 sc->sc_c.sc_dev.dv_xname, target, lun);
2113 #endif
2114
2115 siop_script_write(sc, sc->script_free_lo, 0x98080000);
2116 siop_script_write(sc, sc->script_free_lo + 1, A_int_resellun);
2117
2118 siop_script_write(sc, sc->script_free_lo - 2,
2119 0x800c0000 | lun);
2120 siop_script_write(sc, sc->script_free_lo - 1, 0);
2121 siop_lun->reseloff = sc->script_free_lo - 2;
2122 lunsw->lunsw_size += 2;
2123 sc->script_free_lo += 2;
2124 if (siop_target->target_c.flags & TARF_TAG) {
2125
2126 sc->script_free_hi -=
2127 sizeof(tag_switch) / sizeof(tag_switch[0]);
2128 if (sc->sc_c.features & SF_CHIP_RAM) {
2129 bus_space_write_region_4(sc->sc_c.sc_ramt,
2130 sc->sc_c.sc_ramh,
2131 sc->script_free_hi * 4, tag_switch,
2132 sizeof(tag_switch) / sizeof(tag_switch[0]));
2133 } else {
2134 for(i = 0;
2135 i < sizeof(tag_switch) / sizeof(tag_switch[0]);
2136 i++) {
2137 sc->sc_c.sc_script[sc->script_free_hi + i] =
2138 siop_htoc32(&sc->sc_c, tag_switch[i]);
2139 }
2140 }
2141 siop_script_write(sc,
2142 siop_lun->reseloff + 1,
2143 sc->sc_c.sc_scriptaddr + sc->script_free_hi * 4 +
2144 Ent_tag_switch_entry);
2145
2146 for (i = 0; i < SIOP_NTAG; i++) {
2147 siop_lun->siop_tag[i].reseloff =
2148 sc->script_free_hi + (Ent_resel_tag0 / 4) + i * 2;
2149 }
2150 } else {
2151
2152 siop_lun->siop_tag[0].reseloff =
2153 siop_target->siop_lun[lun]->reseloff;
2154 }
2155 siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
2156 }
2157
2158 void
2159 siop_del_dev(sc, target, lun)
2160 struct siop_softc *sc;
2161 int target;
2162 int lun;
2163 {
2164 int i;
2165 struct siop_target *siop_target;
2166 #ifdef SIOP_DEBUG
2167 printf("%s:%d:%d: free lun sw entry\n",
2168 sc->sc_c.sc_dev.dv_xname, target, lun);
2169 #endif
2170 if (sc->sc_c.targets[target] == NULL)
2171 return;
2172 siop_target = (struct siop_target *)sc->sc_c.targets[target];
2173 free(siop_target->siop_lun[lun], M_DEVBUF);
2174 siop_target->siop_lun[lun] = NULL;
2175
2176
2177 for (i = 0; i < 8; i++) {
2178 if (siop_target->siop_lun[i] != NULL)
2179 return;
2180 }
2181 #ifdef SIOP_DEBUG
2182 printf("%s: free siop_target for target %d lun %d lunsw offset %d\n",
2183 sc->sc_c.sc_dev.dv_xname, target, lun,
2184 siop_target->lunsw->lunsw_off);
2185 #endif
2186
2187
2188
2189
2190 siop_script_write(sc, siop_target->reseloff, 0x800c00ff);
2191 siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
2192 TAILQ_INSERT_TAIL(&sc->lunsw_list, siop_target->lunsw, next);
2193 free(sc->sc_c.targets[target], M_DEVBUF);
2194 sc->sc_c.targets[target] = NULL;
2195 sc->sc_ntargets--;
2196 }
2197
2198 #ifdef SIOP_STATS
2199 void
2200 siop_printstats()
2201 {
2202 printf("siop_stat_intr %d\n", siop_stat_intr);
2203 printf("siop_stat_intr_shortxfer %d\n", siop_stat_intr_shortxfer);
2204 printf("siop_stat_intr_xferdisc %d\n", siop_stat_intr_xferdisc);
2205 printf("siop_stat_intr_sdp %d\n", siop_stat_intr_sdp);
2206 printf("siop_stat_intr_saveoffset %d\n", siop_stat_intr_saveoffset);
2207 printf("siop_stat_intr_done %d\n", siop_stat_intr_done);
2208 printf("siop_stat_intr_lunresel %d\n", siop_stat_intr_lunresel);
2209 printf("siop_stat_intr_qfull %d\n", siop_stat_intr_qfull);
2210 }
2211 #endif