File: | dev/ic/siop.c |
Warning: | line 1000, column 17 Dereference of null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: siop.c,v 1.88 2022/01/09 05:42:42 jsg Exp $ */ | |||
2 | /* $NetBSD: siop.c,v 1.79 2005/11/18 23:10:32 bouyer Exp $ */ | |||
3 | ||||
4 | /* | |||
5 | * Copyright (c) 2000 Manuel Bouyer. | |||
6 | * | |||
7 | * Redistribution and use in source and binary forms, with or without | |||
8 | * modification, are permitted provided that the following conditions | |||
9 | * are met: | |||
10 | * 1. Redistributions of source code must retain the above copyright | |||
11 | * notice, this list of conditions and the following disclaimer. | |||
12 | * 2. Redistributions in binary form must reproduce the above copyright | |||
13 | * notice, this list of conditions and the following disclaimer in the | |||
14 | * documentation and/or other materials provided with the distribution. | |||
15 | * | |||
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |||
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |||
18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |||
19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |||
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |||
21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |||
25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
26 | * | |||
27 | */ | |||
28 | ||||
29 | /* SYM53c7/8xx PCI-SCSI I/O Processors driver */ | |||
30 | ||||
31 | #include <sys/param.h> | |||
32 | #include <sys/systm.h> | |||
33 | #include <sys/device.h> | |||
34 | #include <sys/malloc.h> | |||
35 | #include <sys/kernel.h> | |||
36 | #include <sys/endian.h> | |||
37 | ||||
38 | #include <machine/bus.h> | |||
39 | ||||
40 | #include <dev/microcode/siop/siop.out> | |||
41 | ||||
42 | #include <scsi/scsi_all.h> | |||
43 | #include <scsi/scsi_message.h> | |||
44 | #include <scsi/scsiconf.h> | |||
45 | ||||
46 | #include <dev/ic/siopreg.h> | |||
47 | #include <dev/ic/siopvar_common.h> | |||
48 | #include <dev/ic/siopvar.h> | |||
49 | ||||
50 | #ifndef SIOP_DEBUG | |||
51 | #undef SIOP_DEBUG_DR | |||
52 | #undef SIOP_DEBUG_INTR | |||
53 | #undef SIOP_DEBUG_SCHED | |||
54 | #undef DUMP_SCRIPT | |||
55 | #else | |||
56 | #define SIOP_DEBUG_DR | |||
57 | #define SIOP_DEBUG_INTR | |||
58 | #define SIOP_DEBUG_SCHED | |||
59 | #define DUMP_SCRIPT | |||
60 | #endif | |||
61 | ||||
62 | ||||
63 | #undef SIOP_STATS | |||
64 | ||||
65 | #ifndef SIOP_DEFAULT_TARGET7 | |||
66 | #define SIOP_DEFAULT_TARGET7 7 | |||
67 | #endif | |||
68 | ||||
69 | /* number of cmd descriptors per block */ | |||
70 | #define SIOP_NCMDPB((1 << 12) / sizeof(struct siop_xfer)) (PAGE_SIZE(1 << 12) / sizeof(struct siop_xfer)) | |||
71 | ||||
72 | /* Number of scheduler slot (needs to match script) */ | |||
73 | #define SIOP_NSLOTS40 40 | |||
74 | ||||
75 | void siop_table_sync(struct siop_cmd *, int); | |||
76 | void siop_script_sync(struct siop_softc *, int); | |||
77 | u_int32_t siop_script_read(struct siop_softc *, u_int); | |||
78 | void siop_script_write(struct siop_softc *, u_int, u_int32_t); | |||
79 | void siop_reset(struct siop_softc *); | |||
80 | void siop_handle_reset(struct siop_softc *); | |||
81 | int siop_handle_qtag_reject(struct siop_cmd *); | |||
82 | void siop_scsicmd_end(struct siop_cmd *); | |||
83 | void siop_start(struct siop_softc *); | |||
84 | void siop_timeout(void *); | |||
85 | void siop_scsicmd(struct scsi_xfer *); | |||
86 | void * siop_cmd_get(void *); | |||
87 | void siop_cmd_put(void *, void *); | |||
88 | int siop_scsiprobe(struct scsi_link *); | |||
89 | void siop_scsifree(struct scsi_link *); | |||
90 | #ifdef DUMP_SCRIPT | |||
91 | void siop_dump_script(struct siop_softc *); | |||
92 | #endif | |||
93 | void siop_morecbd(struct siop_softc *); | |||
94 | struct siop_lunsw *siop_get_lunsw(struct siop_softc *); | |||
95 | void siop_add_reselsw(struct siop_softc *, int); | |||
96 | void siop_update_scntl3(struct siop_softc *, struct siop_common_target *); | |||
97 | ||||
98 | struct siop_dmamem *siop_dmamem_alloc(struct siop_softc *, size_t); | |||
99 | void siop_dmamem_free(struct siop_softc *, struct siop_dmamem *); | |||
100 | ||||
101 | struct cfdriver siop_cd = { | |||
102 | NULL((void *)0), "siop", DV_DULL | |||
103 | }; | |||
104 | ||||
105 | struct scsi_adapter siop_switch = { | |||
106 | siop_scsicmd, NULL((void *)0), siop_scsiprobe, siop_scsifree, NULL((void *)0) | |||
107 | }; | |||
108 | ||||
109 | #ifdef SIOP_STATS | |||
110 | static int siop_stat_intr = 0; | |||
111 | static int siop_stat_intr_shortxfer = 0; | |||
112 | static int siop_stat_intr_sdp = 0; | |||
113 | static int siop_stat_intr_saveoffset = 0; | |||
114 | static int siop_stat_intr_done = 0; | |||
115 | static int siop_stat_intr_xferdisc = 0; | |||
116 | static int siop_stat_intr_lunresel = 0; | |||
117 | static int siop_stat_intr_qfull = 0; | |||
118 | void siop_printstats(void); | |||
119 | #define INCSTAT(x) x++ | |||
120 | #else | |||
121 | #define INCSTAT(x) | |||
122 | #endif | |||
123 | ||||
124 | void | |||
125 | siop_table_sync(struct siop_cmd *siop_cmd, int ops) | |||
126 | { | |||
127 | struct siop_common_softc *sc = siop_cmd->cmd_c.siop_sc; | |||
128 | bus_addr_t offset; | |||
129 | ||||
130 | offset = siop_cmd->cmd_c.dsa - | |||
131 | SIOP_DMA_DVA(siop_cmd->siop_cbdp->xfers)((siop_cmd->siop_cbdp->xfers)->sdm_map->dm_segs[0 ].ds_addr); | |||
132 | bus_dmamap_sync(sc->sc_dmat,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((siop_cmd ->siop_cbdp->xfers)->sdm_map)), (offset), (sizeof(struct siop_xfer)), (ops)) | |||
133 | SIOP_DMA_MAP(siop_cmd->siop_cbdp->xfers), offset,(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((siop_cmd ->siop_cbdp->xfers)->sdm_map)), (offset), (sizeof(struct siop_xfer)), (ops)) | |||
134 | sizeof(struct siop_xfer), ops)(*(sc->sc_dmat)->_dmamap_sync)((sc->sc_dmat), (((siop_cmd ->siop_cbdp->xfers)->sdm_map)), (offset), (sizeof(struct siop_xfer)), (ops)); | |||
135 | } | |||
136 | ||||
137 | void | |||
138 | siop_script_sync(struct siop_softc *sc, int ops) | |||
139 | { | |||
140 | if ((sc->sc_c.features & SF_CHIP_RAM0x00004000) == 0) | |||
141 | bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (sc->sc_c.sc_scriptdma), (0), ((1 << 12)), (ops)) | |||
142 | PAGE_SIZE, ops)(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (sc->sc_c.sc_scriptdma), (0), ((1 << 12)), (ops)); | |||
143 | } | |||
144 | ||||
145 | u_int32_t | |||
146 | siop_script_read(struct siop_softc *sc, u_int offset) | |||
147 | { | |||
148 | if (sc->sc_c.features & SF_CHIP_RAM0x00004000) { | |||
149 | return bus_space_read_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,((sc->sc_c.sc_ramt)->read_4((sc->sc_c.sc_ramh), (offset * 4))) | |||
150 | offset * 4)((sc->sc_c.sc_ramt)->read_4((sc->sc_c.sc_ramh), (offset * 4))); | |||
151 | } else { | |||
152 | return siop_ctoh32(&sc->sc_c, sc->sc_c.sc_script[offset])(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_script[offset])) ? (__uint32_t )(((__uint32_t)((sc->sc_c.sc_script[offset])) & 0xff) << 24 | ((__uint32_t)((sc->sc_c.sc_script[offset])) & 0xff00 ) << 8 | ((__uint32_t)((sc->sc_c.sc_script[offset])) & 0xff0000) >> 8 | ((__uint32_t)((sc->sc_c.sc_script [offset])) & 0xff000000) >> 24) : __swap32md((sc-> sc_c.sc_script[offset]))) : ((__uint32_t)((sc->sc_c.sc_script [offset])))); | |||
153 | } | |||
154 | } | |||
155 | ||||
156 | void | |||
157 | siop_script_write(struct siop_softc *sc, u_int offset, u_int32_t val) | |||
158 | { | |||
159 | if (sc->sc_c.features & SF_CHIP_RAM0x00004000) { | |||
160 | bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,((sc->sc_c.sc_ramt)->write_4((sc->sc_c.sc_ramh), (offset * 4), (val))) | |||
161 | offset * 4, val)((sc->sc_c.sc_ramt)->write_4((sc->sc_c.sc_ramh), (offset * 4), (val))); | |||
162 | } else { | |||
163 | sc->sc_c.sc_script[offset] = siop_htoc32(&sc->sc_c, val)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((val)) ? (__uint32_t)(((__uint32_t)((val )) & 0xff) << 24 | ((__uint32_t)((val)) & 0xff00 ) << 8 | ((__uint32_t)((val)) & 0xff0000) >> 8 | ((__uint32_t)((val)) & 0xff000000) >> 24) : __swap32md ((val))) : ((__uint32_t)((val)))); | |||
164 | } | |||
165 | } | |||
166 | ||||
167 | void | |||
168 | siop_attach(struct siop_softc *sc) | |||
169 | { | |||
170 | struct scsibus_attach_args saa; | |||
171 | ||||
172 | if (siop_common_attach(&sc->sc_c) != 0) | |||
173 | return; | |||
174 | ||||
175 | TAILQ_INIT(&sc->free_list)do { (&sc->free_list)->tqh_first = ((void *)0); (& sc->free_list)->tqh_last = &(&sc->free_list) ->tqh_first; } while (0); | |||
176 | TAILQ_INIT(&sc->ready_list)do { (&sc->ready_list)->tqh_first = ((void *)0); (& sc->ready_list)->tqh_last = &(&sc->ready_list )->tqh_first; } while (0); | |||
177 | TAILQ_INIT(&sc->urgent_list)do { (&sc->urgent_list)->tqh_first = ((void *)0); ( &sc->urgent_list)->tqh_last = &(&sc->urgent_list )->tqh_first; } while (0); | |||
178 | TAILQ_INIT(&sc->cmds)do { (&sc->cmds)->tqh_first = ((void *)0); (&sc ->cmds)->tqh_last = &(&sc->cmds)->tqh_first ; } while (0); | |||
179 | TAILQ_INIT(&sc->lunsw_list)do { (&sc->lunsw_list)->tqh_first = ((void *)0); (& sc->lunsw_list)->tqh_last = &(&sc->lunsw_list )->tqh_first; } while (0); | |||
180 | scsi_iopool_init(&sc->iopool, sc, siop_cmd_get, siop_cmd_put); | |||
181 | sc->sc_currschedslot = 0; | |||
182 | ||||
183 | /* Start with one page worth of commands */ | |||
184 | siop_morecbd(sc); | |||
185 | ||||
186 | #ifdef SIOP_DEBUG | |||
187 | printf("%s: script size = %d, PHY addr=0x%x, VIRT=%p\n", | |||
188 | sc->sc_c.sc_dev.dv_xname, (int)sizeof(siop_script), | |||
189 | (u_int32_t)sc->sc_c.sc_scriptaddr, sc->sc_c.sc_script); | |||
190 | #endif | |||
191 | ||||
192 | /* Do a bus reset, so that devices fall back to narrow/async */ | |||
193 | siop_resetbus(&sc->sc_c); | |||
194 | /* | |||
195 | * siop_reset() will reset the chip, thus clearing pending interrupts | |||
196 | */ | |||
197 | siop_reset(sc); | |||
198 | #ifdef DUMP_SCRIPT | |||
199 | siop_dump_script(sc); | |||
200 | #endif | |||
201 | ||||
202 | saa.saa_adapter_softc = sc; | |||
203 | saa.saa_adapter = &siop_switch; | |||
204 | saa.saa_adapter_target = sc->sc_c.sc_id; | |||
205 | saa.saa_adapter_buswidth = (sc->sc_c.features & SF_BUS_WIDE0x00000001) ? 16 : 8; | |||
206 | saa.saa_luns = 8; | |||
207 | saa.saa_openings = SIOP_NTAG16; | |||
208 | saa.saa_pool = &sc->iopool; | |||
209 | saa.saa_quirks = saa.saa_flags = 0; | |||
210 | saa.saa_wwpn = saa.saa_wwnn = 0; | |||
211 | ||||
212 | config_found((struct device*)sc, &saa, scsiprint)config_found_sm(((struct device*)sc), (&saa), (scsiprint) , ((void *)0)); | |||
213 | } | |||
214 | ||||
215 | void | |||
216 | siop_reset(struct siop_softc *sc) | |||
217 | { | |||
218 | int i, j, buswidth; | |||
219 | struct siop_lunsw *lunsw; | |||
220 | ||||
221 | siop_common_reset(&sc->sc_c); | |||
222 | ||||
223 | /* copy and patch the script */ | |||
224 | if (sc->sc_c.features & SF_CHIP_RAM0x00004000) { | |||
225 | bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 0,((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (0), (siop_script), (sizeof(siop_script) / sizeof(siop_script [0])))) | |||
226 | siop_script, sizeof(siop_script) / sizeof(siop_script[0]))((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (0), (siop_script), (sizeof(siop_script) / sizeof(siop_script [0])))); | |||
227 | for (j = 0; j < | |||
228 | (sizeof(E_abs_msgin_Used) / sizeof(E_abs_msgin_Used[0])); | |||
229 | j++) { | |||
230 | bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,((sc->sc_c.sc_ramt)->write_4((sc->sc_c.sc_ramh), (E_abs_msgin_Used [j] * 4), (sc->sc_c.sc_scriptaddr + 0x00000598))) | |||
231 | E_abs_msgin_Used[j] * 4,((sc->sc_c.sc_ramt)->write_4((sc->sc_c.sc_ramh), (E_abs_msgin_Used [j] * 4), (sc->sc_c.sc_scriptaddr + 0x00000598))) | |||
232 | sc->sc_c.sc_scriptaddr + Ent_msgin_space)((sc->sc_c.sc_ramt)->write_4((sc->sc_c.sc_ramh), (E_abs_msgin_Used [j] * 4), (sc->sc_c.sc_scriptaddr + 0x00000598))); | |||
233 | } | |||
234 | if (sc->sc_c.features & SF_CHIP_LED00x00000100) { | |||
235 | bus_space_write_region_4(sc->sc_c.sc_ramt,((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (0x00000068), (siop_led_on), (sizeof(siop_led_on) / sizeof (siop_led_on[0])))) | |||
236 | sc->sc_c.sc_ramh,((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (0x00000068), (siop_led_on), (sizeof(siop_led_on) / sizeof (siop_led_on[0])))) | |||
237 | Ent_led_on1, siop_led_on,((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (0x00000068), (siop_led_on), (sizeof(siop_led_on) / sizeof (siop_led_on[0])))) | |||
238 | sizeof(siop_led_on) / sizeof(siop_led_on[0]))((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (0x00000068), (siop_led_on), (sizeof(siop_led_on) / sizeof (siop_led_on[0])))); | |||
239 | bus_space_write_region_4(sc->sc_c.sc_ramt,((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (0x00000220), (siop_led_on), (sizeof(siop_led_on) / sizeof (siop_led_on[0])))) | |||
240 | sc->sc_c.sc_ramh,((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (0x00000220), (siop_led_on), (sizeof(siop_led_on) / sizeof (siop_led_on[0])))) | |||
241 | Ent_led_on2, siop_led_on,((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (0x00000220), (siop_led_on), (sizeof(siop_led_on) / sizeof (siop_led_on[0])))) | |||
242 | sizeof(siop_led_on) / sizeof(siop_led_on[0]))((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (0x00000220), (siop_led_on), (sizeof(siop_led_on) / sizeof (siop_led_on[0])))); | |||
243 | bus_space_write_region_4(sc->sc_c.sc_ramt,((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (0x00000210), (siop_led_off), (sizeof(siop_led_off) / sizeof (siop_led_off[0])))) | |||
244 | sc->sc_c.sc_ramh,((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (0x00000210), (siop_led_off), (sizeof(siop_led_off) / sizeof (siop_led_off[0])))) | |||
245 | Ent_led_off, siop_led_off,((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (0x00000210), (siop_led_off), (sizeof(siop_led_off) / sizeof (siop_led_off[0])))) | |||
246 | sizeof(siop_led_off) / sizeof(siop_led_off[0]))((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (0x00000210), (siop_led_off), (sizeof(siop_led_off) / sizeof (siop_led_off[0])))); | |||
247 | } | |||
248 | } else { | |||
249 | for (j = 0; | |||
250 | j < (sizeof(siop_script) / sizeof(siop_script[0])); j++) { | |||
251 | sc->sc_c.sc_script[j] = | |||
252 | siop_htoc32(&sc->sc_c, siop_script[j])(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((siop_script[j])) ? (__uint32_t)(((__uint32_t )((siop_script[j])) & 0xff) << 24 | ((__uint32_t)(( siop_script[j])) & 0xff00) << 8 | ((__uint32_t)((siop_script [j])) & 0xff0000) >> 8 | ((__uint32_t)((siop_script [j])) & 0xff000000) >> 24) : __swap32md((siop_script [j]))) : ((__uint32_t)((siop_script[j])))); | |||
253 | } | |||
254 | for (j = 0; j < | |||
255 | (sizeof(E_abs_msgin_Used) / sizeof(E_abs_msgin_Used[0])); | |||
256 | j++) { | |||
257 | sc->sc_c.sc_script[E_abs_msgin_Used[j]] = | |||
258 | siop_htoc32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_scriptaddr + 0x00000598 )) ? (__uint32_t)(((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000598 )) & 0xff) << 24 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000598)) & 0xff00) << 8 | ((__uint32_t)((sc-> sc_c.sc_scriptaddr + 0x00000598)) & 0xff0000) >> 8 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000598)) & 0xff000000) >> 24) : __swap32md((sc->sc_c.sc_scriptaddr + 0x00000598))) : ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000598)))) | |||
259 | sc->sc_c.sc_scriptaddr + Ent_msgin_space)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_scriptaddr + 0x00000598 )) ? (__uint32_t)(((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000598 )) & 0xff) << 24 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000598)) & 0xff00) << 8 | ((__uint32_t)((sc-> sc_c.sc_scriptaddr + 0x00000598)) & 0xff0000) >> 8 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000598)) & 0xff000000) >> 24) : __swap32md((sc->sc_c.sc_scriptaddr + 0x00000598))) : ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000598)))); | |||
260 | } | |||
261 | if (sc->sc_c.features & SF_CHIP_LED00x00000100) { | |||
262 | for (j = 0; j < (sizeof(siop_led_on) / | |||
263 | sizeof(siop_led_on[0])); j++) | |||
264 | sc->sc_c.sc_script[ | |||
265 | Ent_led_on10x00000068 / sizeof(siop_led_on[0]) + j | |||
266 | ] = siop_htoc32(&sc->sc_c, siop_led_on[j])(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((siop_led_on[j])) ? (__uint32_t)(((__uint32_t )((siop_led_on[j])) & 0xff) << 24 | ((__uint32_t)(( siop_led_on[j])) & 0xff00) << 8 | ((__uint32_t)((siop_led_on [j])) & 0xff0000) >> 8 | ((__uint32_t)((siop_led_on [j])) & 0xff000000) >> 24) : __swap32md((siop_led_on [j]))) : ((__uint32_t)((siop_led_on[j])))); | |||
267 | for (j = 0; j < (sizeof(siop_led_on) / | |||
268 | sizeof(siop_led_on[0])); j++) | |||
269 | sc->sc_c.sc_script[ | |||
270 | Ent_led_on20x00000220 / sizeof(siop_led_on[0]) + j | |||
271 | ] = siop_htoc32(&sc->sc_c, siop_led_on[j])(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((siop_led_on[j])) ? (__uint32_t)(((__uint32_t )((siop_led_on[j])) & 0xff) << 24 | ((__uint32_t)(( siop_led_on[j])) & 0xff00) << 8 | ((__uint32_t)((siop_led_on [j])) & 0xff0000) >> 8 | ((__uint32_t)((siop_led_on [j])) & 0xff000000) >> 24) : __swap32md((siop_led_on [j]))) : ((__uint32_t)((siop_led_on[j])))); | |||
272 | for (j = 0; j < (sizeof(siop_led_off) / | |||
273 | sizeof(siop_led_off[0])); j++) | |||
274 | sc->sc_c.sc_script[ | |||
275 | Ent_led_off0x00000210 / sizeof(siop_led_off[0]) + j | |||
276 | ] = siop_htoc32(&sc->sc_c, siop_led_off[j])(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((siop_led_off[j])) ? (__uint32_t)(((__uint32_t )((siop_led_off[j])) & 0xff) << 24 | ((__uint32_t)( (siop_led_off[j])) & 0xff00) << 8 | ((__uint32_t)(( siop_led_off[j])) & 0xff0000) >> 8 | ((__uint32_t)( (siop_led_off[j])) & 0xff000000) >> 24) : __swap32md ((siop_led_off[j]))) : ((__uint32_t)((siop_led_off[j])))); | |||
277 | } | |||
278 | } | |||
279 | sc->script_free_lo = sizeof(siop_script) / sizeof(siop_script[0]); | |||
280 | sc->script_free_hi = sc->sc_c.ram_size / 4; | |||
281 | sc->sc_ntargets = 0; | |||
282 | ||||
283 | /* free used and unused lun switches */ | |||
284 | while((lunsw = TAILQ_FIRST(&sc->lunsw_list)((&sc->lunsw_list)->tqh_first)) != NULL((void *)0)) { | |||
285 | #ifdef SIOP_DEBUG | |||
286 | printf("%s: free lunsw at offset %d\n", | |||
287 | sc->sc_c.sc_dev.dv_xname, lunsw->lunsw_off); | |||
288 | #endif | |||
289 | TAILQ_REMOVE(&sc->lunsw_list, lunsw, next)do { if (((lunsw)->next.tqe_next) != ((void *)0)) (lunsw)-> next.tqe_next->next.tqe_prev = (lunsw)->next.tqe_prev; else (&sc->lunsw_list)->tqh_last = (lunsw)->next.tqe_prev ; *(lunsw)->next.tqe_prev = (lunsw)->next.tqe_next; ((lunsw )->next.tqe_prev) = ((void *)-1); ((lunsw)->next.tqe_next ) = ((void *)-1); } while (0); | |||
290 | free(lunsw, M_DEVBUF2, 0); | |||
291 | } | |||
292 | TAILQ_INIT(&sc->lunsw_list)do { (&sc->lunsw_list)->tqh_first = ((void *)0); (& sc->lunsw_list)->tqh_last = &(&sc->lunsw_list )->tqh_first; } while (0); | |||
293 | /* restore reselect switch */ | |||
294 | buswidth = (sc->sc_c.features & SF_BUS_WIDE0x00000001) ? 16 : 8; | |||
295 | for (i = 0; i < buswidth; i++) { | |||
296 | struct siop_target *target; | |||
297 | if (sc->sc_c.targets[i] == NULL((void *)0)) | |||
298 | continue; | |||
299 | #ifdef SIOP_DEBUG | |||
300 | printf("%s: restore sw for target %d\n", | |||
301 | sc->sc_c.sc_dev.dv_xname, i); | |||
302 | #endif | |||
303 | target = (struct siop_target *)sc->sc_c.targets[i]; | |||
304 | free(target->lunsw, M_DEVBUF2, 0); | |||
305 | target->lunsw = siop_get_lunsw(sc); | |||
306 | if (target->lunsw == NULL((void *)0)) { | |||
307 | printf("%s: can't alloc lunsw for target %d\n", | |||
308 | sc->sc_c.sc_dev.dv_xname, i); | |||
309 | break; | |||
310 | } | |||
311 | siop_add_reselsw(sc, i); | |||
312 | } | |||
313 | ||||
314 | /* start script */ | |||
315 | if ((sc->sc_c.features & SF_CHIP_RAM0x00004000) == 0) { | |||
316 | bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (sc->sc_c.sc_scriptdma), (0), ((1 << 12)), (0x01 | 0x04)) | |||
317 | PAGE_SIZE, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (sc->sc_c.sc_scriptdma), (0), ((1 << 12)), (0x01 | 0x04)); | |||
318 | } | |||
319 | bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP,((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C), (sc->sc_c.sc_scriptaddr + 0x000001e0))) | |||
320 | sc->sc_c.sc_scriptaddr + Ent_reselect)((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C), (sc->sc_c.sc_scriptaddr + 0x000001e0))); | |||
321 | } | |||
322 | ||||
323 | #if 0 | |||
324 | #define CALL_SCRIPT(ent)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + ent))); } while (0) do {\ | |||
325 | printf ("start script DSA 0x%lx DSP 0x%lx\n", \ | |||
326 | siop_cmd->cmd_c.dsa, \ | |||
327 | sc->sc_c.sc_scriptaddr + ent); \((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C), (sc->sc_c.sc_scriptaddr + ent))) | |||
328 | bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent)((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C), (sc->sc_c.sc_scriptaddr + ent))); \ | |||
329 | } while (0) | |||
330 | #else | |||
331 | #define CALL_SCRIPT(ent)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + ent))); } while (0) do {\((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C), (sc->sc_c.sc_scriptaddr + ent))) | |||
332 | bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent)((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C), (sc->sc_c.sc_scriptaddr + ent))); \ | |||
333 | } while (0) | |||
334 | #endif | |||
335 | ||||
336 | int | |||
337 | siop_intr(void *v) | |||
338 | { | |||
339 | struct siop_softc *sc = v; | |||
340 | struct siop_target *siop_target; | |||
341 | struct siop_cmd *siop_cmd; | |||
342 | struct siop_lun *siop_lun; | |||
343 | struct scsi_xfer *xs; | |||
344 | int istat, sist, sstat1, dstat = 0; | |||
345 | u_int32_t irqcode; | |||
346 | int need_reset = 0; | |||
347 | int offset, target, lun, tag; | |||
348 | bus_addr_t dsa; | |||
349 | struct siop_cbd *cbdp; | |||
350 | int restart = 0; | |||
351 | ||||
352 | istat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT)((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x14))); | |||
353 | if ((istat & (ISTAT_INTF0x04 | ISTAT_DIP0x01 | ISTAT_SIP0x02)) == 0) | |||
| ||||
354 | return 0; | |||
355 | INCSTAT(siop_stat_intr); | |||
356 | if (istat & ISTAT_INTF0x04) { | |||
357 | printf("INTRF\n"); | |||
358 | bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,((sc->sc_c.sc_rt)->write_1((sc->sc_c.sc_rh), (0x14), (0x04))) | |||
359 | SIOP_ISTAT, ISTAT_INTF)((sc->sc_c.sc_rt)->write_1((sc->sc_c.sc_rh), (0x14), (0x04))); | |||
360 | } | |||
361 | if ((istat &(ISTAT_DIP0x01 | ISTAT_SIP0x02 | ISTAT_ABRT0x80)) == | |||
362 | (ISTAT_DIP0x01 | ISTAT_ABRT0x80)) { | |||
363 | /* clear abort */ | |||
364 | bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,((sc->sc_c.sc_rt)->write_1((sc->sc_c.sc_rh), (0x14), (0))) | |||
365 | SIOP_ISTAT, 0)((sc->sc_c.sc_rt)->write_1((sc->sc_c.sc_rh), (0x14), (0))); | |||
366 | } | |||
367 | /* use DSA to find the current siop_cmd */ | |||
368 | siop_cmd = NULL((void *)0); | |||
369 | dsa = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA)((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x10))); | |||
370 | TAILQ_FOREACH(cbdp, &sc->cmds, next)for((cbdp) = ((&sc->cmds)->tqh_first); (cbdp) != (( void *)0); (cbdp) = ((cbdp)->next.tqe_next)) { | |||
371 | if (dsa >= SIOP_DMA_DVA(cbdp->xfers)((cbdp->xfers)->sdm_map->dm_segs[0].ds_addr) && | |||
372 | dsa < SIOP_DMA_DVA(cbdp->xfers)((cbdp->xfers)->sdm_map->dm_segs[0].ds_addr) + PAGE_SIZE(1 << 12)) { | |||
373 | dsa -= SIOP_DMA_DVA(cbdp->xfers)((cbdp->xfers)->sdm_map->dm_segs[0].ds_addr); | |||
374 | siop_cmd = &cbdp->cmds[dsa / sizeof(struct siop_xfer)]; | |||
375 | siop_table_sync(siop_cmd, | |||
376 | BUS_DMASYNC_POSTREAD0x02 | BUS_DMASYNC_POSTWRITE0x08); | |||
377 | break; | |||
378 | } | |||
379 | } | |||
380 | if (siop_cmd
| |||
381 | xs = siop_cmd->cmd_c.xs; | |||
382 | siop_target = (struct siop_target *)siop_cmd->cmd_c.siop_target; | |||
383 | target = siop_cmd->cmd_c.xs->sc_link->target; | |||
384 | lun = siop_cmd->cmd_c.xs->sc_link->lun; | |||
385 | tag = siop_cmd->cmd_c.tag; | |||
386 | siop_lun = siop_target->siop_lun[lun]; | |||
387 | #ifdef DIAGNOSTIC1 | |||
388 | if (siop_cmd->cmd_c.status != CMDST_ACTIVE2 && | |||
389 | siop_cmd->cmd_c.status != CMDST_SENSE_ACTIVE4) { | |||
390 | printf("siop_cmd (lun %d) for DSA 0x%x " | |||
391 | "not active (%d)\n", lun, (u_int)dsa, | |||
392 | siop_cmd->cmd_c.status); | |||
393 | xs = NULL((void *)0); | |||
394 | siop_target = NULL((void *)0); | |||
395 | target = -1; | |||
396 | lun = -1; | |||
397 | tag = -1; | |||
398 | siop_lun = NULL((void *)0); | |||
399 | siop_cmd = NULL((void *)0); | |||
400 | } else if (siop_lun->siop_tag[tag].active != siop_cmd) { | |||
401 | printf("siop_cmd (lun %d tag %d) not in siop_lun " | |||
402 | "active (%p != %p)\n", lun, tag, siop_cmd, | |||
403 | siop_lun->siop_tag[tag].active); | |||
404 | } | |||
405 | #endif | |||
406 | } else { | |||
407 | xs = NULL((void *)0); | |||
408 | siop_target = NULL((void *)0); | |||
409 | target = -1; | |||
410 | lun = -1; | |||
411 | tag = -1; | |||
412 | siop_lun = NULL((void *)0); | |||
413 | } | |||
414 | if (istat & ISTAT_DIP0x01) { | |||
415 | dstat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x0C))) | |||
416 | SIOP_DSTAT)((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x0C))); | |||
417 | if (dstat & DSTAT_ABRT0x10) { | |||
418 | /* was probably generated by a bus reset IOCTL */ | |||
419 | if ((dstat & DSTAT_DFE0x80) == 0) | |||
420 | siop_clearfifo(&sc->sc_c); | |||
421 | goto reset; | |||
422 | } | |||
423 | if (dstat & DSTAT_SSI0x08) { | |||
424 | printf("single step dsp 0x%08x dsa 0x08%x\n", | |||
425 | (int)(bus_space_read_4(sc->sc_c.sc_rt,((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x2C))) | |||
426 | sc->sc_c.sc_rh, SIOP_DSP)((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x2C))) - | |||
427 | sc->sc_c.sc_scriptaddr), | |||
428 | bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x10))) | |||
429 | SIOP_DSA)((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x10)))); | |||
430 | if ((dstat & ~(DSTAT_DFE0x80 | DSTAT_SSI0x08)) == 0 && | |||
431 | (istat & ISTAT_SIP0x02) == 0) { | |||
432 | bus_space_write_1(sc->sc_c.sc_rt,((sc->sc_c.sc_rt)->write_1((sc->sc_c.sc_rh), (0x3B), (((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x3B) )) | 0x04))) | |||
433 | sc->sc_c.sc_rh, SIOP_DCNTL,((sc->sc_c.sc_rt)->write_1((sc->sc_c.sc_rh), (0x3B), (((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x3B) )) | 0x04))) | |||
434 | bus_space_read_1(sc->sc_c.sc_rt,((sc->sc_c.sc_rt)->write_1((sc->sc_c.sc_rh), (0x3B), (((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x3B) )) | 0x04))) | |||
435 | sc->sc_c.sc_rh, SIOP_DCNTL) | DCNTL_STD)((sc->sc_c.sc_rt)->write_1((sc->sc_c.sc_rh), (0x3B), (((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x3B) )) | 0x04))); | |||
436 | } | |||
437 | return 1; | |||
438 | } | |||
439 | ||||
440 | if (dstat & ~(DSTAT_SIR0x04 | DSTAT_DFE0x80 | DSTAT_SSI0x08)) { | |||
441 | printf("%s: DMA IRQ:", sc->sc_c.sc_dev.dv_xname); | |||
442 | if (dstat & DSTAT_IID0x01) | |||
443 | printf(" illegal instruction"); | |||
444 | if (dstat & DSTAT_BF0x20) | |||
445 | printf(" bus fault"); | |||
446 | if (dstat & DSTAT_MDPE0x40) | |||
447 | printf(" parity"); | |||
448 | if (dstat & DSTAT_DFE0x80) | |||
449 | printf(" DMA fifo empty"); | |||
450 | else | |||
451 | siop_clearfifo(&sc->sc_c); | |||
452 | printf(", DSP=0x%x DSA=0x%x: ", | |||
453 | (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x2C))) | |||
454 | SIOP_DSP)((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x2C))) - sc->sc_c.sc_scriptaddr), | |||
455 | bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA)((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x10)))); | |||
456 | if (siop_cmd) | |||
457 | printf("last msg_in=0x%x status=0x%x\n", | |||
458 | siop_cmd->cmd_tablescmd_c.siop_tables->msg_in[0], | |||
459 | siop_ctoh32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((siop_cmd->cmd_c.siop_tables->status )) ? (__uint32_t)(((__uint32_t)((siop_cmd->cmd_c.siop_tables ->status)) & 0xff) << 24 | ((__uint32_t)((siop_cmd ->cmd_c.siop_tables->status)) & 0xff00) << 8 | ((__uint32_t)((siop_cmd->cmd_c.siop_tables->status)) & 0xff0000) >> 8 | ((__uint32_t)((siop_cmd->cmd_c.siop_tables ->status)) & 0xff000000) >> 24) : __swap32md((siop_cmd ->cmd_c.siop_tables->status))) : ((__uint32_t)((siop_cmd ->cmd_c.siop_tables->status)))) | |||
460 | siop_cmd->cmd_tables->status)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((siop_cmd->cmd_c.siop_tables->status )) ? (__uint32_t)(((__uint32_t)((siop_cmd->cmd_c.siop_tables ->status)) & 0xff) << 24 | ((__uint32_t)((siop_cmd ->cmd_c.siop_tables->status)) & 0xff00) << 8 | ((__uint32_t)((siop_cmd->cmd_c.siop_tables->status)) & 0xff0000) >> 8 | ((__uint32_t)((siop_cmd->cmd_c.siop_tables ->status)) & 0xff000000) >> 24) : __swap32md((siop_cmd ->cmd_c.siop_tables->status))) : ((__uint32_t)((siop_cmd ->cmd_c.siop_tables->status))))); | |||
461 | else | |||
462 | printf("current DSA invalid\n"); | |||
463 | need_reset = 1; | |||
464 | } | |||
465 | } | |||
466 | if (istat & ISTAT_SIP0x02) { | |||
467 | if (istat & ISTAT_DIP0x01) | |||
468 | delay(10)(*delay_func)(10); | |||
469 | /* | |||
470 | * Can't read sist0 & sist1 independently, or we have to | |||
471 | * insert delay | |||
472 | */ | |||
473 | sist = bus_space_read_2(sc->sc_c.sc_rt, sc->sc_c.sc_rh,((sc->sc_c.sc_rt)->read_2((sc->sc_c.sc_rh), (0x42))) | |||
474 | SIOP_SIST0)((sc->sc_c.sc_rt)->read_2((sc->sc_c.sc_rh), (0x42))); | |||
475 | sstat1 = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x0E))) | |||
476 | SIOP_SSTAT1)((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x0E))); | |||
477 | #ifdef SIOP_DEBUG_INTR | |||
478 | printf("scsi interrupt, sist=0x%x sstat1=0x%x " | |||
479 | "DSA=0x%x DSP=0x%lx\n", sist, sstat1, | |||
480 | bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA)((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x10))), | |||
481 | (u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x2C))) | |||
482 | SIOP_DSP)((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x2C))) - | |||
483 | sc->sc_c.sc_scriptaddr)); | |||
484 | #endif | |||
485 | if (sist & SIST0_RST0x02) { | |||
486 | siop_handle_reset(sc); | |||
487 | siop_start(sc); | |||
488 | /* no table to flush here */ | |||
489 | return 1; | |||
490 | } | |||
491 | if (sist & SIST0_SGE0x08) { | |||
492 | if (siop_cmd) | |||
493 | sc_print_addr(xs->sc_link); | |||
494 | else | |||
495 | printf("%s: ", sc->sc_c.sc_dev.dv_xname); | |||
496 | printf("scsi gross error\n"); | |||
497 | goto reset; | |||
498 | } | |||
499 | if ((sist & SIST0_MA0x80) && need_reset == 0) { | |||
500 | if (siop_cmd) { | |||
501 | int scratcha0; | |||
502 | /* XXX Why read DSTAT again? */ | |||
503 | dstat = bus_space_read_1(sc->sc_c.sc_rt,((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x0C))) | |||
504 | sc->sc_c.sc_rh, SIOP_DSTAT)((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x0C))); | |||
505 | /* | |||
506 | * first restore DSA, in case we were in a S/G | |||
507 | * operation. | |||
508 | */ | |||
509 | bus_space_write_4(sc->sc_c.sc_rt,((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x10), (siop_cmd->cmd_c.dsa))) | |||
510 | sc->sc_c.sc_rh,((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x10), (siop_cmd->cmd_c.dsa))) | |||
511 | SIOP_DSA, siop_cmd->cmd_c.dsa)((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x10), (siop_cmd->cmd_c.dsa))); | |||
512 | scratcha0 = bus_space_read_1(sc->sc_c.sc_rt,((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x34))) | |||
513 | sc->sc_c.sc_rh, SIOP_SCRATCHA)((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x34))); | |||
514 | switch (sstat1 & SSTAT1_PHASE_MASK(0x01 | 0x02 | 0x04)) { | |||
515 | case SSTAT1_PHASE_STATUS(0x02 | 0x01): | |||
516 | /* | |||
517 | * previous phase may be aborted for any reason | |||
518 | * ( for example, the target has less data to | |||
519 | * transfer than requested). Compute resid and | |||
520 | * just go to status, the command should | |||
521 | * terminate. | |||
522 | */ | |||
523 | INCSTAT(siop_stat_intr_shortxfer); | |||
524 | if (scratcha0 & A_flag_data0x00000002) | |||
525 | siop_ma(&siop_cmd->cmd_c); | |||
526 | else if ((dstat & DSTAT_DFE0x80) == 0) | |||
527 | siop_clearfifo(&sc->sc_c); | |||
528 | CALL_SCRIPT(Ent_status)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x000003d0))); } while (0); | |||
529 | return 1; | |||
530 | case SSTAT1_PHASE_MSGIN(0x04 | 0x02 | 0x01): | |||
531 | /* | |||
532 | * target may be ready to disconnect | |||
533 | * Compute resid which would be used later | |||
534 | * if a save data pointer is needed. | |||
535 | */ | |||
536 | INCSTAT(siop_stat_intr_xferdisc); | |||
537 | if (scratcha0 & A_flag_data0x00000002) | |||
538 | siop_ma(&siop_cmd->cmd_c); | |||
539 | else if ((dstat & DSTAT_DFE0x80) == 0) | |||
540 | siop_clearfifo(&sc->sc_c); | |||
541 | bus_space_write_1(sc->sc_c.sc_rt,((sc->sc_c.sc_rt)->write_1((sc->sc_c.sc_rh), (0x34), (scratcha0 & ~0x00000002))) | |||
542 | sc->sc_c.sc_rh, SIOP_SCRATCHA,((sc->sc_c.sc_rt)->write_1((sc->sc_c.sc_rh), (0x34), (scratcha0 & ~0x00000002))) | |||
543 | scratcha0 & ~A_flag_data)((sc->sc_c.sc_rt)->write_1((sc->sc_c.sc_rh), (0x34), (scratcha0 & ~0x00000002))); | |||
544 | CALL_SCRIPT(Ent_msgin)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000328))); } while (0); | |||
545 | return 1; | |||
546 | } | |||
547 | printf("%s: unexpected phase mismatch %d\n", | |||
548 | sc->sc_c.sc_dev.dv_xname, | |||
549 | sstat1 & SSTAT1_PHASE_MASK(0x01 | 0x02 | 0x04)); | |||
550 | } else { | |||
551 | printf("%s: phase mismatch without command\n", | |||
552 | sc->sc_c.sc_dev.dv_xname); | |||
553 | } | |||
554 | need_reset = 1; | |||
555 | } | |||
556 | if (sist & SIST0_PAR0x01) { | |||
557 | /* parity error, reset */ | |||
558 | if (siop_cmd) | |||
559 | sc_print_addr(xs->sc_link); | |||
560 | else | |||
561 | printf("%s: ", sc->sc_c.sc_dev.dv_xname); | |||
562 | printf("parity error\n"); | |||
563 | goto reset; | |||
564 | } | |||
565 | if ((sist & (SIST1_STO0x04 << 8)) && need_reset == 0) { | |||
566 | /* selection time out, assume there's no device here */ | |||
567 | if (siop_cmd) { | |||
568 | siop_cmd->cmd_c.status = CMDST_DONE6; | |||
569 | xs->error = XS_SELTIMEOUT3; | |||
570 | goto end; | |||
571 | } else { | |||
572 | printf("%s: selection timeout without " | |||
573 | "command\n", sc->sc_c.sc_dev.dv_xname); | |||
574 | need_reset = 1; | |||
575 | } | |||
576 | } | |||
577 | if (sist & SIST0_UDC0x04) { | |||
578 | /* | |||
579 | * unexpected disconnect. Usually the target signals | |||
580 | * a fatal condition this way. Attempt to get sense. | |||
581 | */ | |||
582 | if (siop_cmd) { | |||
583 | siop_cmd->cmd_tablescmd_c.siop_tables->status = | |||
584 | siop_htoc32(&sc->sc_c, SCSI_CHECK)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((0x02)) ? (__uint32_t)(((__uint32_t)(( 0x02)) & 0xff) << 24 | ((__uint32_t)((0x02)) & 0xff00 ) << 8 | ((__uint32_t)((0x02)) & 0xff0000) >> 8 | ((__uint32_t)((0x02)) & 0xff000000) >> 24) : __swap32md ((0x02))) : ((__uint32_t)((0x02)))); | |||
585 | goto end; | |||
586 | } | |||
587 | printf("%s: unexpected disconnect without " | |||
588 | "command\n", sc->sc_c.sc_dev.dv_xname); | |||
589 | goto reset; | |||
590 | } | |||
591 | if (sist & (SIST1_SBMC0x10 << 8)) { | |||
592 | /* SCSI bus mode change */ | |||
593 | if (siop_modechange(&sc->sc_c) == 0 || need_reset == 1) | |||
594 | goto reset; | |||
595 | if ((istat & ISTAT_DIP0x01) && (dstat & DSTAT_SIR0x04)) { | |||
596 | /* | |||
597 | * we have a script interrupt, it will | |||
598 | * restart the script. | |||
599 | */ | |||
600 | goto scintr; | |||
601 | } | |||
602 | /* | |||
603 | * else we have to restart it ourselves, at the | |||
604 | * interrupted instruction. | |||
605 | */ | |||
606 | bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C), (((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x2C) )) - 8))) | |||
607 | SIOP_DSP,((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C), (((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x2C) )) - 8))) | |||
608 | bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C), (((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x2C) )) - 8))) | |||
609 | SIOP_DSP) - 8)((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C), (((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x2C) )) - 8))); | |||
610 | return 1; | |||
611 | } | |||
612 | /* Else it's an unhandled exception (for now). */ | |||
613 | printf("%s: unhandled scsi interrupt, sist=0x%x sstat1=0x%x " | |||
614 | "DSA=0x%x DSP=0x%x\n", sc->sc_c.sc_dev.dv_xname, | |||
615 | sist, sstat1, | |||
616 | bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA)((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x10))), | |||
617 | (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x2C))) | |||
618 | SIOP_DSP)((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x2C))) - sc->sc_c.sc_scriptaddr)); | |||
619 | if (siop_cmd) { | |||
620 | siop_cmd->cmd_c.status = CMDST_DONE6; | |||
621 | xs->error = XS_SELTIMEOUT3; | |||
622 | goto end; | |||
623 | } | |||
624 | need_reset = 1; | |||
625 | } else { | |||
626 | sist = sstat1 = 0; | |||
627 | } | |||
628 | if (need_reset
| |||
629 | reset: | |||
630 | /* fatal error, reset the bus */ | |||
631 | siop_resetbus(&sc->sc_c); | |||
632 | /* no table to flush here */ | |||
633 | return 1; | |||
634 | } | |||
635 | ||||
636 | scintr: | |||
637 | if ((istat & ISTAT_DIP0x01) && (dstat & DSTAT_SIR0x04)) { /* script interrupt */ | |||
638 | irqcode = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x30))) | |||
639 | SIOP_DSPS)((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x30))); | |||
640 | #ifdef SIOP_DEBUG_INTR | |||
641 | printf("script interrupt 0x%x\n", irqcode); | |||
642 | #endif | |||
643 | /* | |||
644 | * no command, or an inactive command is only valid for a | |||
645 | * reselect interrupt | |||
646 | */ | |||
647 | if ((irqcode & 0x80) == 0) { | |||
648 | if (siop_cmd == NULL((void *)0)) { | |||
649 | printf( | |||
650 | "%s: script interrupt (0x%x) with invalid DSA !!!\n", | |||
651 | sc->sc_c.sc_dev.dv_xname, irqcode); | |||
652 | goto reset; | |||
653 | } | |||
654 | if (siop_cmd->cmd_c.status != CMDST_ACTIVE2 && | |||
655 | siop_cmd->cmd_c.status != CMDST_SENSE_ACTIVE4) { | |||
656 | printf("%s: command with invalid status " | |||
657 | "(IRQ code 0x%x current status %d) !\n", | |||
658 | sc->sc_c.sc_dev.dv_xname, | |||
659 | irqcode, siop_cmd->cmd_c.status); | |||
660 | xs = NULL((void *)0); | |||
661 | } | |||
662 | } | |||
663 | switch(irqcode) { | |||
664 | case A_int_err0x0000ffff: | |||
665 | printf("error, DSP=0x%x\n", | |||
666 | (int)(bus_space_read_4(sc->sc_c.sc_rt,((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x2C))) | |||
667 | sc->sc_c.sc_rh, SIOP_DSP)((sc->sc_c.sc_rt)->read_4((sc->sc_c.sc_rh), (0x2C))) - sc->sc_c.sc_scriptaddr)); | |||
668 | if (xs) { | |||
669 | xs->error = XS_SELTIMEOUT3; | |||
670 | goto end; | |||
671 | } else { | |||
672 | goto reset; | |||
673 | } | |||
674 | case A_int_reseltarg0x0000ff80: | |||
675 | printf("%s: reselect with invalid target\n", | |||
676 | sc->sc_c.sc_dev.dv_xname); | |||
677 | goto reset; | |||
678 | case A_int_resellun0x0000ff81: | |||
679 | INCSTAT(siop_stat_intr_lunresel); | |||
680 | target = bus_space_read_1(sc->sc_c.sc_rt,((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x34))) | |||
681 | sc->sc_c.sc_rh, SIOP_SCRATCHA)((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x34))) & 0xf; | |||
682 | lun = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x34 + 1 ))) | |||
683 | SIOP_SCRATCHA + 1)((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x34 + 1 ))); | |||
684 | tag = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x34 + 2 ))) | |||
685 | SIOP_SCRATCHA + 2)((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x34 + 2 ))); | |||
686 | siop_target = | |||
687 | (struct siop_target *)sc->sc_c.targets[target]; | |||
688 | if (siop_target == NULL((void *)0)) { | |||
689 | printf("%s: reselect with invalid target %d\n", | |||
690 | sc->sc_c.sc_dev.dv_xname, target); | |||
691 | goto reset; | |||
692 | } | |||
693 | siop_lun = siop_target->siop_lun[lun]; | |||
694 | if (siop_lun == NULL((void *)0)) { | |||
695 | printf("%s: target %d reselect with invalid " | |||
696 | "lun %d\n", sc->sc_c.sc_dev.dv_xname, | |||
697 | target, lun); | |||
698 | goto reset; | |||
699 | } | |||
700 | if (siop_lun->siop_tag[tag].active == NULL((void *)0)) { | |||
701 | printf("%s: target %d lun %d tag %d reselect " | |||
702 | "without command\n", | |||
703 | sc->sc_c.sc_dev.dv_xname, | |||
704 | target, lun, tag); | |||
705 | goto reset; | |||
706 | } | |||
707 | siop_cmd = siop_lun->siop_tag[tag].active; | |||
708 | bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C), (siop_cmd->cmd_c.dsa + sizeof(struct siop_common_xfer) + 0x00000028 ))) | |||
709 | SIOP_DSP, siop_cmd->cmd_c.dsa +((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C), (siop_cmd->cmd_c.dsa + sizeof(struct siop_common_xfer) + 0x00000028 ))) | |||
710 | sizeof(struct siop_common_xfer) +((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C), (siop_cmd->cmd_c.dsa + sizeof(struct siop_common_xfer) + 0x00000028 ))) | |||
711 | Ent_ldsa_reload_dsa)((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C), (siop_cmd->cmd_c.dsa + sizeof(struct siop_common_xfer) + 0x00000028 ))); | |||
712 | siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE0x04); | |||
713 | return 1; | |||
714 | case A_int_reseltag0x0000ff82: | |||
715 | printf("%s: reselect with invalid tag\n", | |||
716 | sc->sc_c.sc_dev.dv_xname); | |||
717 | goto reset; | |||
718 | case A_int_msgin0x0000ff01: | |||
719 | { | |||
720 | int msgin = bus_space_read_1(sc->sc_c.sc_rt,((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x08))) | |||
721 | sc->sc_c.sc_rh, SIOP_SFBR)((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x08))); | |||
722 | if (msgin == MSG_MESSAGE_REJECT0x07) { | |||
723 | int msg, extmsg; | |||
724 | if (siop_cmd->cmd_tablescmd_c.siop_tables->msg_out[0] & 0x80) { | |||
725 | /* | |||
726 | * message was part of a identify + | |||
727 | * something else. Identify shouldn't | |||
728 | * have been rejected. | |||
729 | */ | |||
730 | msg = | |||
731 | siop_cmd->cmd_tablescmd_c.siop_tables->msg_out[1]; | |||
732 | extmsg = | |||
733 | siop_cmd->cmd_tablescmd_c.siop_tables->msg_out[3]; | |||
734 | } else { | |||
735 | msg = siop_cmd->cmd_tablescmd_c.siop_tables->msg_out[0]; | |||
736 | extmsg = | |||
737 | siop_cmd->cmd_tablescmd_c.siop_tables->msg_out[2]; | |||
738 | } | |||
739 | if (msg == MSG_MESSAGE_REJECT0x07) { | |||
740 | /* MSG_REJECT for a MSG_REJECT !*/ | |||
741 | if (xs) | |||
742 | sc_print_addr(xs->sc_link); | |||
743 | else | |||
744 | printf("%s: ", | |||
745 | sc->sc_c.sc_dev.dv_xname); | |||
746 | printf("our reject message was " | |||
747 | "rejected\n"); | |||
748 | goto reset; | |||
749 | } | |||
750 | if (msg == MSG_EXTENDED0x01 && | |||
751 | extmsg == MSG_EXT_WDTR0x03) { | |||
752 | /* WDTR rejected, initiate sync */ | |||
753 | if ((siop_target->target_c.flags & | |||
754 | TARF_SYNC0x01) == 0) { | |||
755 | siop_target->target_c.status = | |||
756 | TARST_OK5; | |||
757 | siop_update_xfer_mode(&sc->sc_c, | |||
758 | target); | |||
759 | /* no table to flush here */ | |||
760 | CALL_SCRIPT(Ent_msgin_ack)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000388))); } while (0); | |||
761 | return 1; | |||
762 | } | |||
763 | siop_target->target_c.status = | |||
764 | TARST_SYNC_NEG3; | |||
765 | siop_sdtr_msg(&siop_cmd->cmd_c, 0, | |||
766 | sc->sc_c.st_minsync, | |||
767 | sc->sc_c.maxoff); | |||
768 | siop_table_sync(siop_cmd, | |||
769 | BUS_DMASYNC_PREREAD0x01 | | |||
770 | BUS_DMASYNC_PREWRITE0x04); | |||
771 | CALL_SCRIPT(Ent_send_msgout)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000398))); } while (0); | |||
772 | return 1; | |||
773 | } else if (msg == MSG_EXTENDED0x01 && | |||
774 | extmsg == MSG_EXT_SDTR0x01) { | |||
775 | /* sync rejected */ | |||
776 | siop_target->target_c.offset = 0; | |||
777 | siop_target->target_c.period = 0; | |||
778 | siop_target->target_c.status = TARST_OK5; | |||
779 | siop_update_xfer_mode(&sc->sc_c, | |||
780 | target); | |||
781 | /* no table to flush here */ | |||
782 | CALL_SCRIPT(Ent_msgin_ack)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000388))); } while (0); | |||
783 | return 1; | |||
784 | } else if (msg == MSG_EXTENDED0x01 && | |||
785 | extmsg == MSG_EXT_PPR0x04) { | |||
786 | /* PPR negotiation rejected */ | |||
787 | siop_target->target_c.offset = 0; | |||
788 | siop_target->target_c.period = 0; | |||
789 | siop_target->target_c.status = TARST_ASYNC1; | |||
790 | siop_target->target_c.flags &= ~(TARF_DT0x08 | TARF_ISDT0x20); | |||
791 | CALL_SCRIPT(Ent_msgin_ack)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000388))); } while (0); | |||
792 | return 1; | |||
793 | } else if (msg == MSG_SIMPLE_Q_TAG0x20 || | |||
794 | msg == MSG_HEAD_OF_Q_TAG0x21 || | |||
795 | msg == MSG_ORDERED_Q_TAG0x22) { | |||
796 | if (siop_handle_qtag_reject( | |||
797 | siop_cmd) == -1) | |||
798 | goto reset; | |||
799 | CALL_SCRIPT(Ent_msgin_ack)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000388))); } while (0); | |||
800 | return 1; | |||
801 | } | |||
802 | if (xs) | |||
803 | sc_print_addr(xs->sc_link); | |||
804 | else | |||
805 | printf("%s: ", | |||
806 | sc->sc_c.sc_dev.dv_xname); | |||
807 | if (msg == MSG_EXTENDED0x01) { | |||
808 | printf("scsi message reject, extended " | |||
809 | "message sent was 0x%x\n", extmsg); | |||
810 | } else { | |||
811 | printf("scsi message reject, message " | |||
812 | "sent was 0x%x\n", msg); | |||
813 | } | |||
814 | /* no table to flush here */ | |||
815 | CALL_SCRIPT(Ent_msgin_ack)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000388))); } while (0); | |||
816 | return 1; | |||
817 | } | |||
818 | if (msgin == MSG_IGN_WIDE_RESIDUE0x23) { | |||
819 | /* use the extmsgdata table to get the second byte */ | |||
820 | siop_cmd->cmd_tablescmd_c.siop_tables->t_extmsgdata.count = | |||
821 | siop_htoc32(&sc->sc_c, 1)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((1)) ? (__uint32_t)(((__uint32_t)((1)) & 0xff) << 24 | ((__uint32_t)((1)) & 0xff00) << 8 | ((__uint32_t)((1)) & 0xff0000) >> 8 | ((__uint32_t )((1)) & 0xff000000) >> 24) : __swap32md((1))) : (( __uint32_t)((1)))); | |||
822 | siop_table_sync(siop_cmd, | |||
823 | BUS_DMASYNC_PREREAD0x01 | BUS_DMASYNC_PREWRITE0x04); | |||
824 | CALL_SCRIPT(Ent_get_extmsgdata)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000580))); } while (0); | |||
825 | return 1; | |||
826 | } | |||
827 | if (xs) | |||
828 | sc_print_addr(xs->sc_link); | |||
829 | else | |||
830 | printf("%s: ", sc->sc_c.sc_dev.dv_xname); | |||
831 | printf("unhandled message 0x%x\n", | |||
832 | siop_cmd->cmd_tablescmd_c.siop_tables->msg_in[0]); | |||
833 | siop_cmd->cmd_tablescmd_c.siop_tables->msg_out[0] = MSG_MESSAGE_REJECT0x07; | |||
834 | siop_cmd->cmd_tablescmd_c.siop_tables->t_msgout.count = | |||
835 | siop_htoc32(&sc->sc_c, 1)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((1)) ? (__uint32_t)(((__uint32_t)((1)) & 0xff) << 24 | ((__uint32_t)((1)) & 0xff00) << 8 | ((__uint32_t)((1)) & 0xff0000) >> 8 | ((__uint32_t )((1)) & 0xff000000) >> 24) : __swap32md((1))) : (( __uint32_t)((1)))); | |||
836 | siop_table_sync(siop_cmd, | |||
837 | BUS_DMASYNC_PREREAD0x01 | BUS_DMASYNC_PREWRITE0x04); | |||
838 | CALL_SCRIPT(Ent_send_msgout)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000398))); } while (0); | |||
839 | return 1; | |||
840 | } | |||
841 | case A_int_extmsgin0x0000ff02: | |||
842 | #ifdef SIOP_DEBUG_INTR | |||
843 | printf("extended message: msg 0x%x len %d\n", | |||
844 | siop_cmd->cmd_tablescmd_c.siop_tables->msg_in[2], | |||
845 | siop_cmd->cmd_tablescmd_c.siop_tables->msg_in[1]); | |||
846 | #endif | |||
847 | if (siop_cmd->cmd_tablescmd_c.siop_tables->msg_in[1] > | |||
848 | sizeof(siop_cmd->cmd_tablescmd_c.siop_tables->msg_in) - 2) | |||
849 | printf("%s: extended message too big (%d)\n", | |||
850 | sc->sc_c.sc_dev.dv_xname, | |||
851 | siop_cmd->cmd_tablescmd_c.siop_tables->msg_in[1]); | |||
852 | siop_cmd->cmd_tablescmd_c.siop_tables->t_extmsgdata.count = | |||
853 | siop_htoc32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((siop_cmd->cmd_c.siop_tables->msg_in [1] - 1)) ? (__uint32_t)(((__uint32_t)((siop_cmd->cmd_c.siop_tables ->msg_in[1] - 1)) & 0xff) << 24 | ((__uint32_t)( (siop_cmd->cmd_c.siop_tables->msg_in[1] - 1)) & 0xff00 ) << 8 | ((__uint32_t)((siop_cmd->cmd_c.siop_tables-> msg_in[1] - 1)) & 0xff0000) >> 8 | ((__uint32_t)((siop_cmd ->cmd_c.siop_tables->msg_in[1] - 1)) & 0xff000000) >> 24) : __swap32md((siop_cmd->cmd_c.siop_tables->msg_in[ 1] - 1))) : ((__uint32_t)((siop_cmd->cmd_c.siop_tables-> msg_in[1] - 1)))) | |||
854 | siop_cmd->cmd_tables->msg_in[1] - 1)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((siop_cmd->cmd_c.siop_tables->msg_in [1] - 1)) ? (__uint32_t)(((__uint32_t)((siop_cmd->cmd_c.siop_tables ->msg_in[1] - 1)) & 0xff) << 24 | ((__uint32_t)( (siop_cmd->cmd_c.siop_tables->msg_in[1] - 1)) & 0xff00 ) << 8 | ((__uint32_t)((siop_cmd->cmd_c.siop_tables-> msg_in[1] - 1)) & 0xff0000) >> 8 | ((__uint32_t)((siop_cmd ->cmd_c.siop_tables->msg_in[1] - 1)) & 0xff000000) >> 24) : __swap32md((siop_cmd->cmd_c.siop_tables->msg_in[ 1] - 1))) : ((__uint32_t)((siop_cmd->cmd_c.siop_tables-> msg_in[1] - 1)))); | |||
855 | siop_table_sync(siop_cmd, | |||
856 | BUS_DMASYNC_PREREAD0x01 | BUS_DMASYNC_PREWRITE0x04); | |||
857 | CALL_SCRIPT(Ent_get_extmsgdata)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000580))); } while (0); | |||
858 | return 1; | |||
859 | case A_int_extmsgdata0x0000ff03: | |||
860 | #ifdef SIOP_DEBUG_INTR | |||
861 | { | |||
862 | int i; | |||
863 | printf("extended message: 0x%x, data:", | |||
864 | siop_cmd->cmd_tablescmd_c.siop_tables->msg_in[2]); | |||
865 | for (i = 3; i < 2 + siop_cmd->cmd_tablescmd_c.siop_tables->msg_in[1]; | |||
866 | i++) | |||
867 | printf(" 0x%x", | |||
868 | siop_cmd->cmd_tablescmd_c.siop_tables->msg_in[i]); | |||
869 | printf("\n"); | |||
870 | } | |||
871 | #endif | |||
872 | if (siop_cmd->cmd_tablescmd_c.siop_tables->msg_in[0] == | |||
873 | MSG_IGN_WIDE_RESIDUE0x23) { | |||
874 | /* we got the second byte of MSG_IGN_WIDE_RESIDUE */ | |||
875 | if (siop_cmd->cmd_tablescmd_c.siop_tables->msg_in[3] != 1) | |||
876 | printf("MSG_IGN_WIDE_RESIDUE: " | |||
877 | "bad len %d\n", | |||
878 | siop_cmd->cmd_tablescmd_c.siop_tables->msg_in[3]); | |||
879 | switch (siop_iwr(&siop_cmd->cmd_c)) { | |||
880 | case SIOP_NEG_MSGOUT0x1: | |||
881 | siop_table_sync(siop_cmd, | |||
882 | BUS_DMASYNC_PREREAD0x01 | | |||
883 | BUS_DMASYNC_PREWRITE0x04); | |||
884 | CALL_SCRIPT(Ent_send_msgout)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000398))); } while (0); | |||
885 | return(1); | |||
886 | case SIOP_NEG_ACK0x2: | |||
887 | CALL_SCRIPT(Ent_msgin_ack)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000388))); } while (0); | |||
888 | return(1); | |||
889 | default: | |||
890 | panic("invalid retval from " | |||
891 | "siop_iwr()"); | |||
892 | } | |||
893 | return(1); | |||
894 | } | |||
895 | if (siop_cmd->cmd_tablescmd_c.siop_tables->msg_in[2] == MSG_EXT_WDTR0x03) { | |||
896 | switch (siop_wdtr_neg(&siop_cmd->cmd_c)) { | |||
897 | case SIOP_NEG_MSGOUT0x1: | |||
898 | siop_update_scntl3(sc, | |||
899 | siop_cmd->cmd_c.siop_target); | |||
900 | siop_table_sync(siop_cmd, | |||
901 | BUS_DMASYNC_PREREAD0x01 | | |||
902 | BUS_DMASYNC_PREWRITE0x04); | |||
903 | CALL_SCRIPT(Ent_send_msgout)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000398))); } while (0); | |||
904 | return(1); | |||
905 | case SIOP_NEG_ACK0x2: | |||
906 | siop_update_scntl3(sc, | |||
907 | siop_cmd->cmd_c.siop_target); | |||
908 | CALL_SCRIPT(Ent_msgin_ack)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000388))); } while (0); | |||
909 | return(1); | |||
910 | default: | |||
911 | panic("invalid retval from " | |||
912 | "siop_wdtr_neg()"); | |||
913 | } | |||
914 | return(1); | |||
915 | } | |||
916 | if (siop_cmd->cmd_tablescmd_c.siop_tables->msg_in[2] == MSG_EXT_SDTR0x01) { | |||
917 | switch (siop_sdtr_neg(&siop_cmd->cmd_c)) { | |||
918 | case SIOP_NEG_MSGOUT0x1: | |||
919 | siop_update_scntl3(sc, | |||
920 | siop_cmd->cmd_c.siop_target); | |||
921 | siop_table_sync(siop_cmd, | |||
922 | BUS_DMASYNC_PREREAD0x01 | | |||
923 | BUS_DMASYNC_PREWRITE0x04); | |||
924 | CALL_SCRIPT(Ent_send_msgout)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000398))); } while (0); | |||
925 | return(1); | |||
926 | case SIOP_NEG_ACK0x2: | |||
927 | siop_update_scntl3(sc, | |||
928 | siop_cmd->cmd_c.siop_target); | |||
929 | CALL_SCRIPT(Ent_msgin_ack)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000388))); } while (0); | |||
930 | return(1); | |||
931 | default: | |||
932 | panic("invalid retval from " | |||
933 | "siop_sdtr_neg()"); | |||
934 | } | |||
935 | return(1); | |||
936 | } | |||
937 | if (siop_cmd->cmd_tablescmd_c.siop_tables->msg_in[2] == MSG_EXT_PPR0x04) { | |||
938 | switch (siop_ppr_neg(&siop_cmd->cmd_c)) { | |||
939 | case SIOP_NEG_MSGOUT0x1: | |||
940 | siop_update_scntl3(sc, | |||
941 | siop_cmd->cmd_c.siop_target); | |||
942 | siop_table_sync(siop_cmd, | |||
943 | BUS_DMASYNC_PREREAD0x01 | | |||
944 | BUS_DMASYNC_PREWRITE0x04); | |||
945 | CALL_SCRIPT(Ent_send_msgout)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000398))); } while (0); | |||
946 | return(1); | |||
947 | case SIOP_NEG_ACK0x2: | |||
948 | siop_update_scntl3(sc, | |||
949 | siop_cmd->cmd_c.siop_target); | |||
950 | CALL_SCRIPT(Ent_msgin_ack)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000388))); } while (0); | |||
951 | return(1); | |||
952 | default: | |||
953 | panic("invalid retval from " | |||
954 | "siop_wdtr_neg()"); | |||
955 | } | |||
956 | return(1); | |||
957 | } | |||
958 | /* send a message reject */ | |||
959 | siop_cmd->cmd_tablescmd_c.siop_tables->msg_out[0] = MSG_MESSAGE_REJECT0x07; | |||
960 | siop_cmd->cmd_tablescmd_c.siop_tables->t_msgout.count = | |||
961 | siop_htoc32(&sc->sc_c, 1)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((1)) ? (__uint32_t)(((__uint32_t)((1)) & 0xff) << 24 | ((__uint32_t)((1)) & 0xff00) << 8 | ((__uint32_t)((1)) & 0xff0000) >> 8 | ((__uint32_t )((1)) & 0xff000000) >> 24) : __swap32md((1))) : (( __uint32_t)((1)))); | |||
962 | siop_table_sync(siop_cmd, | |||
963 | BUS_DMASYNC_PREREAD0x01 | BUS_DMASYNC_PREWRITE0x04); | |||
964 | CALL_SCRIPT(Ent_send_msgout)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000398))); } while (0); | |||
965 | return 1; | |||
966 | case A_int_disc0x0000ff04: | |||
967 | INCSTAT(siop_stat_intr_sdp); | |||
968 | offset = bus_space_read_1(sc->sc_c.sc_rt,((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x34 + 1 ))) | |||
969 | sc->sc_c.sc_rh, SIOP_SCRATCHA + 1)((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x34 + 1 ))); | |||
970 | #ifdef SIOP_DEBUG_DR | |||
971 | printf("disconnect offset %d\n", offset); | |||
972 | #endif | |||
973 | siop_sdp(&siop_cmd->cmd_c, offset); | |||
974 | /* we start again with no offset */ | |||
975 | siop_cmd->saved_offset = SIOP_NOOFFSET0xffffffff; | |||
976 | siop_table_sync(siop_cmd, | |||
977 | BUS_DMASYNC_PREREAD0x01 | BUS_DMASYNC_PREWRITE0x04); | |||
978 | CALL_SCRIPT(Ent_script_sched)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000070))); } while (0); | |||
979 | return 1; | |||
980 | case A_int_saveoffset0x0000ff05: | |||
981 | INCSTAT(siop_stat_intr_saveoffset); | |||
982 | offset = bus_space_read_1(sc->sc_c.sc_rt,((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x34 + 1 ))) | |||
983 | sc->sc_c.sc_rh, SIOP_SCRATCHA + 1)((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x34 + 1 ))); | |||
984 | #ifdef SIOP_DEBUG_DR | |||
985 | printf("saveoffset offset %d\n", offset); | |||
986 | #endif | |||
987 | siop_cmd->saved_offset = offset; | |||
988 | CALL_SCRIPT(Ent_script_sched)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000070))); } while (0); | |||
989 | return 1; | |||
990 | case A_int_resfail0x0000ff83: | |||
991 | printf("reselect failed\n"); | |||
992 | /* check if we can put some command in scheduler */ | |||
993 | siop_start(sc); | |||
994 | CALL_SCRIPT(Ent_script_sched)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000070))); } while (0); | |||
995 | return 1; | |||
996 | case A_int_done0x0000ff00: | |||
997 | if (xs
| |||
998 | printf("%s: done without command, DSA=0x%lx\n", | |||
999 | sc->sc_c.sc_dev.dv_xname, | |||
1000 | (u_long)siop_cmd->cmd_c.dsa); | |||
| ||||
1001 | siop_cmd->cmd_c.status = CMDST_FREE0; | |||
1002 | siop_start(sc); | |||
1003 | CALL_SCRIPT(Ent_script_sched)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000070))); } while (0); | |||
1004 | return 1; | |||
1005 | } | |||
1006 | #ifdef SIOP_DEBUG_INTR | |||
1007 | printf("done, DSA=0x%lx target id 0x%x last msg " | |||
1008 | "in=0x%x status=0x%x\n", (u_long)siop_cmd->cmd_c.dsa, | |||
1009 | siop_ctoh32(&sc->sc_c, siop_cmd->cmd_tables->id)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((siop_cmd->cmd_c.siop_tables->id )) ? (__uint32_t)(((__uint32_t)((siop_cmd->cmd_c.siop_tables ->id)) & 0xff) << 24 | ((__uint32_t)((siop_cmd-> cmd_c.siop_tables->id)) & 0xff00) << 8 | ((__uint32_t )((siop_cmd->cmd_c.siop_tables->id)) & 0xff0000) >> 8 | ((__uint32_t)((siop_cmd->cmd_c.siop_tables->id)) & 0xff000000) >> 24) : __swap32md((siop_cmd->cmd_c.siop_tables ->id))) : ((__uint32_t)((siop_cmd->cmd_c.siop_tables-> id)))), | |||
1010 | siop_cmd->cmd_tablescmd_c.siop_tables->msg_in[0], | |||
1011 | siop_ctoh32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((siop_cmd->cmd_c.siop_tables->status )) ? (__uint32_t)(((__uint32_t)((siop_cmd->cmd_c.siop_tables ->status)) & 0xff) << 24 | ((__uint32_t)((siop_cmd ->cmd_c.siop_tables->status)) & 0xff00) << 8 | ((__uint32_t)((siop_cmd->cmd_c.siop_tables->status)) & 0xff0000) >> 8 | ((__uint32_t)((siop_cmd->cmd_c.siop_tables ->status)) & 0xff000000) >> 24) : __swap32md((siop_cmd ->cmd_c.siop_tables->status))) : ((__uint32_t)((siop_cmd ->cmd_c.siop_tables->status)))) | |||
1012 | siop_cmd->cmd_tables->status)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((siop_cmd->cmd_c.siop_tables->status )) ? (__uint32_t)(((__uint32_t)((siop_cmd->cmd_c.siop_tables ->status)) & 0xff) << 24 | ((__uint32_t)((siop_cmd ->cmd_c.siop_tables->status)) & 0xff00) << 8 | ((__uint32_t)((siop_cmd->cmd_c.siop_tables->status)) & 0xff0000) >> 8 | ((__uint32_t)((siop_cmd->cmd_c.siop_tables ->status)) & 0xff000000) >> 24) : __swap32md((siop_cmd ->cmd_c.siop_tables->status))) : ((__uint32_t)((siop_cmd ->cmd_c.siop_tables->status))))); | |||
1013 | #endif | |||
1014 | INCSTAT(siop_stat_intr_done); | |||
1015 | /* update resid. */ | |||
1016 | offset = bus_space_read_1(sc->sc_c.sc_rt,((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x34 + 1 ))) | |||
1017 | sc->sc_c.sc_rh, SIOP_SCRATCHA + 1)((sc->sc_c.sc_rt)->read_1((sc->sc_c.sc_rh), (0x34 + 1 ))); | |||
1018 | /* | |||
1019 | * if we got a disconnect between the last data phase | |||
1020 | * and the status phase, offset will be 0. In this | |||
1021 | * case, siop_cmd->saved_offset will have the proper | |||
1022 | * value if it got updated by the controller | |||
1023 | */ | |||
1024 | if (offset == 0 && | |||
1025 | siop_cmd->saved_offset != SIOP_NOOFFSET0xffffffff) | |||
1026 | offset = siop_cmd->saved_offset; | |||
1027 | siop_update_resid(&siop_cmd->cmd_c, offset); | |||
1028 | if (siop_cmd->cmd_c.status == CMDST_SENSE_ACTIVE4) | |||
1029 | siop_cmd->cmd_c.status = CMDST_SENSE_DONE5; | |||
1030 | else | |||
1031 | siop_cmd->cmd_c.status = CMDST_DONE6; | |||
1032 | goto end; | |||
1033 | default: | |||
1034 | printf("unknown irqcode %x\n", irqcode); | |||
1035 | if (xs) { | |||
1036 | xs->error = XS_SELTIMEOUT3; | |||
1037 | goto end; | |||
1038 | } | |||
1039 | goto reset; | |||
1040 | } | |||
1041 | return 1; | |||
1042 | } else | |||
1043 | irqcode = 0; | |||
1044 | /* We can get here if ISTAT_DIP and DSTAT_DFE are the only bits set. */ | |||
1045 | /* But that *SHOULDN'T* happen. It does on powerpc (at least). */ | |||
1046 | printf("%s: siop_intr() - we should not be here!\n" | |||
1047 | " istat = 0x%x, dstat = 0x%x, sist = 0x%x, sstat1 = 0x%x\n" | |||
1048 | " need_reset = %x, irqcode = %x, siop_cmd %s\n", | |||
1049 | sc->sc_c.sc_dev.dv_xname, | |||
1050 | istat, dstat, sist, sstat1, need_reset, irqcode, | |||
1051 | (siop_cmd == NULL((void *)0)) ? "== NULL" : "!= NULL"); | |||
1052 | goto reset; /* Where we should have gone in the first place! */ | |||
1053 | end: | |||
1054 | /* | |||
1055 | * restart the script now if command completed properly | |||
1056 | * Otherwise wait for siop_scsicmd_end(), we may need to cleanup the | |||
1057 | * queue | |||
1058 | */ | |||
1059 | xs->status = siop_ctoh32(&sc->sc_c, siop_cmd->cmd_tables->status)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((siop_cmd->cmd_c.siop_tables->status )) ? (__uint32_t)(((__uint32_t)((siop_cmd->cmd_c.siop_tables ->status)) & 0xff) << 24 | ((__uint32_t)((siop_cmd ->cmd_c.siop_tables->status)) & 0xff00) << 8 | ((__uint32_t)((siop_cmd->cmd_c.siop_tables->status)) & 0xff0000) >> 8 | ((__uint32_t)((siop_cmd->cmd_c.siop_tables ->status)) & 0xff000000) >> 24) : __swap32md((siop_cmd ->cmd_c.siop_tables->status))) : ((__uint32_t)((siop_cmd ->cmd_c.siop_tables->status)))); | |||
1060 | if (xs->status == SCSI_OK0x00) | |||
1061 | CALL_SCRIPT(Ent_script_sched)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000070))); } while (0); | |||
1062 | else | |||
1063 | restart = 1; | |||
1064 | siop_lun->siop_tag[tag].active = NULL((void *)0); | |||
1065 | siop_scsicmd_end(siop_cmd); | |||
1066 | siop_start(sc); | |||
1067 | if (restart) | |||
1068 | CALL_SCRIPT(Ent_script_sched)do {((sc->sc_c.sc_rt)->write_4((sc->sc_c.sc_rh), (0x2C ), (sc->sc_c.sc_scriptaddr + 0x00000070))); } while (0); | |||
1069 | return 1; | |||
1070 | } | |||
1071 | ||||
1072 | void | |||
1073 | siop_scsicmd_end(struct siop_cmd *siop_cmd) | |||
1074 | { | |||
1075 | struct scsi_xfer *xs = siop_cmd->cmd_c.xs; | |||
1076 | struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc; | |||
1077 | struct siop_lun *siop_lun = | |||
1078 | ((struct siop_target*)sc->sc_c.targets[xs->sc_link->target])->siop_lun[xs->sc_link->lun]; | |||
1079 | ||||
1080 | /* | |||
1081 | * If the command is re-queued (SENSE, QUEUE_FULL) it | |||
1082 | * must get a new timeout, so delete existing timeout now. | |||
1083 | */ | |||
1084 | timeout_del(&siop_cmd->cmd_c.xs->stimeout); | |||
1085 | ||||
1086 | switch(xs->status) { | |||
1087 | case SCSI_OK0x00: | |||
1088 | xs->error = (siop_cmd->cmd_c.status == CMDST_DONE6) ? | |||
1089 | XS_NOERROR0 : XS_SENSE1; | |||
1090 | break; | |||
1091 | case SCSI_BUSY0x08: | |||
1092 | xs->error = XS_BUSY5; | |||
1093 | break; | |||
1094 | case SCSI_CHECK0x02: | |||
1095 | if (siop_cmd->cmd_c.status == CMDST_SENSE_DONE5) { | |||
1096 | /* request sense on a request sense ? */ | |||
1097 | printf("%s: request sense failed\n", | |||
1098 | sc->sc_c.sc_dev.dv_xname); | |||
1099 | xs->error = XS_DRIVER_STUFFUP2; | |||
1100 | } else { | |||
1101 | siop_cmd->cmd_c.status = CMDST_SENSE3; | |||
1102 | } | |||
1103 | break; | |||
1104 | case SCSI_QUEUE_FULL0x28: | |||
1105 | /* | |||
1106 | * Device didn't queue the command. We have to retry | |||
1107 | * it. We insert it into the urgent list, hoping to | |||
1108 | * preserve order. But unfortunately, commands already | |||
1109 | * in the scheduler may be accepted before this one. | |||
1110 | * Also remember the condition, to avoid starting new | |||
1111 | * commands for this device before one is done. | |||
1112 | */ | |||
1113 | INCSTAT(siop_stat_intr_qfull); | |||
1114 | #ifdef SIOP_DEBUG | |||
1115 | printf("%s:%d:%d: queue full (tag %d)\n", sc->sc_c.sc_dev.dv_xname, | |||
1116 | xs->sc_link->target, | |||
1117 | xs->sc_link->lun, siop_cmd->cmd_c.tag); | |||
1118 | #endif | |||
1119 | siop_lun->lun_flags |= SIOP_LUNF_FULL0x01; | |||
1120 | siop_cmd->cmd_c.status = CMDST_READY1; | |||
1121 | siop_setuptables(&siop_cmd->cmd_c); | |||
1122 | siop_table_sync(siop_cmd, BUS_DMASYNC_PREREAD0x01 | BUS_DMASYNC_PREWRITE0x04); | |||
1123 | TAILQ_INSERT_TAIL(&sc->urgent_list, siop_cmd, next)do { (siop_cmd)->next.tqe_next = ((void *)0); (siop_cmd)-> next.tqe_prev = (&sc->urgent_list)->tqh_last; *(& sc->urgent_list)->tqh_last = (siop_cmd); (&sc->urgent_list )->tqh_last = &(siop_cmd)->next.tqe_next; } while ( 0); | |||
1124 | return; | |||
1125 | case SCSI_SIOP_NOCHECK0xfe: | |||
1126 | /* | |||
1127 | * don't check status, xs->error is already valid | |||
1128 | */ | |||
1129 | break; | |||
1130 | case SCSI_SIOP_NOSTATUS0xff: | |||
1131 | /* | |||
1132 | * the status byte was not updated, cmd was | |||
1133 | * aborted | |||
1134 | */ | |||
1135 | xs->error = XS_SELTIMEOUT3; | |||
1136 | break; | |||
1137 | default: | |||
1138 | xs->error = XS_DRIVER_STUFFUP2; | |||
1139 | } | |||
1140 | if (siop_cmd->cmd_c.status != CMDST_SENSE_DONE5 && | |||
1141 | xs->flags & (SCSI_DATA_IN0x00800 | SCSI_DATA_OUT0x01000)) { | |||
1142 | bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data, 0,(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (0), (siop_cmd->cmd_c .dmamap_data->dm_mapsize), ((xs->flags & 0x00800) ? 0x02 : 0x08)) | |||
1143 | siop_cmd->cmd_c.dmamap_data->dm_mapsize,(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (0), (siop_cmd->cmd_c .dmamap_data->dm_mapsize), ((xs->flags & 0x00800) ? 0x02 : 0x08)) | |||
1144 | (xs->flags & SCSI_DATA_IN) ?(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (0), (siop_cmd->cmd_c .dmamap_data->dm_mapsize), ((xs->flags & 0x00800) ? 0x02 : 0x08)) | |||
1145 | BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE)(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (0), (siop_cmd->cmd_c .dmamap_data->dm_mapsize), ((xs->flags & 0x00800) ? 0x02 : 0x08)); | |||
1146 | bus_dmamap_unload(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data)(*(sc->sc_c.sc_dmat)->_dmamap_unload)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data)); | |||
1147 | } | |||
1148 | if (siop_cmd->cmd_c.status == CMDST_SENSE3) { | |||
1149 | /* issue a request sense for this target */ | |||
1150 | struct scsi_sense *cmd = (struct scsi_sense *)&siop_cmd->cmd_c.siop_tables->xscmd; | |||
1151 | int error; | |||
1152 | bzero(cmd, sizeof(*cmd))__builtin_bzero((cmd), (sizeof(*cmd))); | |||
1153 | siop_cmd->cmd_c.siop_tables->cmd.count = | |||
1154 | siop_htoc32(&sc->sc_c, sizeof(struct scsi_sense))(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sizeof(struct scsi_sense))) ? (__uint32_t )(((__uint32_t)((sizeof(struct scsi_sense))) & 0xff) << 24 | ((__uint32_t)((sizeof(struct scsi_sense))) & 0xff00 ) << 8 | ((__uint32_t)((sizeof(struct scsi_sense))) & 0xff0000) >> 8 | ((__uint32_t)((sizeof(struct scsi_sense ))) & 0xff000000) >> 24) : __swap32md((sizeof(struct scsi_sense)))) : ((__uint32_t)((sizeof(struct scsi_sense)))) ); | |||
1155 | cmd->opcode = REQUEST_SENSE0x03; | |||
1156 | cmd->byte2 = xs->sc_link->lun << 5; | |||
1157 | cmd->unused[0] = cmd->unused[1] = 0; | |||
1158 | cmd->length = sizeof(struct scsi_sense_data); | |||
1159 | cmd->control = 0; | |||
1160 | siop_cmd->cmd_c.flags &= ~CMDFL_TAG0x0002; | |||
1161 | error = bus_dmamap_load(sc->sc_c.sc_dmat,(*(sc->sc_c.sc_dmat)->_dmamap_load)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (siop_cmd->cmd_c.sense ), (sizeof(struct scsi_sense_data)), (((void *)0)), (0x0001)) | |||
1162 | siop_cmd->cmd_c.dmamap_data,(*(sc->sc_c.sc_dmat)->_dmamap_load)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (siop_cmd->cmd_c.sense ), (sizeof(struct scsi_sense_data)), (((void *)0)), (0x0001)) | |||
1163 | siop_cmd->cmd_c.sense, sizeof(struct scsi_sense_data),(*(sc->sc_c.sc_dmat)->_dmamap_load)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (siop_cmd->cmd_c.sense ), (sizeof(struct scsi_sense_data)), (((void *)0)), (0x0001)) | |||
1164 | NULL, BUS_DMA_NOWAIT)(*(sc->sc_c.sc_dmat)->_dmamap_load)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (siop_cmd->cmd_c.sense ), (sizeof(struct scsi_sense_data)), (((void *)0)), (0x0001)); | |||
1165 | if (error) { | |||
1166 | printf("%s: unable to load data DMA map " | |||
1167 | "(for SENSE): %d\n", | |||
1168 | sc->sc_c.sc_dev.dv_xname, error); | |||
1169 | xs->error = XS_DRIVER_STUFFUP2; | |||
1170 | goto out; | |||
1171 | } | |||
1172 | bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data,(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (0), (siop_cmd->cmd_c .dmamap_data->dm_mapsize), (0x01)) | |||
1173 | 0, siop_cmd->cmd_c.dmamap_data->dm_mapsize,(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (0), (siop_cmd->cmd_c .dmamap_data->dm_mapsize), (0x01)) | |||
1174 | BUS_DMASYNC_PREREAD)(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (0), (siop_cmd->cmd_c .dmamap_data->dm_mapsize), (0x01)); | |||
1175 | ||||
1176 | siop_setuptables(&siop_cmd->cmd_c); | |||
1177 | siop_table_sync(siop_cmd, BUS_DMASYNC_PREREAD0x01 | BUS_DMASYNC_PREWRITE0x04); | |||
1178 | /* arrange for the cmd to be handled now */ | |||
1179 | TAILQ_INSERT_HEAD(&sc->urgent_list, siop_cmd, next)do { if (((siop_cmd)->next.tqe_next = (&sc->urgent_list )->tqh_first) != ((void *)0)) (&sc->urgent_list)-> tqh_first->next.tqe_prev = &(siop_cmd)->next.tqe_next ; else (&sc->urgent_list)->tqh_last = &(siop_cmd )->next.tqe_next; (&sc->urgent_list)->tqh_first = (siop_cmd); (siop_cmd)->next.tqe_prev = &(&sc-> urgent_list)->tqh_first; } while (0); | |||
1180 | return; | |||
1181 | } else if (siop_cmd->cmd_c.status == CMDST_SENSE_DONE5) { | |||
1182 | bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data,(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (0), (siop_cmd->cmd_c .dmamap_data->dm_mapsize), (0x02)) | |||
1183 | 0, siop_cmd->cmd_c.dmamap_data->dm_mapsize,(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (0), (siop_cmd->cmd_c .dmamap_data->dm_mapsize), (0x02)) | |||
1184 | BUS_DMASYNC_POSTREAD)(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (0), (siop_cmd->cmd_c .dmamap_data->dm_mapsize), (0x02)); | |||
1185 | bus_dmamap_unload(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data)(*(sc->sc_c.sc_dmat)->_dmamap_unload)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data)); | |||
1186 | bcopy(siop_cmd->cmd_c.sense, &xs->sense, sizeof(xs->sense)); | |||
1187 | } | |||
1188 | out: | |||
1189 | siop_lun->lun_flags &= ~SIOP_LUNF_FULL0x01; | |||
1190 | #if 0 | |||
1191 | if (xs->resid != 0) | |||
1192 | printf("resid %d datalen %d\n", xs->resid, xs->datalen); | |||
1193 | #endif | |||
1194 | scsi_done(xs); | |||
1195 | } | |||
1196 | ||||
1197 | /* | |||
1198 | * handle a rejected queue tag message: the command will run untagged, | |||
1199 | * has to adjust the reselect script. | |||
1200 | */ | |||
1201 | int | |||
1202 | siop_handle_qtag_reject(struct siop_cmd *siop_cmd) | |||
1203 | { | |||
1204 | struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc; | |||
1205 | int target = siop_cmd->cmd_c.xs->sc_link->target; | |||
1206 | int lun = siop_cmd->cmd_c.xs->sc_link->lun; | |||
1207 | int tag = siop_cmd->cmd_tablescmd_c.siop_tables->msg_out[2]; | |||
1208 | struct siop_lun *siop_lun = | |||
1209 | ((struct siop_target*)sc->sc_c.targets[target])->siop_lun[lun]; | |||
1210 | ||||
1211 | #ifdef SIOP_DEBUG | |||
1212 | printf("%s:%d:%d: tag message %d (%d) rejected (status %d)\n", | |||
1213 | sc->sc_c.sc_dev.dv_xname, target, lun, tag, siop_cmd->cmd_c.tag, | |||
1214 | siop_cmd->cmd_c.status); | |||
1215 | #endif | |||
1216 | ||||
1217 | if (siop_lun->siop_tag[0].active != NULL((void *)0)) { | |||
1218 | printf("%s: untagged command already running for target %d " | |||
1219 | "lun %d (status %d)\n", sc->sc_c.sc_dev.dv_xname, | |||
1220 | target, lun, siop_lun->siop_tag[0].active->cmd_c.status); | |||
1221 | return -1; | |||
1222 | } | |||
1223 | /* clear tag slot */ | |||
1224 | siop_lun->siop_tag[tag].active = NULL((void *)0); | |||
1225 | /* add command to non-tagged slot */ | |||
1226 | siop_lun->siop_tag[0].active = siop_cmd; | |||
1227 | siop_cmd->cmd_c.tag = 0; | |||
1228 | /* adjust reselect script if there is one */ | |||
1229 | if (siop_lun->siop_tag[0].reseloff > 0) { | |||
1230 | siop_script_write(sc, | |||
1231 | siop_lun->siop_tag[0].reseloff + 1, | |||
1232 | siop_cmd->cmd_c.dsa + sizeof(struct siop_common_xfer) + | |||
1233 | Ent_ldsa_reload_dsa0x00000028); | |||
1234 | siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE0x04); | |||
1235 | } | |||
1236 | return 0; | |||
1237 | } | |||
1238 | ||||
1239 | /* | |||
1240 | * handle a bus reset: reset chip, unqueue all active commands, free all | |||
1241 | * target struct and report lossage to upper layer. | |||
1242 | * As the upper layer may requeue immediately we have to first store | |||
1243 | * all active commands in a temporary queue. | |||
1244 | */ | |||
1245 | void | |||
1246 | siop_handle_reset(struct siop_softc *sc) | |||
1247 | { | |||
1248 | struct cmd_list reset_list; | |||
1249 | struct siop_cmd *siop_cmd, *next_siop_cmd; | |||
1250 | struct siop_lun *siop_lun; | |||
1251 | int target, lun, tag, buswidth; | |||
1252 | /* | |||
1253 | * scsi bus reset. reset the chip and restart | |||
1254 | * the queue. Need to clean up all active commands | |||
1255 | */ | |||
1256 | printf("%s: scsi bus reset\n", sc->sc_c.sc_dev.dv_xname); | |||
1257 | /* stop, reset and restart the chip */ | |||
1258 | siop_reset(sc); | |||
1259 | TAILQ_INIT(&reset_list)do { (&reset_list)->tqh_first = ((void *)0); (&reset_list )->tqh_last = &(&reset_list)->tqh_first; } while (0); | |||
1260 | /* | |||
1261 | * Process all commands: first commands being executed | |||
1262 | */ | |||
1263 | buswidth = (sc->sc_c.features & SF_BUS_WIDE0x00000001) ? 16 : 8; | |||
1264 | for (target = 0; target < buswidth; target++) { | |||
1265 | if (sc->sc_c.targets[target] == NULL((void *)0)) | |||
1266 | continue; | |||
1267 | for (lun = 0; lun < 8; lun++) { | |||
1268 | struct siop_target *siop_target = | |||
1269 | (struct siop_target *)sc->sc_c.targets[target]; | |||
1270 | siop_lun = siop_target->siop_lun[lun]; | |||
1271 | if (siop_lun == NULL((void *)0)) | |||
1272 | continue; | |||
1273 | siop_lun->lun_flags &= ~SIOP_LUNF_FULL0x01; | |||
1274 | for (tag = 0; tag < | |||
1275 | ((sc->sc_c.targets[target]->flags & TARF_TAG0x04) ? | |||
1276 | SIOP_NTAG16 : 1); | |||
1277 | tag++) { | |||
1278 | siop_cmd = siop_lun->siop_tag[tag].active; | |||
1279 | if (siop_cmd == NULL((void *)0)) | |||
1280 | continue; | |||
1281 | siop_lun->siop_tag[tag].active = NULL((void *)0); | |||
1282 | TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next)do { (siop_cmd)->next.tqe_next = ((void *)0); (siop_cmd)-> next.tqe_prev = (&reset_list)->tqh_last; *(&reset_list )->tqh_last = (siop_cmd); (&reset_list)->tqh_last = &(siop_cmd)->next.tqe_next; } while (0); | |||
1283 | sc_print_addr(siop_cmd->cmd_c.xs->sc_link); | |||
1284 | printf("cmd %p (tag %d) added to reset list\n", | |||
1285 | siop_cmd, tag); | |||
1286 | } | |||
1287 | } | |||
1288 | if (sc->sc_c.targets[target]->status != TARST_PROBING0) { | |||
1289 | sc->sc_c.targets[target]->status = TARST_ASYNC1; | |||
1290 | sc->sc_c.targets[target]->flags &= ~TARF_ISWIDE0x10; | |||
1291 | sc->sc_c.targets[target]->period = | |||
1292 | sc->sc_c.targets[target]->offset = 0; | |||
1293 | siop_update_xfer_mode(&sc->sc_c, target); | |||
1294 | } | |||
1295 | } | |||
1296 | /* Next commands from the urgent list */ | |||
1297 | for (siop_cmd = TAILQ_FIRST(&sc->urgent_list)((&sc->urgent_list)->tqh_first); siop_cmd != NULL((void *)0); | |||
1298 | siop_cmd = next_siop_cmd) { | |||
1299 | next_siop_cmd = TAILQ_NEXT(siop_cmd, next)((siop_cmd)->next.tqe_next); | |||
1300 | TAILQ_REMOVE(&sc->urgent_list, siop_cmd, next)do { if (((siop_cmd)->next.tqe_next) != ((void *)0)) (siop_cmd )->next.tqe_next->next.tqe_prev = (siop_cmd)->next.tqe_prev ; else (&sc->urgent_list)->tqh_last = (siop_cmd)-> next.tqe_prev; *(siop_cmd)->next.tqe_prev = (siop_cmd)-> next.tqe_next; ((siop_cmd)->next.tqe_prev) = ((void *)-1); ((siop_cmd)->next.tqe_next) = ((void *)-1); } while (0); | |||
1301 | TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next)do { (siop_cmd)->next.tqe_next = ((void *)0); (siop_cmd)-> next.tqe_prev = (&reset_list)->tqh_last; *(&reset_list )->tqh_last = (siop_cmd); (&reset_list)->tqh_last = &(siop_cmd)->next.tqe_next; } while (0); | |||
1302 | sc_print_addr(siop_cmd->cmd_c.xs->sc_link); | |||
1303 | printf("cmd %p added to reset list from urgent list\n", | |||
1304 | siop_cmd); | |||
1305 | } | |||
1306 | /* Then commands waiting in the input list. */ | |||
1307 | for (siop_cmd = TAILQ_FIRST(&sc->ready_list)((&sc->ready_list)->tqh_first); siop_cmd != NULL((void *)0); | |||
1308 | siop_cmd = next_siop_cmd) { | |||
1309 | next_siop_cmd = TAILQ_NEXT(siop_cmd, next)((siop_cmd)->next.tqe_next); | |||
1310 | TAILQ_REMOVE(&sc->ready_list, siop_cmd, next)do { if (((siop_cmd)->next.tqe_next) != ((void *)0)) (siop_cmd )->next.tqe_next->next.tqe_prev = (siop_cmd)->next.tqe_prev ; else (&sc->ready_list)->tqh_last = (siop_cmd)-> next.tqe_prev; *(siop_cmd)->next.tqe_prev = (siop_cmd)-> next.tqe_next; ((siop_cmd)->next.tqe_prev) = ((void *)-1); ((siop_cmd)->next.tqe_next) = ((void *)-1); } while (0); | |||
1311 | TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next)do { (siop_cmd)->next.tqe_next = ((void *)0); (siop_cmd)-> next.tqe_prev = (&reset_list)->tqh_last; *(&reset_list )->tqh_last = (siop_cmd); (&reset_list)->tqh_last = &(siop_cmd)->next.tqe_next; } while (0); | |||
1312 | sc_print_addr(siop_cmd->cmd_c.xs->sc_link); | |||
1313 | printf("cmd %p added to reset list from ready list\n", | |||
1314 | siop_cmd); | |||
1315 | } | |||
1316 | ||||
1317 | for (siop_cmd = TAILQ_FIRST(&reset_list)((&reset_list)->tqh_first); siop_cmd != NULL((void *)0); | |||
1318 | siop_cmd = next_siop_cmd) { | |||
1319 | next_siop_cmd = TAILQ_NEXT(siop_cmd, next)((siop_cmd)->next.tqe_next); | |||
1320 | siop_cmd->cmd_c.flags &= ~CMDFL_TAG0x0002; | |||
1321 | siop_cmd->cmd_c.xs->error = | |||
1322 | (siop_cmd->cmd_c.flags & CMDFL_TIMEOUT0x0001) | |||
1323 | ? XS_TIMEOUT4 : XS_RESET8; | |||
1324 | siop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK0xfe; | |||
1325 | sc_print_addr(siop_cmd->cmd_c.xs->sc_link); | |||
1326 | printf("cmd %p (status %d) reset", | |||
1327 | siop_cmd, siop_cmd->cmd_c.status); | |||
1328 | if (siop_cmd->cmd_c.status == CMDST_SENSE3 || | |||
1329 | siop_cmd->cmd_c.status == CMDST_SENSE_ACTIVE4) | |||
1330 | siop_cmd->cmd_c.status = CMDST_SENSE_DONE5; | |||
1331 | else | |||
1332 | siop_cmd->cmd_c.status = CMDST_DONE6; | |||
1333 | printf(" with status %d, xs->error %d\n", | |||
1334 | siop_cmd->cmd_c.status, siop_cmd->cmd_c.xs->error); | |||
1335 | TAILQ_REMOVE(&reset_list, siop_cmd, next)do { if (((siop_cmd)->next.tqe_next) != ((void *)0)) (siop_cmd )->next.tqe_next->next.tqe_prev = (siop_cmd)->next.tqe_prev ; else (&reset_list)->tqh_last = (siop_cmd)->next.tqe_prev ; *(siop_cmd)->next.tqe_prev = (siop_cmd)->next.tqe_next ; ((siop_cmd)->next.tqe_prev) = ((void *)-1); ((siop_cmd)-> next.tqe_next) = ((void *)-1); } while (0); | |||
1336 | siop_scsicmd_end(siop_cmd); | |||
1337 | } | |||
1338 | } | |||
1339 | ||||
1340 | void * | |||
1341 | siop_cmd_get(void *cookie) | |||
1342 | { | |||
1343 | struct siop_softc *sc = cookie; | |||
1344 | struct siop_cmd *siop_cmd; | |||
1345 | int s; | |||
1346 | ||||
1347 | /* Look if a ccb is available. */ | |||
1348 | s = splbio()splraise(0x6); | |||
1349 | siop_cmd = TAILQ_FIRST(&sc->free_list)((&sc->free_list)->tqh_first); | |||
1350 | if (siop_cmd != NULL((void *)0)) { | |||
1351 | TAILQ_REMOVE(&sc->free_list, siop_cmd, next)do { if (((siop_cmd)->next.tqe_next) != ((void *)0)) (siop_cmd )->next.tqe_next->next.tqe_prev = (siop_cmd)->next.tqe_prev ; else (&sc->free_list)->tqh_last = (siop_cmd)-> next.tqe_prev; *(siop_cmd)->next.tqe_prev = (siop_cmd)-> next.tqe_next; ((siop_cmd)->next.tqe_prev) = ((void *)-1); ((siop_cmd)->next.tqe_next) = ((void *)-1); } while (0); | |||
1352 | #ifdef DIAGNOSTIC1 | |||
1353 | if (siop_cmd->cmd_c.status != CMDST_FREE0) | |||
1354 | panic("siop_scsicmd: new cmd not free"); | |||
1355 | #endif | |||
1356 | siop_cmd->cmd_c.status = CMDST_READY1; | |||
1357 | } | |||
1358 | splx(s)spllower(s); | |||
1359 | ||||
1360 | return (siop_cmd); | |||
1361 | } | |||
1362 | ||||
1363 | void | |||
1364 | siop_cmd_put(void *cookie, void *io) | |||
1365 | { | |||
1366 | struct siop_softc *sc = cookie; | |||
1367 | struct siop_cmd *siop_cmd = io; | |||
1368 | int s; | |||
1369 | ||||
1370 | s = splbio()splraise(0x6); | |||
1371 | siop_cmd->cmd_c.status = CMDST_FREE0; | |||
1372 | TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next)do { (siop_cmd)->next.tqe_next = ((void *)0); (siop_cmd)-> next.tqe_prev = (&sc->free_list)->tqh_last; *(& sc->free_list)->tqh_last = (siop_cmd); (&sc->free_list )->tqh_last = &(siop_cmd)->next.tqe_next; } while ( 0); | |||
1373 | splx(s)spllower(s); | |||
1374 | } | |||
1375 | ||||
1376 | int | |||
1377 | siop_scsiprobe(struct scsi_link *link) | |||
1378 | { | |||
1379 | struct siop_softc *sc = link->bus->sb_adapter_softc; | |||
1380 | struct siop_target *siop_target; | |||
1381 | const int target = link->target; | |||
1382 | const int lun = link->lun; | |||
1383 | int i; | |||
1384 | ||||
1385 | #ifdef SIOP_DEBUG | |||
1386 | printf("%s:%d:%d: probe\n", | |||
1387 | sc->sc_c.sc_dev.dv_xname, target, lun); | |||
1388 | #endif | |||
1389 | ||||
1390 | /* XXX locking */ | |||
1391 | ||||
1392 | siop_target = (struct siop_target*)sc->sc_c.targets[target]; | |||
1393 | if (siop_target == NULL((void *)0)) { | |||
1394 | siop_target = malloc(sizeof(*siop_target), M_DEVBUF2, | |||
1395 | M_WAITOK0x0001 | M_CANFAIL0x0004 | M_ZERO0x0008); | |||
1396 | if (siop_target == NULL((void *)0)) { | |||
1397 | printf("%s: can't malloc memory for target %d\n", | |||
1398 | sc->sc_c.sc_dev.dv_xname, target); | |||
1399 | return (ENOMEM12); | |||
1400 | } | |||
1401 | ||||
1402 | siop_target->target_c.status = TARST_PROBING0; | |||
1403 | siop_target->target_c.flags = 0; | |||
1404 | siop_target->target_c.id = | |||
1405 | sc->sc_c.clock_div << 24; /* scntl3 */ | |||
1406 | siop_target->target_c.id |= target << 16; /* id */ | |||
1407 | /* siop_target->target_c.id |= 0x0 << 8; scxfer is 0 */ | |||
1408 | ||||
1409 | /* get a lun switch script */ | |||
1410 | siop_target->lunsw = siop_get_lunsw(sc); | |||
1411 | if (siop_target->lunsw == NULL((void *)0)) { | |||
1412 | printf("%s: can't alloc lunsw for target %d\n", | |||
1413 | sc->sc_c.sc_dev.dv_xname, target); | |||
1414 | free(siop_target, M_DEVBUF2, sizeof *siop_target); | |||
1415 | return (ENOMEM12); | |||
1416 | } | |||
1417 | for (i = 0; i < 8; i++) | |||
1418 | siop_target->siop_lun[i] = NULL((void *)0); | |||
1419 | ||||
1420 | sc->sc_c.targets[target] = | |||
1421 | (struct siop_common_target *)siop_target; | |||
1422 | ||||
1423 | siop_add_reselsw(sc, target); | |||
1424 | } | |||
1425 | ||||
1426 | if (siop_target->siop_lun[lun] == NULL((void *)0)) { | |||
1427 | siop_target->siop_lun[lun] = | |||
1428 | malloc(sizeof(struct siop_lun), M_DEVBUF2, | |||
1429 | M_WAITOK0x0001 | M_CANFAIL0x0004 | M_ZERO0x0008); | |||
1430 | if (siop_target->siop_lun[lun] == NULL((void *)0)) { | |||
1431 | printf("%s: can't alloc siop_lun for " | |||
1432 | "target %d lun %d\n", | |||
1433 | sc->sc_c.sc_dev.dv_xname, target, lun); | |||
1434 | return (ENOMEM12); | |||
1435 | } | |||
1436 | } | |||
1437 | ||||
1438 | return (0); | |||
1439 | } | |||
1440 | ||||
1441 | void | |||
1442 | siop_scsicmd(struct scsi_xfer *xs) | |||
1443 | { | |||
1444 | struct siop_softc *sc = xs->sc_link->bus->sb_adapter_softc; | |||
1445 | struct siop_cmd *siop_cmd; | |||
1446 | struct siop_target *siop_target; | |||
1447 | int s, error, i, j; | |||
1448 | const int target = xs->sc_link->target; | |||
1449 | const int lun = xs->sc_link->lun; | |||
1450 | ||||
1451 | #ifdef SIOP_DEBUG_SCHED | |||
1452 | printf("starting cmd for %d:%d\n", target, lun); | |||
1453 | #endif | |||
1454 | ||||
1455 | siop_target = (struct siop_target*)sc->sc_c.targets[target]; | |||
1456 | siop_cmd = xs->io; | |||
1457 | ||||
1458 | /* | |||
1459 | * The xs may have been restarted by the scsi layer, so ensure the ccb | |||
1460 | * starts in the proper state. | |||
1461 | */ | |||
1462 | siop_cmd->cmd_c.status = CMDST_READY1; | |||
1463 | ||||
1464 | /* Always reset xs->stimeout, lest we timeout_del() with trash */ | |||
1465 | timeout_set(&xs->stimeout, siop_timeout, siop_cmd); | |||
1466 | ||||
1467 | siop_cmd->cmd_c.siop_target = sc->sc_c.targets[target]; | |||
1468 | siop_cmd->cmd_c.xs = xs; | |||
1469 | siop_cmd->cmd_c.flags = 0; | |||
1470 | ||||
1471 | bzero(&siop_cmd->cmd_c.siop_tables->xscmd,__builtin_bzero((&siop_cmd->cmd_c.siop_tables->xscmd ), (sizeof(siop_cmd->cmd_c.siop_tables->xscmd))) | |||
1472 | sizeof(siop_cmd->cmd_c.siop_tables->xscmd))__builtin_bzero((&siop_cmd->cmd_c.siop_tables->xscmd ), (sizeof(siop_cmd->cmd_c.siop_tables->xscmd))); | |||
1473 | bcopy(&xs->cmd, &siop_cmd->cmd_c.siop_tables->xscmd, xs->cmdlen); | |||
1474 | siop_cmd->cmd_c.siop_tables->cmd.count = | |||
1475 | siop_htoc32(&sc->sc_c, xs->cmdlen)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((xs->cmdlen)) ? (__uint32_t)(((__uint32_t )((xs->cmdlen)) & 0xff) << 24 | ((__uint32_t)((xs ->cmdlen)) & 0xff00) << 8 | ((__uint32_t)((xs-> cmdlen)) & 0xff0000) >> 8 | ((__uint32_t)((xs->cmdlen )) & 0xff000000) >> 24) : __swap32md((xs->cmdlen ))) : ((__uint32_t)((xs->cmdlen)))); | |||
1476 | ||||
1477 | /* load the DMA maps */ | |||
1478 | if (xs->flags & (SCSI_DATA_IN0x00800 | SCSI_DATA_OUT0x01000)) { | |||
1479 | error = bus_dmamap_load(sc->sc_c.sc_dmat,(*(sc->sc_c.sc_dmat)->_dmamap_load)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (xs->data), (xs->datalen ), (((void *)0)), (0x0001 | 0x0100 | ((xs->flags & 0x00800 ) ? 0x0200 : 0x0400))) | |||
1480 | siop_cmd->cmd_c.dmamap_data, xs->data, xs->datalen,(*(sc->sc_c.sc_dmat)->_dmamap_load)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (xs->data), (xs->datalen ), (((void *)0)), (0x0001 | 0x0100 | ((xs->flags & 0x00800 ) ? 0x0200 : 0x0400))) | |||
1481 | NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING |(*(sc->sc_c.sc_dmat)->_dmamap_load)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (xs->data), (xs->datalen ), (((void *)0)), (0x0001 | 0x0100 | ((xs->flags & 0x00800 ) ? 0x0200 : 0x0400))) | |||
1482 | ((xs->flags & SCSI_DATA_IN) ?(*(sc->sc_c.sc_dmat)->_dmamap_load)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (xs->data), (xs->datalen ), (((void *)0)), (0x0001 | 0x0100 | ((xs->flags & 0x00800 ) ? 0x0200 : 0x0400))) | |||
1483 | BUS_DMA_READ : BUS_DMA_WRITE))(*(sc->sc_c.sc_dmat)->_dmamap_load)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (xs->data), (xs->datalen ), (((void *)0)), (0x0001 | 0x0100 | ((xs->flags & 0x00800 ) ? 0x0200 : 0x0400))); | |||
1484 | if (error) { | |||
1485 | printf("%s: unable to load data DMA map: %d\n", | |||
1486 | sc->sc_c.sc_dev.dv_xname, error); | |||
1487 | xs->error = XS_DRIVER_STUFFUP2; | |||
1488 | scsi_done(xs); | |||
1489 | return; | |||
1490 | } | |||
1491 | bus_dmamap_sync(sc->sc_c.sc_dmat,(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (0), (siop_cmd->cmd_c .dmamap_data->dm_mapsize), ((xs->flags & 0x00800) ? 0x01 : 0x04)) | |||
1492 | siop_cmd->cmd_c.dmamap_data, 0,(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (0), (siop_cmd->cmd_c .dmamap_data->dm_mapsize), ((xs->flags & 0x00800) ? 0x01 : 0x04)) | |||
1493 | siop_cmd->cmd_c.dmamap_data->dm_mapsize,(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (0), (siop_cmd->cmd_c .dmamap_data->dm_mapsize), ((xs->flags & 0x00800) ? 0x01 : 0x04)) | |||
1494 | (xs->flags & SCSI_DATA_IN) ?(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (0), (siop_cmd->cmd_c .dmamap_data->dm_mapsize), ((xs->flags & 0x00800) ? 0x01 : 0x04)) | |||
1495 | BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)(*(sc->sc_c.sc_dmat)->_dmamap_sync)((sc->sc_c.sc_dmat ), (siop_cmd->cmd_c.dmamap_data), (0), (siop_cmd->cmd_c .dmamap_data->dm_mapsize), ((xs->flags & 0x00800) ? 0x01 : 0x04)); | |||
1496 | } | |||
1497 | ||||
1498 | siop_setuptables(&siop_cmd->cmd_c); | |||
1499 | siop_cmd->saved_offset = SIOP_NOOFFSET0xffffffff; | |||
1500 | siop_table_sync(siop_cmd, | |||
1501 | BUS_DMASYNC_PREREAD0x01 | BUS_DMASYNC_PREWRITE0x04); | |||
1502 | ||||
1503 | /* Negotiate transfer parameters on first non-polling command. */ | |||
1504 | if (((xs->flags & SCSI_POLL0x00002) == 0) && | |||
1505 | siop_target->target_c.status == TARST_PROBING0) | |||
1506 | siop_target->target_c.status = TARST_ASYNC1; | |||
1507 | ||||
1508 | s = splbio()splraise(0x6); | |||
1509 | TAILQ_INSERT_TAIL(&sc->ready_list, siop_cmd, next)do { (siop_cmd)->next.tqe_next = ((void *)0); (siop_cmd)-> next.tqe_prev = (&sc->ready_list)->tqh_last; *(& sc->ready_list)->tqh_last = (siop_cmd); (&sc->ready_list )->tqh_last = &(siop_cmd)->next.tqe_next; } while ( 0); | |||
1510 | siop_start(sc); | |||
1511 | if ((xs->flags & SCSI_POLL0x00002) == 0) { | |||
1512 | splx(s)spllower(s); | |||
1513 | return; | |||
1514 | } | |||
1515 | ||||
1516 | /* Poll for command completion. */ | |||
1517 | for(i = xs->timeout; i > 0; i--) { | |||
1518 | siop_intr(sc); | |||
1519 | if ((xs->flags & ITSDONE0x00008) == 0) { | |||
1520 | delay(1000)(*delay_func)(1000); | |||
1521 | continue; | |||
1522 | } | |||
1523 | if (xs->cmd.opcode == INQUIRY0x12 && xs->error == XS_NOERROR0) { | |||
1524 | struct scsi_inquiry_data *inqbuf = | |||
1525 | (struct scsi_inquiry_data *)xs->data; | |||
1526 | if ((inqbuf->device & SID_QUAL0xe0) == SID_QUAL_BAD_LU0x60) | |||
1527 | break; | |||
1528 | /* | |||
1529 | * Allocate cbd's to hold maximum openings worth of | |||
1530 | * commands. Do this now because doing it dynamically in | |||
1531 | * siop_startcmd may cause calls to bus_dma* functions | |||
1532 | * in interrupt context. | |||
1533 | */ | |||
1534 | for (j = 0; j < SIOP_NTAG16; j += SIOP_NCMDPB((1 << 12) / sizeof(struct siop_xfer))) | |||
1535 | siop_morecbd(sc); | |||
1536 | ||||
1537 | /* | |||
1538 | * Set TARF_DT here because if it is turned off during | |||
1539 | * PPR, it must STAY off! | |||
1540 | */ | |||
1541 | if ((lun == 0) && (sc->sc_c.features & SF_BUS_ULTRA30x00000008)) | |||
1542 | sc->sc_c.targets[target]->flags |= TARF_DT0x08; | |||
1543 | /* | |||
1544 | * Can't do lun 0 here, because flags are not set yet. | |||
1545 | * But have to do other lun's here because they never go | |||
1546 | * through TARST_ASYNC. | |||
1547 | */ | |||
1548 | if (lun > 0) | |||
1549 | siop_add_dev(sc, target, lun); | |||
1550 | } | |||
1551 | break; | |||
1552 | } | |||
1553 | if (i == 0) { | |||
1554 | siop_timeout(siop_cmd); | |||
1555 | while ((xs->flags & ITSDONE0x00008) == 0) | |||
1556 | siop_intr(sc); | |||
1557 | } | |||
1558 | ||||
1559 | splx(s)spllower(s); | |||
1560 | } | |||
1561 | ||||
1562 | void | |||
1563 | siop_start(struct siop_softc *sc) | |||
1564 | { | |||
1565 | struct siop_cmd *siop_cmd, *next_siop_cmd; | |||
1566 | struct siop_lun *siop_lun; | |||
1567 | struct siop_xfer *siop_xfer; | |||
1568 | u_int32_t dsa; | |||
1569 | int target, lun, tag, slot; | |||
1570 | int newcmd = 0; | |||
1571 | int doingready = 0; | |||
1572 | ||||
1573 | /* | |||
1574 | * first make sure to read valid data | |||
1575 | */ | |||
1576 | siop_script_sync(sc, BUS_DMASYNC_POSTREAD0x02 | BUS_DMASYNC_POSTWRITE0x08); | |||
1577 | ||||
1578 | /* | |||
1579 | * The queue management here is a bit tricky: the script always looks | |||
1580 | * at the slot from first to last, so if we always use the first | |||
1581 | * free slot commands can stay at the tail of the queue ~forever. | |||
1582 | * The algorithm used here is to restart from the head when we know | |||
1583 | * that the queue is empty, and only add commands after the last one. | |||
1584 | * When we're at the end of the queue wait for the script to clear it. | |||
1585 | * The best thing to do here would be to implement a circular queue, | |||
1586 | * but using only 53c720 features this can be "interesting". | |||
1587 | * A mid-way solution could be to implement 2 queues and swap orders. | |||
1588 | */ | |||
1589 | slot = sc->sc_currschedslot; | |||
1590 | /* | |||
1591 | * If the instruction is 0x80000000 (JUMP foo, IF FALSE) the slot is | |||
1592 | * free. As this is the last used slot, all previous slots are free, | |||
1593 | * we can restart from 1. | |||
1594 | * slot 0 is reserved for request sense commands. | |||
1595 | */ | |||
1596 | if (siop_script_read(sc, (Ent_script_sched_slot00x000000a0 / 4) + slot * 2) == | |||
1597 | 0x80000000) { | |||
1598 | slot = sc->sc_currschedslot = 1; | |||
1599 | } else { | |||
1600 | slot++; | |||
1601 | } | |||
1602 | /* first handle commands from the urgent list */ | |||
1603 | siop_cmd = TAILQ_FIRST(&sc->urgent_list)((&sc->urgent_list)->tqh_first); | |||
1604 | again: | |||
1605 | for (; siop_cmd != NULL((void *)0); siop_cmd = next_siop_cmd) { | |||
1606 | next_siop_cmd = TAILQ_NEXT(siop_cmd, next)((siop_cmd)->next.tqe_next); | |||
1607 | #ifdef DIAGNOSTIC1 | |||
1608 | if (siop_cmd->cmd_c.status != CMDST_READY1 && | |||
1609 | siop_cmd->cmd_c.status != CMDST_SENSE3) | |||
1610 | panic("siop: non-ready cmd in ready list"); | |||
1611 | #endif | |||
1612 | target = siop_cmd->cmd_c.xs->sc_link->target; | |||
1613 | lun = siop_cmd->cmd_c.xs->sc_link->lun; | |||
1614 | siop_lun = | |||
1615 | ((struct siop_target*)sc->sc_c.targets[target])->siop_lun[lun]; | |||
1616 | /* if non-tagged command active, wait */ | |||
1617 | if (siop_lun->siop_tag[0].active != NULL((void *)0)) | |||
1618 | continue; | |||
1619 | /* | |||
1620 | * if we're in a queue full condition don't start a new | |||
1621 | * command, unless it's a request sense | |||
1622 | */ | |||
1623 | if ((siop_lun->lun_flags & SIOP_LUNF_FULL0x01) && | |||
1624 | siop_cmd->cmd_c.status == CMDST_READY1) | |||
1625 | continue; | |||
1626 | /* find a free tag if needed */ | |||
1627 | if (siop_cmd->cmd_c.flags & CMDFL_TAG0x0002) { | |||
1628 | for (tag = 1; tag < SIOP_NTAG16; tag++) { | |||
1629 | if (siop_lun->siop_tag[tag].active == NULL((void *)0)) | |||
1630 | break; | |||
1631 | } | |||
1632 | if (tag == SIOP_NTAG16) /* no free tag */ | |||
1633 | continue; | |||
1634 | } else { | |||
1635 | tag = 0; | |||
1636 | } | |||
1637 | siop_cmd->cmd_c.tag = tag; | |||
1638 | /* | |||
1639 | * find a free scheduler slot and load it. If it's a request | |||
1640 | * sense we need to use slot 0. | |||
1641 | */ | |||
1642 | if (siop_cmd->cmd_c.status != CMDST_SENSE3) { | |||
1643 | for (; slot < SIOP_NSLOTS40; slot++) { | |||
1644 | /* | |||
1645 | * If cmd if 0x80000000 the slot is free | |||
1646 | */ | |||
1647 | if (siop_script_read(sc, | |||
1648 | (Ent_script_sched_slot00x000000a0 / 4) + slot * 2) == | |||
1649 | 0x80000000) | |||
1650 | break; | |||
1651 | } | |||
1652 | /* no more free slots, no need to continue */ | |||
1653 | if (slot == SIOP_NSLOTS40) { | |||
1654 | goto end; | |||
1655 | } | |||
1656 | } else { | |||
1657 | slot = 0; | |||
1658 | if (siop_script_read(sc, Ent_script_sched_slot00x000000a0 / 4) | |||
1659 | != 0x80000000) | |||
1660 | goto end; | |||
1661 | } | |||
1662 | ||||
1663 | #ifdef SIOP_DEBUG_SCHED | |||
1664 | printf("using slot %d for DSA 0x%lx\n", slot, | |||
1665 | (u_long)siop_cmd->cmd_c.dsa); | |||
1666 | #endif | |||
1667 | /* Ok, we can add the tag message */ | |||
1668 | if (tag > 0) { | |||
1669 | #ifdef DIAGNOSTIC1 | |||
1670 | int msgcount = siop_ctoh32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((siop_cmd->cmd_c.siop_tables->t_msgout .count)) ? (__uint32_t)(((__uint32_t)((siop_cmd->cmd_c.siop_tables ->t_msgout.count)) & 0xff) << 24 | ((__uint32_t) ((siop_cmd->cmd_c.siop_tables->t_msgout.count)) & 0xff00 ) << 8 | ((__uint32_t)((siop_cmd->cmd_c.siop_tables-> t_msgout.count)) & 0xff0000) >> 8 | ((__uint32_t)(( siop_cmd->cmd_c.siop_tables->t_msgout.count)) & 0xff000000 ) >> 24) : __swap32md((siop_cmd->cmd_c.siop_tables-> t_msgout.count))) : ((__uint32_t)((siop_cmd->cmd_c.siop_tables ->t_msgout.count)))) | |||
1671 | siop_cmd->cmd_tables->t_msgout.count)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((siop_cmd->cmd_c.siop_tables->t_msgout .count)) ? (__uint32_t)(((__uint32_t)((siop_cmd->cmd_c.siop_tables ->t_msgout.count)) & 0xff) << 24 | ((__uint32_t) ((siop_cmd->cmd_c.siop_tables->t_msgout.count)) & 0xff00 ) << 8 | ((__uint32_t)((siop_cmd->cmd_c.siop_tables-> t_msgout.count)) & 0xff0000) >> 8 | ((__uint32_t)(( siop_cmd->cmd_c.siop_tables->t_msgout.count)) & 0xff000000 ) >> 24) : __swap32md((siop_cmd->cmd_c.siop_tables-> t_msgout.count))) : ((__uint32_t)((siop_cmd->cmd_c.siop_tables ->t_msgout.count)))); | |||
1672 | if (msgcount != 1) | |||
1673 | printf("%s:%d:%d: tag %d with msgcount %d\n", | |||
1674 | sc->sc_c.sc_dev.dv_xname, target, lun, tag, | |||
1675 | msgcount); | |||
1676 | #endif | |||
1677 | siop_cmd->cmd_tablescmd_c.siop_tables->msg_out[1] = MSG_SIMPLE_Q_TAG0x20; | |||
1678 | siop_cmd->cmd_tablescmd_c.siop_tables->msg_out[2] = tag; | |||
1679 | siop_cmd->cmd_tablescmd_c.siop_tables->t_msgout.count = | |||
1680 | siop_htoc32(&sc->sc_c, 3)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((3)) ? (__uint32_t)(((__uint32_t)((3)) & 0xff) << 24 | ((__uint32_t)((3)) & 0xff00) << 8 | ((__uint32_t)((3)) & 0xff0000) >> 8 | ((__uint32_t )((3)) & 0xff000000) >> 24) : __swap32md((3))) : (( __uint32_t)((3)))); | |||
1681 | } | |||
1682 | /* note that we started a new command */ | |||
1683 | newcmd = 1; | |||
1684 | /* mark command as active */ | |||
1685 | if (siop_cmd->cmd_c.status == CMDST_READY1) { | |||
1686 | siop_cmd->cmd_c.status = CMDST_ACTIVE2; | |||
1687 | } else if (siop_cmd->cmd_c.status == CMDST_SENSE3) { | |||
1688 | siop_cmd->cmd_c.status = CMDST_SENSE_ACTIVE4; | |||
1689 | } else | |||
1690 | panic("siop_start: bad status"); | |||
1691 | if (doingready) | |||
1692 | TAILQ_REMOVE(&sc->ready_list, siop_cmd, next)do { if (((siop_cmd)->next.tqe_next) != ((void *)0)) (siop_cmd )->next.tqe_next->next.tqe_prev = (siop_cmd)->next.tqe_prev ; else (&sc->ready_list)->tqh_last = (siop_cmd)-> next.tqe_prev; *(siop_cmd)->next.tqe_prev = (siop_cmd)-> next.tqe_next; ((siop_cmd)->next.tqe_prev) = ((void *)-1); ((siop_cmd)->next.tqe_next) = ((void *)-1); } while (0); | |||
1693 | else | |||
1694 | TAILQ_REMOVE(&sc->urgent_list, siop_cmd, next)do { if (((siop_cmd)->next.tqe_next) != ((void *)0)) (siop_cmd )->next.tqe_next->next.tqe_prev = (siop_cmd)->next.tqe_prev ; else (&sc->urgent_list)->tqh_last = (siop_cmd)-> next.tqe_prev; *(siop_cmd)->next.tqe_prev = (siop_cmd)-> next.tqe_next; ((siop_cmd)->next.tqe_prev) = ((void *)-1); ((siop_cmd)->next.tqe_next) = ((void *)-1); } while (0); | |||
1695 | siop_lun->siop_tag[tag].active = siop_cmd; | |||
1696 | /* patch scripts with DSA addr */ | |||
1697 | dsa = siop_cmd->cmd_c.dsa; | |||
1698 | /* first reselect switch, if we have an entry */ | |||
1699 | if (siop_lun->siop_tag[tag].reseloff > 0) | |||
1700 | siop_script_write(sc, | |||
1701 | siop_lun->siop_tag[tag].reseloff + 1, | |||
1702 | dsa + sizeof(struct siop_common_xfer) + | |||
1703 | Ent_ldsa_reload_dsa0x00000028); | |||
1704 | /* CMD script: MOVE MEMORY addr */ | |||
1705 | siop_xfer = (struct siop_xfer*)siop_cmd->cmd_tablescmd_c.siop_tables; | |||
1706 | siop_xfer->resel[E_ldsa_abs_slot_Used[0]] = | |||
1707 | siop_htoc32(&sc->sc_c, sc->sc_c.sc_scriptaddr +(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_scriptaddr + 0x000000a0 + slot * 8)) ? (__uint32_t)(((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000000a0 + slot * 8)) & 0xff) << 24 | ((__uint32_t )((sc->sc_c.sc_scriptaddr + 0x000000a0 + slot * 8)) & 0xff00 ) << 8 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000000a0 + slot * 8)) & 0xff0000) >> 8 | ((__uint32_t)((sc-> sc_c.sc_scriptaddr + 0x000000a0 + slot * 8)) & 0xff000000 ) >> 24) : __swap32md((sc->sc_c.sc_scriptaddr + 0x000000a0 + slot * 8))) : ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000000a0 + slot * 8)))) | |||
1708 | Ent_script_sched_slot0 + slot * 8)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_scriptaddr + 0x000000a0 + slot * 8)) ? (__uint32_t)(((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000000a0 + slot * 8)) & 0xff) << 24 | ((__uint32_t )((sc->sc_c.sc_scriptaddr + 0x000000a0 + slot * 8)) & 0xff00 ) << 8 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000000a0 + slot * 8)) & 0xff0000) >> 8 | ((__uint32_t)((sc-> sc_c.sc_scriptaddr + 0x000000a0 + slot * 8)) & 0xff000000 ) >> 24) : __swap32md((sc->sc_c.sc_scriptaddr + 0x000000a0 + slot * 8))) : ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000000a0 + slot * 8)))); | |||
1709 | siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE0x04); | |||
1710 | /* scheduler slot: JUMP ldsa_select */ | |||
1711 | siop_script_write(sc, | |||
1712 | (Ent_script_sched_slot00x000000a0 / 4) + slot * 2 + 1, | |||
1713 | dsa + sizeof(struct siop_common_xfer) + Ent_ldsa_select0x00000038); | |||
1714 | /* handle timeout */ | |||
1715 | if (siop_cmd->cmd_c.status == CMDST_ACTIVE2) { | |||
1716 | if ((siop_cmd->cmd_c.xs->flags & SCSI_POLL0x00002) == 0) { | |||
1717 | /* start expire timer */ | |||
1718 | timeout_add_msec(&siop_cmd->cmd_c.xs->stimeout, | |||
1719 | siop_cmd->cmd_c.xs->timeout); | |||
1720 | } | |||
1721 | } | |||
1722 | /* | |||
1723 | * Change JUMP cmd so that this slot will be handled | |||
1724 | */ | |||
1725 | siop_script_write(sc, (Ent_script_sched_slot00x000000a0 / 4) + slot * 2, | |||
1726 | 0x80080000); | |||
1727 | /* if we're using the request sense slot, stop here */ | |||
1728 | if (slot == 0) | |||
1729 | goto end; | |||
1730 | sc->sc_currschedslot = slot; | |||
1731 | slot++; | |||
1732 | } | |||
1733 | if (doingready == 0) { | |||
1734 | /* now process ready list */ | |||
1735 | doingready = 1; | |||
1736 | siop_cmd = TAILQ_FIRST(&sc->ready_list)((&sc->ready_list)->tqh_first); | |||
1737 | goto again; | |||
1738 | } | |||
1739 | ||||
1740 | end: | |||
1741 | /* if nothing changed no need to flush cache and wakeup script */ | |||
1742 | if (newcmd == 0) | |||
1743 | return; | |||
1744 | /* make sure SCRIPT processor will read valid data */ | |||
1745 | siop_script_sync(sc,BUS_DMASYNC_PREREAD0x01 | BUS_DMASYNC_PREWRITE0x04); | |||
1746 | /* Signal script it has some work to do */ | |||
1747 | bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,((sc->sc_c.sc_rt)->write_1((sc->sc_c.sc_rh), (0x14), (0x20))) | |||
1748 | SIOP_ISTAT, ISTAT_SIGP)((sc->sc_c.sc_rt)->write_1((sc->sc_c.sc_rh), (0x14), (0x20))); | |||
1749 | /* and wait for IRQ */ | |||
1750 | } | |||
1751 | ||||
1752 | void | |||
1753 | siop_timeout(void *v) | |||
1754 | { | |||
1755 | struct siop_cmd *siop_cmd = v; | |||
1756 | struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc; | |||
1757 | int s; | |||
1758 | ||||
1759 | /* deactivate callout */ | |||
1760 | timeout_del(&siop_cmd->cmd_c.xs->stimeout); | |||
1761 | ||||
1762 | sc_print_addr(siop_cmd->cmd_c.xs->sc_link); | |||
1763 | printf("timeout on SCSI command 0x%x\n", | |||
1764 | siop_cmd->cmd_c.xs->cmd.opcode); | |||
1765 | ||||
1766 | s = splbio()splraise(0x6); | |||
1767 | /* reset the scsi bus */ | |||
1768 | siop_resetbus(&sc->sc_c); | |||
1769 | siop_cmd->cmd_c.flags |= CMDFL_TIMEOUT0x0001; | |||
1770 | siop_handle_reset(sc); | |||
1771 | splx(s)spllower(s); | |||
1772 | } | |||
1773 | ||||
1774 | #ifdef DUMP_SCRIPT | |||
1775 | void | |||
1776 | siop_dump_script(struct siop_softc *sc) | |||
1777 | { | |||
1778 | int i; | |||
1779 | for (i = 0; i < PAGE_SIZE(1 << 12) / 4; i += 2) { | |||
1780 | printf("0x%04x: 0x%08x 0x%08x", i * 4, | |||
1781 | siop_ctoh32(&sc->sc_c, sc->sc_c.sc_script[i])(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_script[i])) ? (__uint32_t )(((__uint32_t)((sc->sc_c.sc_script[i])) & 0xff) << 24 | ((__uint32_t)((sc->sc_c.sc_script[i])) & 0xff00) << 8 | ((__uint32_t)((sc->sc_c.sc_script[i])) & 0xff0000) >> 8 | ((__uint32_t)((sc->sc_c.sc_script[ i])) & 0xff000000) >> 24) : __swap32md((sc->sc_c .sc_script[i]))) : ((__uint32_t)((sc->sc_c.sc_script[i]))) ), | |||
1782 | siop_ctoh32(&sc->sc_c, sc->sc_c.sc_script[i+1])(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_script[i+1])) ? (__uint32_t )(((__uint32_t)((sc->sc_c.sc_script[i+1])) & 0xff) << 24 | ((__uint32_t)((sc->sc_c.sc_script[i+1])) & 0xff00 ) << 8 | ((__uint32_t)((sc->sc_c.sc_script[i+1])) & 0xff0000) >> 8 | ((__uint32_t)((sc->sc_c.sc_script[ i+1])) & 0xff000000) >> 24) : __swap32md((sc->sc_c .sc_script[i+1]))) : ((__uint32_t)((sc->sc_c.sc_script[i+1 ]))))); | |||
1783 | if ((siop_ctoh32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_script[i])) ? (__uint32_t )(((__uint32_t)((sc->sc_c.sc_script[i])) & 0xff) << 24 | ((__uint32_t)((sc->sc_c.sc_script[i])) & 0xff00) << 8 | ((__uint32_t)((sc->sc_c.sc_script[i])) & 0xff0000) >> 8 | ((__uint32_t)((sc->sc_c.sc_script[ i])) & 0xff000000) >> 24) : __swap32md((sc->sc_c .sc_script[i]))) : ((__uint32_t)((sc->sc_c.sc_script[i]))) ) | |||
1784 | sc->sc_c.sc_script[i])(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_script[i])) ? (__uint32_t )(((__uint32_t)((sc->sc_c.sc_script[i])) & 0xff) << 24 | ((__uint32_t)((sc->sc_c.sc_script[i])) & 0xff00) << 8 | ((__uint32_t)((sc->sc_c.sc_script[i])) & 0xff0000) >> 8 | ((__uint32_t)((sc->sc_c.sc_script[ i])) & 0xff000000) >> 24) : __swap32md((sc->sc_c .sc_script[i]))) : ((__uint32_t)((sc->sc_c.sc_script[i]))) ) & 0xe0000000) == 0xc0000000) { | |||
1785 | i++; | |||
1786 | printf(" 0x%08x", siop_ctoh32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_script[i+1])) ? (__uint32_t )(((__uint32_t)((sc->sc_c.sc_script[i+1])) & 0xff) << 24 | ((__uint32_t)((sc->sc_c.sc_script[i+1])) & 0xff00 ) << 8 | ((__uint32_t)((sc->sc_c.sc_script[i+1])) & 0xff0000) >> 8 | ((__uint32_t)((sc->sc_c.sc_script[ i+1])) & 0xff000000) >> 24) : __swap32md((sc->sc_c .sc_script[i+1]))) : ((__uint32_t)((sc->sc_c.sc_script[i+1 ])))) | |||
1787 | sc->sc_c.sc_script[i+1])(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_script[i+1])) ? (__uint32_t )(((__uint32_t)((sc->sc_c.sc_script[i+1])) & 0xff) << 24 | ((__uint32_t)((sc->sc_c.sc_script[i+1])) & 0xff00 ) << 8 | ((__uint32_t)((sc->sc_c.sc_script[i+1])) & 0xff0000) >> 8 | ((__uint32_t)((sc->sc_c.sc_script[ i+1])) & 0xff000000) >> 24) : __swap32md((sc->sc_c .sc_script[i+1]))) : ((__uint32_t)((sc->sc_c.sc_script[i+1 ]))))); | |||
1788 | } | |||
1789 | printf("\n"); | |||
1790 | } | |||
1791 | } | |||
1792 | #endif | |||
1793 | ||||
1794 | void | |||
1795 | siop_morecbd(struct siop_softc *sc) | |||
1796 | { | |||
1797 | int error, off, i, j, s; | |||
1798 | struct siop_cbd *newcbd; | |||
1799 | struct siop_xfer *xfers, *xfer; | |||
1800 | bus_addr_t dsa; | |||
1801 | u_int32_t *scr; | |||
1802 | size_t sense_size = roundup(sizeof(struct scsi_sense_data), 16)((((sizeof(struct scsi_sense_data))+((16)-1))/(16))*(16)); | |||
1803 | ||||
1804 | /* allocate a new list head */ | |||
1805 | newcbd = malloc(sizeof(struct siop_cbd), M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008); | |||
1806 | if (newcbd == NULL((void *)0)) { | |||
1807 | printf("%s: can't allocate memory for command descriptors " | |||
1808 | "head\n", sc->sc_c.sc_dev.dv_xname); | |||
1809 | return; | |||
1810 | } | |||
1811 | ||||
1812 | /* allocate cmd list */ | |||
1813 | newcbd->cmds = mallocarray(SIOP_NCMDPB((1 << 12) / sizeof(struct siop_xfer)), sizeof(struct siop_cmd), | |||
1814 | M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008); | |||
1815 | if (newcbd->cmds == NULL((void *)0)) { | |||
1816 | printf("%s: can't allocate memory for command descriptors\n", | |||
1817 | sc->sc_c.sc_dev.dv_xname); | |||
1818 | goto bad3; | |||
1819 | } | |||
1820 | ||||
1821 | newcbd->xfers = siop_dmamem_alloc(sc, PAGE_SIZE(1 << 12)); | |||
1822 | if (newcbd->xfers == NULL((void *)0)) { | |||
1823 | printf("%s: unable to allocate cbd xfer DMA memory\n", | |||
1824 | sc->sc_c.sc_dev.dv_xname); | |||
1825 | goto bad2; | |||
1826 | } | |||
1827 | xfers = SIOP_DMA_KVA(newcbd->xfers)((void *)(newcbd->xfers)->sdm_kva); | |||
1828 | ||||
1829 | newcbd->sense = siop_dmamem_alloc(sc, sense_size * SIOP_NCMDPB((1 << 12) / sizeof(struct siop_xfer))); | |||
1830 | if (newcbd->sense == NULL((void *)0)) { | |||
1831 | printf("%s: unable to allocate cbd sense DMA memory\n", | |||
1832 | sc->sc_c.sc_dev.dv_xname); | |||
1833 | goto bad1; | |||
1834 | } | |||
1835 | ||||
1836 | for (i = 0; i < SIOP_NCMDPB((1 << 12) / sizeof(struct siop_xfer)); i++) { | |||
1837 | error = bus_dmamap_create(sc->sc_c.sc_dmat, MAXPHYS, SIOP_NSG,(*(sc->sc_c.sc_dmat)->_dmamap_create)((sc->sc_c.sc_dmat ), ((64 * 1024)), (17), ((64 * 1024)), (0), (0x0001 | 0x0002) , (&newcbd->cmds[i].cmd_c.dmamap_data)) | |||
1838 | MAXPHYS, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,(*(sc->sc_c.sc_dmat)->_dmamap_create)((sc->sc_c.sc_dmat ), ((64 * 1024)), (17), ((64 * 1024)), (0), (0x0001 | 0x0002) , (&newcbd->cmds[i].cmd_c.dmamap_data)) | |||
1839 | &newcbd->cmds[i].cmd_c.dmamap_data)(*(sc->sc_c.sc_dmat)->_dmamap_create)((sc->sc_c.sc_dmat ), ((64 * 1024)), (17), ((64 * 1024)), (0), (0x0001 | 0x0002) , (&newcbd->cmds[i].cmd_c.dmamap_data)); | |||
1840 | if (error) { | |||
1841 | printf("%s: unable to create data DMA map for cbd: " | |||
1842 | "error %d\n", | |||
1843 | sc->sc_c.sc_dev.dv_xname, error); | |||
1844 | goto bad0; | |||
1845 | } | |||
1846 | } | |||
1847 | ||||
1848 | /* Use two loops since bailing out above releases allocated memory */ | |||
1849 | off = (sc->sc_c.features & SF_CHIP_BE0x00200000) ? 3 : 0; | |||
1850 | for (i = 0; i < SIOP_NCMDPB((1 << 12) / sizeof(struct siop_xfer)); i++) { | |||
1851 | newcbd->cmds[i].cmd_c.siop_sc = &sc->sc_c; | |||
1852 | newcbd->cmds[i].siop_cbdp = newcbd; | |||
1853 | xfer = &xfers[i]; | |||
1854 | newcbd->cmds[i].cmd_tablescmd_c.siop_tables = (struct siop_common_xfer *)xfer; | |||
1855 | bzero(newcbd->cmds[i].cmd_tables, sizeof(struct siop_xfer))__builtin_bzero((newcbd->cmds[i].cmd_c.siop_tables), (sizeof (struct siop_xfer))); | |||
1856 | dsa = SIOP_DMA_DVA(newcbd->xfers)((newcbd->xfers)->sdm_map->dm_segs[0].ds_addr) + | |||
1857 | i * sizeof(struct siop_xfer); | |||
1858 | newcbd->cmds[i].cmd_c.dsa = dsa; | |||
1859 | newcbd->cmds[i].cmd_c.status = CMDST_FREE0; | |||
1860 | newcbd->cmds[i].cmd_c.sense = (struct scsi_sense_data *)( | |||
1861 | i * sense_size + | |||
1862 | (u_int8_t *)SIOP_DMA_KVA(newcbd->sense)((void *)(newcbd->sense)->sdm_kva)); | |||
1863 | xfer->siop_tables.t_msgout.count= siop_htoc32(&sc->sc_c, 1)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((1)) ? (__uint32_t)(((__uint32_t)((1)) & 0xff) << 24 | ((__uint32_t)((1)) & 0xff00) << 8 | ((__uint32_t)((1)) & 0xff0000) >> 8 | ((__uint32_t )((1)) & 0xff000000) >> 24) : __swap32md((1))) : (( __uint32_t)((1)))); | |||
1864 | xfer->siop_tables.t_msgout.addr = siop_htoc32(&sc->sc_c, dsa)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((dsa)) ? (__uint32_t)(((__uint32_t)((dsa )) & 0xff) << 24 | ((__uint32_t)((dsa)) & 0xff00 ) << 8 | ((__uint32_t)((dsa)) & 0xff0000) >> 8 | ((__uint32_t)((dsa)) & 0xff000000) >> 24) : __swap32md ((dsa))) : ((__uint32_t)((dsa)))); | |||
1865 | xfer->siop_tables.t_msgin.count= siop_htoc32(&sc->sc_c, 1)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((1)) ? (__uint32_t)(((__uint32_t)((1)) & 0xff) << 24 | ((__uint32_t)((1)) & 0xff00) << 8 | ((__uint32_t)((1)) & 0xff0000) >> 8 | ((__uint32_t )((1)) & 0xff000000) >> 24) : __swap32md((1))) : (( __uint32_t)((1)))); | |||
1866 | xfer->siop_tables.t_msgin.addr = siop_htoc32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((dsa + __builtin_offsetof(struct siop_common_xfer , msg_in))) ? (__uint32_t)(((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, msg_in))) & 0xff) << 24 | ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer , msg_in))) & 0xff00) << 8 | ((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, msg_in))) & 0xff0000) >> 8 | ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer , msg_in))) & 0xff000000) >> 24) : __swap32md((dsa + __builtin_offsetof(struct siop_common_xfer, msg_in)))) : ((__uint32_t )((dsa + __builtin_offsetof(struct siop_common_xfer, msg_in)) ))) | |||
1867 | dsa + offsetof(struct siop_common_xfer, msg_in))(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((dsa + __builtin_offsetof(struct siop_common_xfer , msg_in))) ? (__uint32_t)(((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, msg_in))) & 0xff) << 24 | ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer , msg_in))) & 0xff00) << 8 | ((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, msg_in))) & 0xff0000) >> 8 | ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer , msg_in))) & 0xff000000) >> 24) : __swap32md((dsa + __builtin_offsetof(struct siop_common_xfer, msg_in)))) : ((__uint32_t )((dsa + __builtin_offsetof(struct siop_common_xfer, msg_in)) ))); | |||
1868 | xfer->siop_tables.t_extmsgin.count= siop_htoc32(&sc->sc_c, 2)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((2)) ? (__uint32_t)(((__uint32_t)((2)) & 0xff) << 24 | ((__uint32_t)((2)) & 0xff00) << 8 | ((__uint32_t)((2)) & 0xff0000) >> 8 | ((__uint32_t )((2)) & 0xff000000) >> 24) : __swap32md((2))) : (( __uint32_t)((2)))); | |||
1869 | xfer->siop_tables.t_extmsgin.addr = siop_htoc32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((dsa + __builtin_offsetof(struct siop_common_xfer , msg_in) + 1)) ? (__uint32_t)(((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, msg_in) + 1)) & 0xff) << 24 | ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer , msg_in) + 1)) & 0xff00) << 8 | ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer, msg_in) + 1)) & 0xff0000) >> 8 | ((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, msg_in) + 1)) & 0xff000000) >> 24) : __swap32md((dsa + __builtin_offsetof(struct siop_common_xfer , msg_in) + 1))) : ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer, msg_in) + 1)))) | |||
1870 | dsa + offsetof(struct siop_common_xfer, msg_in) + 1)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((dsa + __builtin_offsetof(struct siop_common_xfer , msg_in) + 1)) ? (__uint32_t)(((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, msg_in) + 1)) & 0xff) << 24 | ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer , msg_in) + 1)) & 0xff00) << 8 | ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer, msg_in) + 1)) & 0xff0000) >> 8 | ((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, msg_in) + 1)) & 0xff000000) >> 24) : __swap32md((dsa + __builtin_offsetof(struct siop_common_xfer , msg_in) + 1))) : ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer, msg_in) + 1)))); | |||
1871 | xfer->siop_tables.t_extmsgdata.addr = siop_htoc32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((dsa + __builtin_offsetof(struct siop_common_xfer , msg_in) + 3)) ? (__uint32_t)(((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, msg_in) + 3)) & 0xff) << 24 | ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer , msg_in) + 3)) & 0xff00) << 8 | ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer, msg_in) + 3)) & 0xff0000) >> 8 | ((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, msg_in) + 3)) & 0xff000000) >> 24) : __swap32md((dsa + __builtin_offsetof(struct siop_common_xfer , msg_in) + 3))) : ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer, msg_in) + 3)))) | |||
1872 | dsa + offsetof(struct siop_common_xfer, msg_in) + 3)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((dsa + __builtin_offsetof(struct siop_common_xfer , msg_in) + 3)) ? (__uint32_t)(((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, msg_in) + 3)) & 0xff) << 24 | ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer , msg_in) + 3)) & 0xff00) << 8 | ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer, msg_in) + 3)) & 0xff0000) >> 8 | ((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, msg_in) + 3)) & 0xff000000) >> 24) : __swap32md((dsa + __builtin_offsetof(struct siop_common_xfer , msg_in) + 3))) : ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer, msg_in) + 3)))); | |||
1873 | xfer->siop_tables.t_status.count= siop_htoc32(&sc->sc_c, 1)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((1)) ? (__uint32_t)(((__uint32_t)((1)) & 0xff) << 24 | ((__uint32_t)((1)) & 0xff00) << 8 | ((__uint32_t)((1)) & 0xff0000) >> 8 | ((__uint32_t )((1)) & 0xff000000) >> 24) : __swap32md((1))) : (( __uint32_t)((1)))); | |||
1874 | xfer->siop_tables.t_status.addr = siop_htoc32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((dsa + __builtin_offsetof(struct siop_common_xfer , status) + off)) ? (__uint32_t)(((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, status) + off)) & 0xff) << 24 | ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer , status) + off)) & 0xff00) << 8 | ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer, status) + off) ) & 0xff0000) >> 8 | ((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, status) + off)) & 0xff000000) >> 24) : __swap32md((dsa + __builtin_offsetof(struct siop_common_xfer , status) + off))) : ((__uint32_t)((dsa + __builtin_offsetof( struct siop_common_xfer, status) + off)))) | |||
1875 | dsa + offsetof(struct siop_common_xfer, status) + off)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((dsa + __builtin_offsetof(struct siop_common_xfer , status) + off)) ? (__uint32_t)(((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, status) + off)) & 0xff) << 24 | ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer , status) + off)) & 0xff00) << 8 | ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer, status) + off) ) & 0xff0000) >> 8 | ((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, status) + off)) & 0xff000000) >> 24) : __swap32md((dsa + __builtin_offsetof(struct siop_common_xfer , status) + off))) : ((__uint32_t)((dsa + __builtin_offsetof( struct siop_common_xfer, status) + off)))); | |||
1876 | xfer->siop_tables.cmd.count = siop_htoc32(&sc->sc_c, 0)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((0)) ? (__uint32_t)(((__uint32_t)((0)) & 0xff) << 24 | ((__uint32_t)((0)) & 0xff00) << 8 | ((__uint32_t)((0)) & 0xff0000) >> 8 | ((__uint32_t )((0)) & 0xff000000) >> 24) : __swap32md((0))) : (( __uint32_t)((0)))); | |||
1877 | xfer->siop_tables.cmd.addr = siop_htoc32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((dsa + __builtin_offsetof(struct siop_common_xfer , xscmd))) ? (__uint32_t)(((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, xscmd))) & 0xff) << 24 | ( (__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer , xscmd))) & 0xff00) << 8 | ((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, xscmd))) & 0xff0000) >> 8 | ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer , xscmd))) & 0xff000000) >> 24) : __swap32md((dsa + __builtin_offsetof(struct siop_common_xfer, xscmd)))) : ((__uint32_t )((dsa + __builtin_offsetof(struct siop_common_xfer, xscmd))) )) | |||
1878 | dsa + offsetof(struct siop_common_xfer, xscmd))(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((dsa + __builtin_offsetof(struct siop_common_xfer , xscmd))) ? (__uint32_t)(((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, xscmd))) & 0xff) << 24 | ( (__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer , xscmd))) & 0xff00) << 8 | ((__uint32_t)((dsa + __builtin_offsetof (struct siop_common_xfer, xscmd))) & 0xff0000) >> 8 | ((__uint32_t)((dsa + __builtin_offsetof(struct siop_common_xfer , xscmd))) & 0xff000000) >> 24) : __swap32md((dsa + __builtin_offsetof(struct siop_common_xfer, xscmd)))) : ((__uint32_t )((dsa + __builtin_offsetof(struct siop_common_xfer, xscmd))) )); | |||
1879 | /* The select/reselect script */ | |||
1880 | scr = &xfer->resel[0]; | |||
1881 | for (j = 0; j < sizeof(load_dsa) / sizeof(load_dsa[0]); j++) | |||
1882 | scr[j] = siop_htoc32(&sc->sc_c, load_dsa[j])(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((load_dsa[j])) ? (__uint32_t)(((__uint32_t )((load_dsa[j])) & 0xff) << 24 | ((__uint32_t)((load_dsa [j])) & 0xff00) << 8 | ((__uint32_t)((load_dsa[j])) & 0xff0000) >> 8 | ((__uint32_t)((load_dsa[j])) & 0xff000000) >> 24) : __swap32md((load_dsa[j]))) : ((__uint32_t )((load_dsa[j])))); | |||
1883 | /* | |||
1884 | * 0x78000000 is a 'move data8 to reg'. data8 is the second | |||
1885 | * octet, reg offset is the third. | |||
1886 | */ | |||
1887 | scr[Ent_rdsa00x00000000 / 4] = siop_htoc32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((0x78100000 | ((dsa & 0x000000ff) << 8))) ? (__uint32_t)(((__uint32_t)((0x78100000 | ((dsa & 0x000000ff ) << 8))) & 0xff) << 24 | ((__uint32_t)((0x78100000 | ((dsa & 0x000000ff) << 8))) & 0xff00) << 8 | ((__uint32_t)((0x78100000 | ((dsa & 0x000000ff) << 8))) & 0xff0000) >> 8 | ((__uint32_t)((0x78100000 | ((dsa & 0x000000ff) << 8))) & 0xff000000) >> 24) : __swap32md((0x78100000 | ((dsa & 0x000000ff) << 8)))) : ((__uint32_t)((0x78100000 | ((dsa & 0x000000ff) << 8))))) | |||
1888 | 0x78100000 | ((dsa & 0x000000ff) << 8))(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((0x78100000 | ((dsa & 0x000000ff) << 8))) ? (__uint32_t)(((__uint32_t)((0x78100000 | ((dsa & 0x000000ff ) << 8))) & 0xff) << 24 | ((__uint32_t)((0x78100000 | ((dsa & 0x000000ff) << 8))) & 0xff00) << 8 | ((__uint32_t)((0x78100000 | ((dsa & 0x000000ff) << 8))) & 0xff0000) >> 8 | ((__uint32_t)((0x78100000 | ((dsa & 0x000000ff) << 8))) & 0xff000000) >> 24) : __swap32md((0x78100000 | ((dsa & 0x000000ff) << 8)))) : ((__uint32_t)((0x78100000 | ((dsa & 0x000000ff) << 8))))); | |||
1889 | scr[Ent_rdsa10x00000008 / 4] = siop_htoc32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((0x78110000 | ( dsa & 0x0000ff00 ) )) ? (__uint32_t)(((__uint32_t)((0x78110000 | ( dsa & 0x0000ff00 ))) & 0xff) << 24 | ((__uint32_t)((0x78110000 | ( dsa & 0x0000ff00 ))) & 0xff00) << 8 | ((__uint32_t )((0x78110000 | ( dsa & 0x0000ff00 ))) & 0xff0000) >> 8 | ((__uint32_t)((0x78110000 | ( dsa & 0x0000ff00 ))) & 0xff000000) >> 24) : __swap32md((0x78110000 | ( dsa & 0x0000ff00 )))) : ((__uint32_t)((0x78110000 | ( dsa & 0x0000ff00 ))))) | |||
1890 | 0x78110000 | ( dsa & 0x0000ff00 ))(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((0x78110000 | ( dsa & 0x0000ff00 ) )) ? (__uint32_t)(((__uint32_t)((0x78110000 | ( dsa & 0x0000ff00 ))) & 0xff) << 24 | ((__uint32_t)((0x78110000 | ( dsa & 0x0000ff00 ))) & 0xff00) << 8 | ((__uint32_t )((0x78110000 | ( dsa & 0x0000ff00 ))) & 0xff0000) >> 8 | ((__uint32_t)((0x78110000 | ( dsa & 0x0000ff00 ))) & 0xff000000) >> 24) : __swap32md((0x78110000 | ( dsa & 0x0000ff00 )))) : ((__uint32_t)((0x78110000 | ( dsa & 0x0000ff00 ))))); | |||
1891 | scr[Ent_rdsa20x00000010 / 4] = siop_htoc32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((0x78120000 | ((dsa & 0x00ff0000) >> 8))) ? (__uint32_t)(((__uint32_t)((0x78120000 | ((dsa & 0x00ff0000 ) >> 8))) & 0xff) << 24 | ((__uint32_t)((0x78120000 | ((dsa & 0x00ff0000) >> 8))) & 0xff00) << 8 | ((__uint32_t)((0x78120000 | ((dsa & 0x00ff0000) >> 8))) & 0xff0000) >> 8 | ((__uint32_t)((0x78120000 | ((dsa & 0x00ff0000) >> 8))) & 0xff000000) >> 24) : __swap32md((0x78120000 | ((dsa & 0x00ff0000) >> 8)))) : ((__uint32_t)((0x78120000 | ((dsa & 0x00ff0000) >> 8))))) | |||
1892 | 0x78120000 | ((dsa & 0x00ff0000) >> 8))(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((0x78120000 | ((dsa & 0x00ff0000) >> 8))) ? (__uint32_t)(((__uint32_t)((0x78120000 | ((dsa & 0x00ff0000 ) >> 8))) & 0xff) << 24 | ((__uint32_t)((0x78120000 | ((dsa & 0x00ff0000) >> 8))) & 0xff00) << 8 | ((__uint32_t)((0x78120000 | ((dsa & 0x00ff0000) >> 8))) & 0xff0000) >> 8 | ((__uint32_t)((0x78120000 | ((dsa & 0x00ff0000) >> 8))) & 0xff000000) >> 24) : __swap32md((0x78120000 | ((dsa & 0x00ff0000) >> 8)))) : ((__uint32_t)((0x78120000 | ((dsa & 0x00ff0000) >> 8))))); | |||
1893 | scr[Ent_rdsa30x00000018 / 4] = siop_htoc32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((0x78130000 | ((dsa & 0xff000000) >> 16))) ? (__uint32_t)(((__uint32_t)((0x78130000 | ((dsa & 0xff000000) >> 16))) & 0xff) << 24 | ((__uint32_t )((0x78130000 | ((dsa & 0xff000000) >> 16))) & 0xff00 ) << 8 | ((__uint32_t)((0x78130000 | ((dsa & 0xff000000 ) >> 16))) & 0xff0000) >> 8 | ((__uint32_t)(( 0x78130000 | ((dsa & 0xff000000) >> 16))) & 0xff000000 ) >> 24) : __swap32md((0x78130000 | ((dsa & 0xff000000 ) >> 16)))) : ((__uint32_t)((0x78130000 | ((dsa & 0xff000000 ) >> 16))))) | |||
1894 | 0x78130000 | ((dsa & 0xff000000) >> 16))(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((0x78130000 | ((dsa & 0xff000000) >> 16))) ? (__uint32_t)(((__uint32_t)((0x78130000 | ((dsa & 0xff000000) >> 16))) & 0xff) << 24 | ((__uint32_t )((0x78130000 | ((dsa & 0xff000000) >> 16))) & 0xff00 ) << 8 | ((__uint32_t)((0x78130000 | ((dsa & 0xff000000 ) >> 16))) & 0xff0000) >> 8 | ((__uint32_t)(( 0x78130000 | ((dsa & 0xff000000) >> 16))) & 0xff000000 ) >> 24) : __swap32md((0x78130000 | ((dsa & 0xff000000 ) >> 16)))) : ((__uint32_t)((0x78130000 | ((dsa & 0xff000000 ) >> 16))))); | |||
1895 | scr[E_ldsa_abs_reselected_Used[0]] = siop_htoc32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_scriptaddr + 0x00000000 )) ? (__uint32_t)(((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000000 )) & 0xff) << 24 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000000)) & 0xff00) << 8 | ((__uint32_t)((sc-> sc_c.sc_scriptaddr + 0x00000000)) & 0xff0000) >> 8 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000000)) & 0xff000000) >> 24) : __swap32md((sc->sc_c.sc_scriptaddr + 0x00000000))) : ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000000)))) | |||
1896 | sc->sc_c.sc_scriptaddr + Ent_reselected)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_scriptaddr + 0x00000000 )) ? (__uint32_t)(((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000000 )) & 0xff) << 24 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000000)) & 0xff00) << 8 | ((__uint32_t)((sc-> sc_c.sc_scriptaddr + 0x00000000)) & 0xff0000) >> 8 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000000)) & 0xff000000) >> 24) : __swap32md((sc->sc_c.sc_scriptaddr + 0x00000000))) : ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000000)))); | |||
1897 | scr[E_ldsa_abs_reselect_Used[0]] = siop_htoc32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_scriptaddr + 0x000001e0 )) ? (__uint32_t)(((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000001e0 )) & 0xff) << 24 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000001e0)) & 0xff00) << 8 | ((__uint32_t)((sc-> sc_c.sc_scriptaddr + 0x000001e0)) & 0xff0000) >> 8 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000001e0)) & 0xff000000) >> 24) : __swap32md((sc->sc_c.sc_scriptaddr + 0x000001e0))) : ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000001e0)))) | |||
1898 | sc->sc_c.sc_scriptaddr + Ent_reselect)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_scriptaddr + 0x000001e0 )) ? (__uint32_t)(((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000001e0 )) & 0xff) << 24 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000001e0)) & 0xff00) << 8 | ((__uint32_t)((sc-> sc_c.sc_scriptaddr + 0x000001e0)) & 0xff0000) >> 8 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000001e0)) & 0xff000000) >> 24) : __swap32md((sc->sc_c.sc_scriptaddr + 0x000001e0))) : ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000001e0)))); | |||
1899 | scr[E_ldsa_abs_selected_Used[0]] = siop_htoc32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_scriptaddr + 0x00000388 )) ? (__uint32_t)(((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000388 )) & 0xff) << 24 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000388)) & 0xff00) << 8 | ((__uint32_t)((sc-> sc_c.sc_scriptaddr + 0x00000388)) & 0xff0000) >> 8 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000388)) & 0xff000000) >> 24) : __swap32md((sc->sc_c.sc_scriptaddr + 0x00000388))) : ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000388)))) | |||
1900 | sc->sc_c.sc_scriptaddr + Ent_selected)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_scriptaddr + 0x00000388 )) ? (__uint32_t)(((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000388 )) & 0xff) << 24 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000388)) & 0xff00) << 8 | ((__uint32_t)((sc-> sc_c.sc_scriptaddr + 0x00000388)) & 0xff0000) >> 8 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000388)) & 0xff000000) >> 24) : __swap32md((sc->sc_c.sc_scriptaddr + 0x00000388))) : ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x00000388)))); | |||
1901 | scr[E_ldsa_abs_data_Used[0]] = siop_htoc32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((dsa + sizeof(struct siop_common_xfer) + 0x0000005c)) ? (__uint32_t)(((__uint32_t)((dsa + sizeof(struct siop_common_xfer) + 0x0000005c)) & 0xff) << 24 | ( (__uint32_t)((dsa + sizeof(struct siop_common_xfer) + 0x0000005c )) & 0xff00) << 8 | ((__uint32_t)((dsa + sizeof(struct siop_common_xfer) + 0x0000005c)) & 0xff0000) >> 8 | ((__uint32_t)((dsa + sizeof(struct siop_common_xfer) + 0x0000005c )) & 0xff000000) >> 24) : __swap32md((dsa + sizeof( struct siop_common_xfer) + 0x0000005c))) : ((__uint32_t)((dsa + sizeof(struct siop_common_xfer) + 0x0000005c)))) | |||
1902 | dsa + sizeof(struct siop_common_xfer) + Ent_ldsa_data)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((dsa + sizeof(struct siop_common_xfer) + 0x0000005c)) ? (__uint32_t)(((__uint32_t)((dsa + sizeof(struct siop_common_xfer) + 0x0000005c)) & 0xff) << 24 | ( (__uint32_t)((dsa + sizeof(struct siop_common_xfer) + 0x0000005c )) & 0xff00) << 8 | ((__uint32_t)((dsa + sizeof(struct siop_common_xfer) + 0x0000005c)) & 0xff0000) >> 8 | ((__uint32_t)((dsa + sizeof(struct siop_common_xfer) + 0x0000005c )) & 0xff000000) >> 24) : __swap32md((dsa + sizeof( struct siop_common_xfer) + 0x0000005c))) : ((__uint32_t)((dsa + sizeof(struct siop_common_xfer) + 0x0000005c)))); | |||
1903 | /* JUMP foo, IF FALSE - used by MOVE MEMORY to clear the slot */ | |||
1904 | scr[Ent_ldsa_data0x0000005c / 4] = siop_htoc32(&sc->sc_c, 0x80000000)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((0x80000000)) ? (__uint32_t)(((__uint32_t )((0x80000000)) & 0xff) << 24 | ((__uint32_t)((0x80000000 )) & 0xff00) << 8 | ((__uint32_t)((0x80000000)) & 0xff0000) >> 8 | ((__uint32_t)((0x80000000)) & 0xff000000 ) >> 24) : __swap32md((0x80000000))) : ((__uint32_t)((0x80000000 )))); | |||
1905 | s = splbio()splraise(0x6); | |||
1906 | TAILQ_INSERT_TAIL(&sc->free_list, &newcbd->cmds[i], next)do { (&newcbd->cmds[i])->next.tqe_next = ((void *)0 ); (&newcbd->cmds[i])->next.tqe_prev = (&sc-> free_list)->tqh_last; *(&sc->free_list)->tqh_last = (&newcbd->cmds[i]); (&sc->free_list)->tqh_last = &(&newcbd->cmds[i])->next.tqe_next; } while ( 0); | |||
1907 | splx(s)spllower(s); | |||
1908 | #ifdef SIOP_DEBUG | |||
1909 | printf("tables[%d]: in=0x%x out=0x%x status=0x%x\n", | |||
1910 | i, | |||
1911 | siop_ctoh32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((newcbd->cmds[i].cmd_c.siop_tables-> t_msgin.addr)) ? (__uint32_t)(((__uint32_t)((newcbd->cmds[ i].cmd_c.siop_tables->t_msgin.addr)) & 0xff) << 24 | ((__uint32_t)((newcbd->cmds[i].cmd_c.siop_tables->t_msgin .addr)) & 0xff00) << 8 | ((__uint32_t)((newcbd-> cmds[i].cmd_c.siop_tables->t_msgin.addr)) & 0xff0000) >> 8 | ((__uint32_t)((newcbd->cmds[i].cmd_c.siop_tables-> t_msgin.addr)) & 0xff000000) >> 24) : __swap32md((newcbd ->cmds[i].cmd_c.siop_tables->t_msgin.addr))) : ((__uint32_t )((newcbd->cmds[i].cmd_c.siop_tables->t_msgin.addr)))) | |||
1912 | newcbd->cmds[i].cmd_tables->t_msgin.addr)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((newcbd->cmds[i].cmd_c.siop_tables-> t_msgin.addr)) ? (__uint32_t)(((__uint32_t)((newcbd->cmds[ i].cmd_c.siop_tables->t_msgin.addr)) & 0xff) << 24 | ((__uint32_t)((newcbd->cmds[i].cmd_c.siop_tables->t_msgin .addr)) & 0xff00) << 8 | ((__uint32_t)((newcbd-> cmds[i].cmd_c.siop_tables->t_msgin.addr)) & 0xff0000) >> 8 | ((__uint32_t)((newcbd->cmds[i].cmd_c.siop_tables-> t_msgin.addr)) & 0xff000000) >> 24) : __swap32md((newcbd ->cmds[i].cmd_c.siop_tables->t_msgin.addr))) : ((__uint32_t )((newcbd->cmds[i].cmd_c.siop_tables->t_msgin.addr)))), | |||
1913 | siop_ctoh32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((newcbd->cmds[i].cmd_c.siop_tables-> t_msgout.addr)) ? (__uint32_t)(((__uint32_t)((newcbd->cmds [i].cmd_c.siop_tables->t_msgout.addr)) & 0xff) << 24 | ((__uint32_t)((newcbd->cmds[i].cmd_c.siop_tables-> t_msgout.addr)) & 0xff00) << 8 | ((__uint32_t)((newcbd ->cmds[i].cmd_c.siop_tables->t_msgout.addr)) & 0xff0000 ) >> 8 | ((__uint32_t)((newcbd->cmds[i].cmd_c.siop_tables ->t_msgout.addr)) & 0xff000000) >> 24) : __swap32md ((newcbd->cmds[i].cmd_c.siop_tables->t_msgout.addr))) : ((__uint32_t)((newcbd->cmds[i].cmd_c.siop_tables->t_msgout .addr)))) | |||
1914 | newcbd->cmds[i].cmd_tables->t_msgout.addr)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((newcbd->cmds[i].cmd_c.siop_tables-> t_msgout.addr)) ? (__uint32_t)(((__uint32_t)((newcbd->cmds [i].cmd_c.siop_tables->t_msgout.addr)) & 0xff) << 24 | ((__uint32_t)((newcbd->cmds[i].cmd_c.siop_tables-> t_msgout.addr)) & 0xff00) << 8 | ((__uint32_t)((newcbd ->cmds[i].cmd_c.siop_tables->t_msgout.addr)) & 0xff0000 ) >> 8 | ((__uint32_t)((newcbd->cmds[i].cmd_c.siop_tables ->t_msgout.addr)) & 0xff000000) >> 24) : __swap32md ((newcbd->cmds[i].cmd_c.siop_tables->t_msgout.addr))) : ((__uint32_t)((newcbd->cmds[i].cmd_c.siop_tables->t_msgout .addr)))), | |||
1915 | siop_ctoh32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((newcbd->cmds[i].cmd_c.siop_tables-> t_status.addr)) ? (__uint32_t)(((__uint32_t)((newcbd->cmds [i].cmd_c.siop_tables->t_status.addr)) & 0xff) << 24 | ((__uint32_t)((newcbd->cmds[i].cmd_c.siop_tables-> t_status.addr)) & 0xff00) << 8 | ((__uint32_t)((newcbd ->cmds[i].cmd_c.siop_tables->t_status.addr)) & 0xff0000 ) >> 8 | ((__uint32_t)((newcbd->cmds[i].cmd_c.siop_tables ->t_status.addr)) & 0xff000000) >> 24) : __swap32md ((newcbd->cmds[i].cmd_c.siop_tables->t_status.addr))) : ((__uint32_t)((newcbd->cmds[i].cmd_c.siop_tables->t_status .addr)))) | |||
1916 | newcbd->cmds[i].cmd_tables->t_status.addr)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((newcbd->cmds[i].cmd_c.siop_tables-> t_status.addr)) ? (__uint32_t)(((__uint32_t)((newcbd->cmds [i].cmd_c.siop_tables->t_status.addr)) & 0xff) << 24 | ((__uint32_t)((newcbd->cmds[i].cmd_c.siop_tables-> t_status.addr)) & 0xff00) << 8 | ((__uint32_t)((newcbd ->cmds[i].cmd_c.siop_tables->t_status.addr)) & 0xff0000 ) >> 8 | ((__uint32_t)((newcbd->cmds[i].cmd_c.siop_tables ->t_status.addr)) & 0xff000000) >> 24) : __swap32md ((newcbd->cmds[i].cmd_c.siop_tables->t_status.addr))) : ((__uint32_t)((newcbd->cmds[i].cmd_c.siop_tables->t_status .addr))))); | |||
1917 | #endif | |||
1918 | } | |||
1919 | s = splbio()splraise(0x6); | |||
1920 | TAILQ_INSERT_TAIL(&sc->cmds, newcbd, next)do { (newcbd)->next.tqe_next = ((void *)0); (newcbd)->next .tqe_prev = (&sc->cmds)->tqh_last; *(&sc->cmds )->tqh_last = (newcbd); (&sc->cmds)->tqh_last = & (newcbd)->next.tqe_next; } while (0); | |||
1921 | splx(s)spllower(s); | |||
1922 | return; | |||
1923 | bad0: | |||
1924 | while (--i >= 0) { | |||
1925 | bus_dmamap_destroy(sc->sc_c.sc_dmat,(*(sc->sc_c.sc_dmat)->_dmamap_destroy)((sc->sc_c.sc_dmat ), (newcbd->cmds[i].cmd_c.dmamap_data)) | |||
1926 | newcbd->cmds[i].cmd_c.dmamap_data)(*(sc->sc_c.sc_dmat)->_dmamap_destroy)((sc->sc_c.sc_dmat ), (newcbd->cmds[i].cmd_c.dmamap_data)); | |||
1927 | } | |||
1928 | siop_dmamem_free(sc, newcbd->sense); | |||
1929 | bad1: | |||
1930 | siop_dmamem_free(sc, newcbd->xfers); | |||
1931 | bad2: | |||
1932 | free(newcbd->cmds, M_DEVBUF2, SIOP_NCMDPB((1 << 12) / sizeof(struct siop_xfer)) * sizeof(struct siop_cmd)); | |||
1933 | bad3: | |||
1934 | free(newcbd, M_DEVBUF2, sizeof *newcbd); | |||
1935 | } | |||
1936 | ||||
1937 | struct siop_lunsw * | |||
1938 | siop_get_lunsw(struct siop_softc *sc) | |||
1939 | { | |||
1940 | struct siop_lunsw *lunsw; | |||
1941 | int i; | |||
1942 | ||||
1943 | if (sc->script_free_lo + (sizeof(lun_switch) / sizeof(lun_switch[0])) >= | |||
1944 | sc->script_free_hi) | |||
1945 | return NULL((void *)0); | |||
1946 | lunsw = TAILQ_FIRST(&sc->lunsw_list)((&sc->lunsw_list)->tqh_first); | |||
1947 | if (lunsw != NULL((void *)0)) { | |||
1948 | #ifdef SIOP_DEBUG | |||
1949 | printf("siop_get_lunsw got lunsw at offset %d\n", | |||
1950 | lunsw->lunsw_off); | |||
1951 | #endif | |||
1952 | TAILQ_REMOVE(&sc->lunsw_list, lunsw, next)do { if (((lunsw)->next.tqe_next) != ((void *)0)) (lunsw)-> next.tqe_next->next.tqe_prev = (lunsw)->next.tqe_prev; else (&sc->lunsw_list)->tqh_last = (lunsw)->next.tqe_prev ; *(lunsw)->next.tqe_prev = (lunsw)->next.tqe_next; ((lunsw )->next.tqe_prev) = ((void *)-1); ((lunsw)->next.tqe_next ) = ((void *)-1); } while (0); | |||
1953 | return lunsw; | |||
1954 | } | |||
1955 | lunsw = malloc(sizeof(struct siop_lunsw), M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008); | |||
1956 | if (lunsw == NULL((void *)0)) | |||
1957 | return NULL((void *)0); | |||
1958 | #ifdef SIOP_DEBUG | |||
1959 | printf("allocating lunsw at offset %d\n", sc->script_free_lo); | |||
1960 | #endif | |||
1961 | if (sc->sc_c.features & SF_CHIP_RAM0x00004000) { | |||
1962 | bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (sc->script_free_lo * 4), (lun_switch), (sizeof(lun_switch ) / sizeof(lun_switch[0])))) | |||
1963 | sc->script_free_lo * 4, lun_switch,((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (sc->script_free_lo * 4), (lun_switch), (sizeof(lun_switch ) / sizeof(lun_switch[0])))) | |||
1964 | sizeof(lun_switch) / sizeof(lun_switch[0]))((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (sc->script_free_lo * 4), (lun_switch), (sizeof(lun_switch ) / sizeof(lun_switch[0])))); | |||
1965 | bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,((sc->sc_c.sc_ramt)->write_4((sc->sc_c.sc_ramh), ((sc ->script_free_lo + E_abs_lunsw_return_Used[0]) * 4), (sc-> sc_c.sc_scriptaddr + 0x000002b8))) | |||
1966 | (sc->script_free_lo + E_abs_lunsw_return_Used[0]) * 4,((sc->sc_c.sc_ramt)->write_4((sc->sc_c.sc_ramh), ((sc ->script_free_lo + E_abs_lunsw_return_Used[0]) * 4), (sc-> sc_c.sc_scriptaddr + 0x000002b8))) | |||
1967 | sc->sc_c.sc_scriptaddr + Ent_lunsw_return)((sc->sc_c.sc_ramt)->write_4((sc->sc_c.sc_ramh), ((sc ->script_free_lo + E_abs_lunsw_return_Used[0]) * 4), (sc-> sc_c.sc_scriptaddr + 0x000002b8))); | |||
1968 | } else { | |||
1969 | for (i = 0; i < sizeof(lun_switch) / sizeof(lun_switch[0]); | |||
1970 | i++) | |||
1971 | sc->sc_c.sc_script[sc->script_free_lo + i] = | |||
1972 | siop_htoc32(&sc->sc_c, lun_switch[i])(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((lun_switch[i])) ? (__uint32_t)(((__uint32_t )((lun_switch[i])) & 0xff) << 24 | ((__uint32_t)((lun_switch [i])) & 0xff00) << 8 | ((__uint32_t)((lun_switch[i] )) & 0xff0000) >> 8 | ((__uint32_t)((lun_switch[i]) ) & 0xff000000) >> 24) : __swap32md((lun_switch[i]) )) : ((__uint32_t)((lun_switch[i])))); | |||
1973 | sc->sc_c.sc_script[ | |||
1974 | sc->script_free_lo + E_abs_lunsw_return_Used[0]] = | |||
1975 | siop_htoc32(&sc->sc_c,(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_scriptaddr + 0x000002b8 )) ? (__uint32_t)(((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000002b8 )) & 0xff) << 24 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000002b8)) & 0xff00) << 8 | ((__uint32_t)((sc-> sc_c.sc_scriptaddr + 0x000002b8)) & 0xff0000) >> 8 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000002b8)) & 0xff000000) >> 24) : __swap32md((sc->sc_c.sc_scriptaddr + 0x000002b8))) : ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000002b8)))) | |||
1976 | sc->sc_c.sc_scriptaddr + Ent_lunsw_return)(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((sc->sc_c.sc_scriptaddr + 0x000002b8 )) ? (__uint32_t)(((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000002b8 )) & 0xff) << 24 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000002b8)) & 0xff00) << 8 | ((__uint32_t)((sc-> sc_c.sc_scriptaddr + 0x000002b8)) & 0xff0000) >> 8 | ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000002b8)) & 0xff000000) >> 24) : __swap32md((sc->sc_c.sc_scriptaddr + 0x000002b8))) : ((__uint32_t)((sc->sc_c.sc_scriptaddr + 0x000002b8)))); | |||
1977 | } | |||
1978 | lunsw->lunsw_off = sc->script_free_lo; | |||
1979 | lunsw->lunsw_size = sizeof(lun_switch) / sizeof(lun_switch[0]); | |||
1980 | sc->script_free_lo += lunsw->lunsw_size; | |||
1981 | siop_script_sync(sc, BUS_DMASYNC_PREREAD0x01 | BUS_DMASYNC_PREWRITE0x04); | |||
1982 | return lunsw; | |||
1983 | } | |||
1984 | ||||
1985 | void | |||
1986 | siop_add_reselsw(struct siop_softc *sc, int target) | |||
1987 | { | |||
1988 | int i,j; | |||
1989 | struct siop_target *siop_target; | |||
1990 | struct siop_lun *siop_lun; | |||
1991 | ||||
1992 | siop_target = (struct siop_target *)sc->sc_c.targets[target]; | |||
1993 | /* | |||
1994 | * add an entry to resel switch | |||
1995 | */ | |||
1996 | siop_script_sync(sc, BUS_DMASYNC_POSTWRITE0x08); | |||
1997 | for (i = 0; i < 15; i++) { | |||
1998 | siop_target->reseloff = Ent_resel_targ00x00000238 / 4 + i * 2; | |||
1999 | if ((siop_script_read(sc, siop_target->reseloff) & 0xff) | |||
2000 | == 0xff) { /* it's free */ | |||
2001 | #ifdef SIOP_DEBUG | |||
2002 | printf("siop: target %d slot %d offset %d\n", | |||
2003 | target, i, siop_target->reseloff); | |||
2004 | #endif | |||
2005 | /* JUMP abs_foo, IF target | 0x80; */ | |||
2006 | siop_script_write(sc, siop_target->reseloff, | |||
2007 | 0x800c0080 | target); | |||
2008 | siop_script_write(sc, siop_target->reseloff + 1, | |||
2009 | sc->sc_c.sc_scriptaddr + | |||
2010 | siop_target->lunsw->lunsw_off * 4 + | |||
2011 | Ent_lun_switch_entry0x00000018); | |||
2012 | break; | |||
2013 | } | |||
2014 | } | |||
2015 | if (i == 15) /* no free slot, shouldn't happen */ | |||
2016 | panic("siop: resel switch full"); | |||
2017 | ||||
2018 | sc->sc_ntargets++; | |||
2019 | for (i = 0; i < 8; i++) { | |||
2020 | siop_lun = siop_target->siop_lun[i]; | |||
2021 | if (siop_lun == NULL((void *)0)) | |||
2022 | continue; | |||
2023 | if (siop_lun->reseloff > 0) { | |||
2024 | siop_lun->reseloff = 0; | |||
2025 | for (j = 0; j < SIOP_NTAG16; j++) | |||
2026 | siop_lun->siop_tag[j].reseloff = 0; | |||
2027 | siop_add_dev(sc, target, i); | |||
2028 | } | |||
2029 | } | |||
2030 | siop_update_scntl3(sc, sc->sc_c.targets[target]); | |||
2031 | siop_script_sync(sc, BUS_DMASYNC_PREWRITE0x04); | |||
2032 | } | |||
2033 | ||||
2034 | void | |||
2035 | siop_update_scntl3(struct siop_softc *sc, | |||
2036 | struct siop_common_target *_siop_target) | |||
2037 | { | |||
2038 | struct siop_target *siop_target = (struct siop_target *)_siop_target; | |||
2039 | /* MOVE target->id >> 24 TO SCNTL3 */ | |||
2040 | siop_script_write(sc, | |||
2041 | siop_target->lunsw->lunsw_off + (Ent_restore_scntl30x00000000 / 4), | |||
2042 | 0x78030000 | ((siop_target->target_c.id >> 16) & 0x0000ff00)); | |||
2043 | /* MOVE target->id >> 8 TO SXFER */ | |||
2044 | siop_script_write(sc, | |||
2045 | siop_target->lunsw->lunsw_off + (Ent_restore_scntl30x00000000 / 4) + 2, | |||
2046 | 0x78050000 | (siop_target->target_c.id & 0x0000ff00)); | |||
2047 | siop_script_sync(sc, BUS_DMASYNC_PREWRITE0x04); | |||
2048 | } | |||
2049 | ||||
2050 | void | |||
2051 | siop_add_dev(struct siop_softc *sc, int target, int lun) | |||
2052 | { | |||
2053 | struct siop_lunsw *lunsw; | |||
2054 | struct siop_target *siop_target = | |||
2055 | (struct siop_target *)sc->sc_c.targets[target]; | |||
2056 | struct siop_lun *siop_lun = siop_target->siop_lun[lun]; | |||
2057 | int i, ntargets, buswidth; | |||
2058 | ||||
2059 | if (siop_lun->reseloff > 0) | |||
2060 | return; | |||
2061 | lunsw = siop_target->lunsw; | |||
2062 | if ((lunsw->lunsw_off + lunsw->lunsw_size) < sc->script_free_lo) { | |||
2063 | /* | |||
2064 | * can't extend this slot. Probably not worth trying to deal | |||
2065 | * with this case | |||
2066 | */ | |||
2067 | #ifdef SIOP_DEBUG | |||
2068 | printf("%s:%d:%d: can't allocate a lun sw slot\n", | |||
2069 | sc->sc_c.sc_dev.dv_xname, target, lun); | |||
2070 | #endif | |||
2071 | return; | |||
2072 | } | |||
2073 | /* count how many free targets we still have to probe */ | |||
2074 | buswidth = (sc->sc_c.features & SF_BUS_WIDE0x00000001) ? 16 : 8; | |||
2075 | ntargets = (buswidth - 1) - 1 - sc->sc_ntargets; | |||
2076 | ||||
2077 | /* | |||
2078 | * we need 8 bytes for the lun sw additional entry, and | |||
2079 | * eventually sizeof(tag_switch) for the tag switch entry. | |||
2080 | * Keep enough free space for the free targets that could be | |||
2081 | * probed later. | |||
2082 | */ | |||
2083 | if (sc->script_free_lo + 2 + | |||
2084 | (ntargets * sizeof(lun_switch) / sizeof(lun_switch[0])) >= | |||
2085 | ((siop_target->target_c.flags & TARF_TAG0x04) ? | |||
2086 | sc->script_free_hi - (sizeof(tag_switch) / sizeof(tag_switch[0])) : | |||
2087 | sc->script_free_hi)) { | |||
2088 | /* | |||
2089 | * not enough space, probably not worth dealing with it. | |||
2090 | * We can hold 13 tagged-queuing capable devices in the 4k RAM. | |||
2091 | */ | |||
2092 | #ifdef SIOP_DEBUG | |||
2093 | printf("%s:%d:%d: not enough memory for a lun sw slot\n", | |||
2094 | sc->sc_c.sc_dev.dv_xname, target, lun); | |||
2095 | #endif | |||
2096 | return; | |||
2097 | } | |||
2098 | #ifdef SIOP_DEBUG | |||
2099 | printf("%s:%d:%d: allocate lun sw entry\n", | |||
2100 | sc->sc_c.sc_dev.dv_xname, target, lun); | |||
2101 | #endif | |||
2102 | /* INT int_resellun */ | |||
2103 | siop_script_write(sc, sc->script_free_lo, 0x98080000); | |||
2104 | siop_script_write(sc, sc->script_free_lo + 1, A_int_resellun0x0000ff81); | |||
2105 | /* Now the slot entry: JUMP abs_foo, IF lun */ | |||
2106 | siop_script_write(sc, sc->script_free_lo - 2, | |||
2107 | 0x800c0000 | lun); | |||
2108 | siop_script_write(sc, sc->script_free_lo - 1, 0); | |||
2109 | siop_lun->reseloff = sc->script_free_lo - 2; | |||
2110 | lunsw->lunsw_size += 2; | |||
2111 | sc->script_free_lo += 2; | |||
2112 | if (siop_target->target_c.flags & TARF_TAG0x04) { | |||
2113 | /* we need a tag switch */ | |||
2114 | sc->script_free_hi -= | |||
2115 | sizeof(tag_switch) / sizeof(tag_switch[0]); | |||
2116 | if (sc->sc_c.features & SF_CHIP_RAM0x00004000) { | |||
2117 | bus_space_write_region_4(sc->sc_c.sc_ramt,((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (sc->script_free_hi * 4), (tag_switch), (sizeof(tag_switch ) / sizeof(tag_switch[0])))) | |||
2118 | sc->sc_c.sc_ramh,((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (sc->script_free_hi * 4), (tag_switch), (sizeof(tag_switch ) / sizeof(tag_switch[0])))) | |||
2119 | sc->script_free_hi * 4, tag_switch,((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (sc->script_free_hi * 4), (tag_switch), (sizeof(tag_switch ) / sizeof(tag_switch[0])))) | |||
2120 | sizeof(tag_switch) / sizeof(tag_switch[0]))((sc->sc_c.sc_ramt)->write_region_4((sc->sc_c.sc_ramh ), (sc->script_free_hi * 4), (tag_switch), (sizeof(tag_switch ) / sizeof(tag_switch[0])))); | |||
2121 | } else { | |||
2122 | for(i = 0; | |||
2123 | i < sizeof(tag_switch) / sizeof(tag_switch[0]); | |||
2124 | i++) { | |||
2125 | sc->sc_c.sc_script[sc->script_free_hi + i] = | |||
2126 | siop_htoc32(&sc->sc_c, tag_switch[i])(((&sc->sc_c)->features & 0x00200000) ? (__uint32_t )(__builtin_constant_p((tag_switch[i])) ? (__uint32_t)(((__uint32_t )((tag_switch[i])) & 0xff) << 24 | ((__uint32_t)((tag_switch [i])) & 0xff00) << 8 | ((__uint32_t)((tag_switch[i] )) & 0xff0000) >> 8 | ((__uint32_t)((tag_switch[i]) ) & 0xff000000) >> 24) : __swap32md((tag_switch[i]) )) : ((__uint32_t)((tag_switch[i])))); | |||
2127 | } | |||
2128 | } | |||
2129 | siop_script_write(sc, | |||
2130 | siop_lun->reseloff + 1, | |||
2131 | sc->sc_c.sc_scriptaddr + sc->script_free_hi * 4 + | |||
2132 | Ent_tag_switch_entry0x00000000); | |||
2133 | ||||
2134 | for (i = 0; i < SIOP_NTAG16; i++) { | |||
2135 | siop_lun->siop_tag[i].reseloff = | |||
2136 | sc->script_free_hi + (Ent_resel_tag00x00000008 / 4) + i * 2; | |||
2137 | } | |||
2138 | } else { | |||
2139 | /* non-tag case; just work with the lun switch */ | |||
2140 | siop_lun->siop_tag[0].reseloff = | |||
2141 | siop_target->siop_lun[lun]->reseloff; | |||
2142 | } | |||
2143 | siop_script_sync(sc, BUS_DMASYNC_PREWRITE0x04); | |||
2144 | } | |||
2145 | ||||
2146 | void | |||
2147 | siop_scsifree(struct scsi_link *link) | |||
2148 | { | |||
2149 | struct siop_softc *sc = link->bus->sb_adapter_softc; | |||
2150 | int target = link->target; | |||
2151 | int lun = link->lun; | |||
2152 | int i; | |||
2153 | struct siop_target *siop_target; | |||
2154 | ||||
2155 | #ifdef SIOP_DEBUG | |||
2156 | printf("%s:%d:%d: free lun sw entry\n", | |||
2157 | sc->sc_c.sc_dev.dv_xname, target, lun); | |||
2158 | #endif | |||
2159 | ||||
2160 | siop_target = (struct siop_target *)sc->sc_c.targets[target]; | |||
2161 | free(siop_target->siop_lun[lun], M_DEVBUF2, 0); | |||
2162 | siop_target->siop_lun[lun] = NULL((void *)0); | |||
2163 | /* XXX compact sw entry too ? */ | |||
2164 | /* check if we can free the whole target */ | |||
2165 | for (i = 0; i < 8; i++) { | |||
2166 | if (siop_target->siop_lun[i] != NULL((void *)0)) | |||
2167 | return; | |||
2168 | } | |||
2169 | #ifdef SIOP_DEBUG | |||
2170 | printf("%s: free siop_target for target %d lun %d lunsw offset %d\n", | |||
2171 | sc->sc_c.sc_dev.dv_xname, target, lun, | |||
2172 | siop_target->lunsw->lunsw_off); | |||
2173 | #endif | |||
2174 | /* | |||
2175 | * nothing here, free the target struct and resel | |||
2176 | * switch entry | |||
2177 | */ | |||
2178 | siop_script_write(sc, siop_target->reseloff, 0x800c00ff); | |||
2179 | siop_script_sync(sc, BUS_DMASYNC_PREWRITE0x04); | |||
2180 | TAILQ_INSERT_TAIL(&sc->lunsw_list, siop_target->lunsw, next)do { (siop_target->lunsw)->next.tqe_next = ((void *)0); (siop_target->lunsw)->next.tqe_prev = (&sc->lunsw_list )->tqh_last; *(&sc->lunsw_list)->tqh_last = (siop_target ->lunsw); (&sc->lunsw_list)->tqh_last = &(siop_target ->lunsw)->next.tqe_next; } while (0); | |||
2181 | free(sc->sc_c.targets[target], M_DEVBUF2, 0); | |||
2182 | sc->sc_c.targets[target] = NULL((void *)0); | |||
2183 | sc->sc_ntargets--; | |||
2184 | } | |||
2185 | ||||
2186 | #ifdef SIOP_STATS | |||
2187 | void | |||
2188 | siop_printstats(void) | |||
2189 | { | |||
2190 | printf("siop_stat_intr %d\n", siop_stat_intr); | |||
2191 | printf("siop_stat_intr_shortxfer %d\n", siop_stat_intr_shortxfer); | |||
2192 | printf("siop_stat_intr_xferdisc %d\n", siop_stat_intr_xferdisc); | |||
2193 | printf("siop_stat_intr_sdp %d\n", siop_stat_intr_sdp); | |||
2194 | printf("siop_stat_intr_saveoffset %d\n", siop_stat_intr_saveoffset); | |||
2195 | printf("siop_stat_intr_done %d\n", siop_stat_intr_done); | |||
2196 | printf("siop_stat_intr_lunresel %d\n", siop_stat_intr_lunresel); | |||
2197 | printf("siop_stat_intr_qfull %d\n", siop_stat_intr_qfull); | |||
2198 | } | |||
2199 | #endif | |||
2200 | ||||
2201 | struct siop_dmamem * | |||
2202 | siop_dmamem_alloc(struct siop_softc *sc, size_t size) | |||
2203 | { | |||
2204 | struct siop_dmamem *sdm; | |||
2205 | int nsegs; | |||
2206 | ||||
2207 | sdm = malloc(sizeof(*sdm), M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008); | |||
2208 | if (sdm == NULL((void *)0)) | |||
2209 | return (NULL((void *)0)); | |||
2210 | ||||
2211 | sdm->sdm_size = size; | |||
2212 | ||||
2213 | if (bus_dmamap_create(sc->sc_c.sc_dmat, size, 1, size, 0,(*(sc->sc_c.sc_dmat)->_dmamap_create)((sc->sc_c.sc_dmat ), (size), (1), (size), (0), (0x0001 | 0x0002), (&sdm-> sdm_map)) | |||
2214 | BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sdm->sdm_map)(*(sc->sc_c.sc_dmat)->_dmamap_create)((sc->sc_c.sc_dmat ), (size), (1), (size), (0), (0x0001 | 0x0002), (&sdm-> sdm_map)) != 0) | |||
2215 | goto sdmfree; | |||
2216 | ||||
2217 | if (bus_dmamem_alloc(sc->sc_c.sc_dmat, size, PAGE_SIZE, 0,(*(sc->sc_c.sc_dmat)->_dmamem_alloc)((sc->sc_c.sc_dmat ), (size), ((1 << 12)), (0), (&sdm->sdm_seg), (1 ), (&nsegs), (0x0001 | 0x1000)) | |||
2218 | &sdm->sdm_seg, 1, &nsegs, BUS_DMA_NOWAIT | BUS_DMA_ZERO)(*(sc->sc_c.sc_dmat)->_dmamem_alloc)((sc->sc_c.sc_dmat ), (size), ((1 << 12)), (0), (&sdm->sdm_seg), (1 ), (&nsegs), (0x0001 | 0x1000)) != 0) | |||
2219 | goto destroy; | |||
2220 | ||||
2221 | if (bus_dmamem_map(sc->sc_c.sc_dmat, &sdm->sdm_seg, nsegs, size,(*(sc->sc_c.sc_dmat)->_dmamem_map)((sc->sc_c.sc_dmat ), (&sdm->sdm_seg), (nsegs), (size), (&sdm->sdm_kva ), (0x0001 | 0x0004)) | |||
2222 | &sdm->sdm_kva, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)(*(sc->sc_c.sc_dmat)->_dmamem_map)((sc->sc_c.sc_dmat ), (&sdm->sdm_seg), (nsegs), (size), (&sdm->sdm_kva ), (0x0001 | 0x0004)) != 0) | |||
2223 | goto free; | |||
2224 | ||||
2225 | if (bus_dmamap_load(sc->sc_c.sc_dmat, sdm->sdm_map, sdm->sdm_kva,(*(sc->sc_c.sc_dmat)->_dmamap_load)((sc->sc_c.sc_dmat ), (sdm->sdm_map), (sdm->sdm_kva), (size), (((void *)0) ), (0x0001)) | |||
2226 | size, NULL, BUS_DMA_NOWAIT)(*(sc->sc_c.sc_dmat)->_dmamap_load)((sc->sc_c.sc_dmat ), (sdm->sdm_map), (sdm->sdm_kva), (size), (((void *)0) ), (0x0001)) != 0) | |||
2227 | goto unmap; | |||
2228 | ||||
2229 | return (sdm); | |||
2230 | ||||
2231 | unmap: | |||
2232 | bus_dmamem_unmap(sc->sc_c.sc_dmat, sdm->sdm_kva, size)(*(sc->sc_c.sc_dmat)->_dmamem_unmap)((sc->sc_c.sc_dmat ), (sdm->sdm_kva), (size)); | |||
2233 | free: | |||
2234 | bus_dmamem_free(sc->sc_c.sc_dmat, &sdm->sdm_seg, 1)(*(sc->sc_c.sc_dmat)->_dmamem_free)((sc->sc_c.sc_dmat ), (&sdm->sdm_seg), (1)); | |||
2235 | destroy: | |||
2236 | bus_dmamap_destroy(sc->sc_c.sc_dmat, sdm->sdm_map)(*(sc->sc_c.sc_dmat)->_dmamap_destroy)((sc->sc_c.sc_dmat ), (sdm->sdm_map)); | |||
2237 | sdmfree: | |||
2238 | free(sdm, M_DEVBUF2, sizeof *sdm); | |||
2239 | ||||
2240 | return (NULL((void *)0)); | |||
2241 | } | |||
2242 | ||||
2243 | void | |||
2244 | siop_dmamem_free(struct siop_softc *sc, struct siop_dmamem *sdm) | |||
2245 | { | |||
2246 | bus_dmamap_unload(sc->sc_c.sc_dmat, sdm->sdm_map)(*(sc->sc_c.sc_dmat)->_dmamap_unload)((sc->sc_c.sc_dmat ), (sdm->sdm_map)); | |||
2247 | bus_dmamem_unmap(sc->sc_c.sc_dmat, sdm->sdm_kva, sdm->sdm_size)(*(sc->sc_c.sc_dmat)->_dmamem_unmap)((sc->sc_c.sc_dmat ), (sdm->sdm_kva), (sdm->sdm_size)); | |||
2248 | bus_dmamem_free(sc->sc_c.sc_dmat, &sdm->sdm_seg, 1)(*(sc->sc_c.sc_dmat)->_dmamem_free)((sc->sc_c.sc_dmat ), (&sdm->sdm_seg), (1)); | |||
2249 | bus_dmamap_destroy(sc->sc_c.sc_dmat, sdm->sdm_map)(*(sc->sc_c.sc_dmat)->_dmamap_destroy)((sc->sc_c.sc_dmat ), (sdm->sdm_map)); | |||
2250 | free(sdm, M_DEVBUF2, sizeof *sdm); | |||
2251 | } |