File: | dev/ic/aic79xx.c |
Warning: | line 2759, column 5 Value stored to 'len' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: aic79xx.c,v 1.67 2022/01/09 05:42:38 jsg Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 2004 Milos Urbanek, Kenneth R. Westerback & Marco Peereboom |
5 | * All rights reserved. |
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 AUTHORS AND CONTRIBUTORS ``AS IS'' AND |
17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR |
20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
26 | * SUCH DAMAGE. |
27 | * |
28 | */ |
29 | |
30 | /* |
31 | * Core routines and tables shareable across OS platforms. |
32 | * |
33 | * Copyright (c) 1994-2002, 2004 Justin T. Gibbs. |
34 | * Copyright (c) 2000-2003 Adaptec Inc. |
35 | * All rights reserved. |
36 | * |
37 | * Redistribution and use in source and binary forms, with or without |
38 | * modification, are permitted provided that the following conditions |
39 | * are met: |
40 | * 1. Redistributions of source code must retain the above copyright |
41 | * notice, this list of conditions, and the following disclaimer, |
42 | * without modification. |
43 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer |
44 | * substantially similar to the "NO WARRANTY" disclaimer below |
45 | * ("Disclaimer") and any redistribution must be conditioned upon |
46 | * including a substantially similar Disclaimer requirement for further |
47 | * binary redistribution. |
48 | * 3. Neither the names of the above-listed copyright holders nor the names |
49 | * of any contributors may be used to endorse or promote products derived |
50 | * from this software without specific prior written permission. |
51 | * |
52 | * Alternatively, this software may be distributed under the terms of the |
53 | * GNU General Public License ("GPL") version 2 as published by the Free |
54 | * Software Foundation. |
55 | * |
56 | * NO WARRANTY |
57 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
58 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
59 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR |
60 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
61 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
62 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
63 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
64 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
65 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
66 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
67 | * POSSIBILITY OF SUCH DAMAGES. |
68 | * |
69 | * Id: //depot/aic7xxx/aic7xxx/aic79xx.c#246 |
70 | * |
71 | * FreeBSD: src/sys/dev/aic7xxx/aic79xx.c,v 1.33 2004/11/18 20:22:30 gibbs Exp |
72 | */ |
73 | |
74 | #include <dev/ic/aic79xx_openbsd.h> |
75 | #include <dev/ic/aic79xx_inline.h> |
76 | #include <dev/ic/aic79xx.h> |
77 | |
78 | #include <dev/microcode/aic7xxx/aicasm_insformat.h> |
79 | |
80 | /******************************** Globals *************************************/ |
81 | struct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq){ ((void *)0), &(ahd_tailq).tqh_first }; |
82 | uint32_t ahd_attach_to_HostRAID_controllers = 1; |
83 | |
84 | /***************************** Lookup Tables **********************************/ |
85 | char *ahd_chip_names[] = |
86 | { |
87 | "NONE", |
88 | "aic7901", |
89 | "aic7902", |
90 | "aic7901A" |
91 | }; |
92 | |
93 | /* |
94 | * Hardware error codes. |
95 | */ |
96 | struct ahd_hard_error_entry { |
97 | uint8_t errno; |
98 | char *errmesg; |
99 | }; |
100 | |
101 | static struct ahd_hard_error_entry ahd_hard_errors[] = { |
102 | { DSCTMOUT0x02, "Discard Timer has timed out" }, |
103 | { ILLOPCODE0x04, "Illegal Opcode in sequencer program" }, |
104 | { SQPARERR0x08, "Sequencer Parity Error" }, |
105 | { DPARERR0x10, "Data-path Parity Error" }, |
106 | { MPARERR0x20, "Scratch or SCB Memory Parity Error" }, |
107 | { CIOPARERR0x80, "CIOBUS Parity Error" }, |
108 | }; |
109 | static const u_int num_errors = NUM_ELEMENTS(ahd_hard_errors)(sizeof(ahd_hard_errors) / sizeof(*ahd_hard_errors)); |
110 | |
111 | static struct ahd_phase_table_entry ahd_phase_table[] = |
112 | { |
113 | { P_DATAOUT0x00, MSG_NOOP0x08, "in Data-out phase" }, |
114 | { P_DATAIN0x40, MSG_INITIATOR_DET_ERR0x05, "in Data-in phase" }, |
115 | { P_DATAOUT_DT0x20, MSG_NOOP0x08, "in DT Data-out phase" }, |
116 | { P_DATAIN_DT0x60, MSG_INITIATOR_DET_ERR0x05, "in DT Data-in phase" }, |
117 | { P_COMMAND0x80, MSG_NOOP0x08, "in Command phase" }, |
118 | { P_MESGOUT0xa0, MSG_NOOP0x08, "in Message-out phase" }, |
119 | { P_STATUS0xc0, MSG_INITIATOR_DET_ERR0x05, "in Status phase" }, |
120 | { P_MESGIN0xe0, MSG_PARITY_ERROR0x09, "in Message-in phase" }, |
121 | { P_BUSFREE0x01, MSG_NOOP0x08, "while idle" }, |
122 | { 0, MSG_NOOP0x08, "in unknown phase" } |
123 | }; |
124 | |
125 | /* |
126 | * In most cases we only wish to iterate over real phases, so |
127 | * exclude the last element from the count. |
128 | */ |
129 | static const u_int num_phases = NUM_ELEMENTS(ahd_phase_table)(sizeof(ahd_phase_table) / sizeof(*ahd_phase_table)) - 1; |
130 | |
131 | /* Our Sequencer Program */ |
132 | #include <dev/microcode/aic7xxx/aic79xx_seq.h> |
133 | |
134 | /**************************** Function Declarations ***************************/ |
135 | void ahd_handle_transmission_error(struct ahd_softc *ahd); |
136 | void ahd_handle_lqiphase_error(struct ahd_softc *ahd, |
137 | u_int lqistat1); |
138 | int ahd_handle_pkt_busfree(struct ahd_softc *ahd, |
139 | u_int busfreetime); |
140 | int ahd_handle_nonpkt_busfree(struct ahd_softc *ahd); |
141 | void ahd_handle_proto_violation(struct ahd_softc *ahd); |
142 | void ahd_force_renegotiation(struct ahd_softc *ahd, |
143 | struct ahd_devinfo *devinfo); |
144 | |
145 | struct ahd_tmode_tstate* |
146 | ahd_alloc_tstate(struct ahd_softc *ahd, |
147 | u_int scsi_id, char channel); |
148 | #ifdef AHD_TARGET_MODE |
149 | void ahd_free_tstate(struct ahd_softc *ahd, |
150 | u_int scsi_id, char channel, int force); |
151 | #endif |
152 | void ahd_devlimited_syncrate(struct ahd_softc *ahd, |
153 | struct ahd_initiator_tinfo *, |
154 | u_int *period, |
155 | u_int *ppr_options, |
156 | role_t role); |
157 | void ahd_update_neg_table(struct ahd_softc *ahd, |
158 | struct ahd_devinfo *devinfo, |
159 | struct ahd_transinfo *tinfo); |
160 | void ahd_update_pending_scbs(struct ahd_softc *ahd); |
161 | void ahd_fetch_devinfo(struct ahd_softc *ahd, |
162 | struct ahd_devinfo *devinfo); |
163 | void ahd_scb_devinfo(struct ahd_softc *ahd, |
164 | struct ahd_devinfo *devinfo, |
165 | struct scb *scb); |
166 | void ahd_setup_initiator_msgout(struct ahd_softc *ahd, |
167 | struct ahd_devinfo *devinfo, |
168 | struct scb *scb); |
169 | void ahd_build_transfer_msg(struct ahd_softc *ahd, |
170 | struct ahd_devinfo *devinfo); |
171 | void ahd_construct_sdtr(struct ahd_softc *ahd, |
172 | struct ahd_devinfo *devinfo, |
173 | u_int period, u_int offset); |
174 | void ahd_construct_wdtr(struct ahd_softc *ahd, |
175 | struct ahd_devinfo *devinfo, |
176 | u_int bus_width); |
177 | void ahd_construct_ppr(struct ahd_softc *ahd, |
178 | struct ahd_devinfo *devinfo, |
179 | u_int period, u_int offset, |
180 | u_int bus_width, u_int ppr_options); |
181 | void ahd_clear_msg_state(struct ahd_softc *ahd); |
182 | void ahd_handle_message_phase(struct ahd_softc *ahd); |
183 | typedef enum { |
184 | AHDMSG_1B, |
185 | AHDMSG_2B, |
186 | AHDMSG_EXT |
187 | } ahd_msgtype; |
188 | int ahd_sent_msg(struct ahd_softc *ahd, ahd_msgtype type, |
189 | u_int msgval, int full); |
190 | int ahd_parse_msg(struct ahd_softc *ahd, |
191 | struct ahd_devinfo *devinfo); |
192 | int ahd_handle_msg_reject(struct ahd_softc *ahd, |
193 | struct ahd_devinfo *devinfo); |
194 | void ahd_handle_ign_wide_residue(struct ahd_softc *ahd, |
195 | struct ahd_devinfo *devinfo); |
196 | void ahd_reinitialize_dataptrs(struct ahd_softc *ahd); |
197 | void ahd_handle_devreset(struct ahd_softc *ahd, |
198 | struct ahd_devinfo *devinfo, |
199 | u_int lun, cam_status status, |
200 | char *message, int verbose_level); |
201 | #if AHD_TARGET_MODE |
202 | void ahd_setup_target_msgin(struct ahd_softc *ahd, |
203 | struct ahd_devinfo *devinfo, |
204 | struct scb *scb); |
205 | #endif |
206 | |
207 | u_int ahd_sglist_size(struct ahd_softc *ahd); |
208 | u_int ahd_sglist_allocsize(struct ahd_softc *ahd); |
209 | void ahd_initialize_hscbs(struct ahd_softc *ahd); |
210 | int ahd_init_scbdata(struct ahd_softc *ahd); |
211 | struct scb * ahd_find_scb_by_tag(struct ahd_softc *, u_int); |
212 | void ahd_fini_scbdata(struct ahd_softc *ahd); |
213 | void ahd_setup_iocell_workaround(struct ahd_softc *ahd); |
214 | void ahd_iocell_first_selection(struct ahd_softc *ahd); |
215 | void ahd_chip_init(struct ahd_softc *ahd); |
216 | void ahd_qinfifo_requeue(struct ahd_softc *ahd, |
217 | struct scb *prev_scb, |
218 | struct scb *scb); |
219 | int ahd_qinfifo_count(struct ahd_softc *ahd); |
220 | int ahd_search_scb_list(struct ahd_softc *ahd, int target, |
221 | char channel, int lun, u_int tag, |
222 | role_t role, uint32_t status, |
223 | ahd_search_action action, |
224 | u_int *list_head, u_int *list_tail, |
225 | u_int tid); |
226 | void ahd_stitch_tid_list(struct ahd_softc *ahd, |
227 | u_int tid_prev, u_int tid_cur, |
228 | u_int tid_next); |
229 | void ahd_add_scb_to_free_list(struct ahd_softc *ahd, |
230 | u_int scbid); |
231 | u_int ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid, |
232 | u_int prev, u_int next, u_int tid); |
233 | void ahd_reset_current_bus(struct ahd_softc *ahd); |
234 | ahd_callback_t ahd_reset_poll; |
235 | ahd_callback_t ahd_stat_timer; |
236 | #ifdef AHD_DUMP_SEQ |
237 | void ahd_dumpseq(struct ahd_softc *ahd); |
238 | #endif |
239 | void ahd_loadseq(struct ahd_softc *ahd); |
240 | int ahd_check_patch(struct ahd_softc *ahd, |
241 | const struct patch **start_patch, |
242 | u_int start_instr, u_int *skip_addr); |
243 | u_int ahd_resolve_seqaddr(struct ahd_softc *ahd, |
244 | u_int address); |
245 | void ahd_download_instr(struct ahd_softc *ahd, |
246 | u_int instrptr, uint8_t *dconsts); |
247 | int ahd_probe_stack_size(struct ahd_softc *ahd); |
248 | int ahd_scb_active_in_fifo(struct ahd_softc *ahd, |
249 | struct scb *scb); |
250 | void ahd_run_data_fifo(struct ahd_softc *ahd, |
251 | struct scb *scb); |
252 | |
253 | #ifdef AHD_TARGET_MODE |
254 | void ahd_queue_lstate_event(struct ahd_softc *ahd, |
255 | struct ahd_tmode_lstate *lstate, |
256 | u_int initiator_id, |
257 | u_int event_type, |
258 | u_int event_arg); |
259 | void ahd_update_scsiid(struct ahd_softc *ahd, |
260 | u_int targid_mask); |
261 | int ahd_handle_target_cmd(struct ahd_softc *ahd, |
262 | struct target_cmd *cmd); |
263 | #endif |
264 | |
265 | /************************** Added for porting to NetBSD ***********************/ |
266 | int ahd_createdmamem(struct ahd_softc *, size_t, struct map_node *, |
267 | const char *); |
268 | |
269 | void ahd_freedmamem(struct ahd_softc *, struct map_node *); |
270 | |
271 | /******************************** Private Inlines *****************************/ |
272 | int ahd_currently_packetized(struct ahd_softc *ahd); |
273 | int ahd_set_active_fifo(struct ahd_softc *ahd); |
274 | |
275 | static inline void |
276 | ahd_assert_atn(struct ahd_softc *ahd) |
277 | { |
278 | ahd_outb(ahd, SCSISIGO, ATNO)(((ahd)->tags[(0x40) >> 8])->write_1(((ahd)->bshs [(0x40) >> 8]), ((0x40) & 0xFF), (0x10))); |
279 | } |
280 | |
281 | /* |
282 | * Determine if the current connection has a packetized |
283 | * agreement. This does not necessarily mean that we |
284 | * are currently in a packetized transfer. We could |
285 | * just as easily be sending or receiving a message. |
286 | */ |
287 | int |
288 | ahd_currently_packetized(struct ahd_softc *ahd) |
289 | { |
290 | ahd_mode_state saved_modes; |
291 | int packetized; |
292 | |
293 | saved_modes = ahd_save_modes(ahd); |
294 | if ((ahd->bugs & AHD_PKTIZED_STATUS_BUG) != 0) { |
295 | /* |
296 | * The packetized bit refers to the last |
297 | * connection, not the current one. Check |
298 | * for non-zero LQISTATE instead. |
299 | */ |
300 | ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); |
301 | packetized = ahd_inb(ahd, LQISTATE)(((ahd)->tags[(0x4e) >> 8])->read_1(((ahd)->bshs [(0x4e) >> 8]), ((0x4e) & 0xFF))) != 0; |
302 | } else { |
303 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
304 | packetized = ahd_inb(ahd, LQISTAT2)(((ahd)->tags[(0x52) >> 8])->read_1(((ahd)->bshs [(0x52) >> 8]), ((0x52) & 0xFF))) & PACKETIZED0x80; |
305 | } |
306 | ahd_restore_modes(ahd, saved_modes); |
307 | return (packetized); |
308 | } |
309 | |
310 | int |
311 | ahd_set_active_fifo(struct ahd_softc *ahd) |
312 | { |
313 | u_int active_fifo; |
314 | |
315 | AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK)ahd_assert_modes(ahd, (0x01 << (AHD_MODE_SCSI)), (0x01 << (AHD_MODE_SCSI)), "/usr/src/sys/dev/ic/aic79xx.c", 315);; |
316 | active_fifo = ahd_inb(ahd, DFFSTAT)(((ahd)->tags[(0x3f) >> 8])->read_1(((ahd)->bshs [(0x3f) >> 8]), ((0x3f) & 0xFF))) & CURRFIFO0x03; |
317 | switch (active_fifo) { |
318 | case 0: |
319 | case 1: |
320 | ahd_set_modes(ahd, active_fifo, active_fifo); |
321 | return (1); |
322 | default: |
323 | return (0); |
324 | } |
325 | } |
326 | |
327 | /************************* Sequencer Execution Control ************************/ |
328 | /* |
329 | * Restart the sequencer program from address zero |
330 | */ |
331 | void |
332 | ahd_restart(struct ahd_softc *ahd) |
333 | { |
334 | |
335 | ahd_pause(ahd); |
336 | |
337 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
338 | |
339 | /* No more pending messages */ |
340 | ahd_clear_msg_state(ahd); |
341 | ahd_outb(ahd, SCSISIGO, 0)(((ahd)->tags[(0x40) >> 8])->write_1(((ahd)->bshs [(0x40) >> 8]), ((0x40) & 0xFF), (0))); /* De-assert BSY */ |
342 | ahd_outb(ahd, MSG_OUT, MSG_NOOP)(((ahd)->tags[(0x137) >> 8])->write_1(((ahd)-> bshs[(0x137) >> 8]), ((0x137) & 0xFF), (0x08))); /* No message to send */ |
343 | ahd_outb(ahd, SXFRCTL1, ahd_inb(ahd, SXFRCTL1) & ~BITBUCKET)(((ahd)->tags[(0x3d) >> 8])->write_1(((ahd)->bshs [(0x3d) >> 8]), ((0x3d) & 0xFF), ((((ahd)->tags[ (0x3d) >> 8])->read_1(((ahd)->bshs[(0x3d) >> 8]), ((0x3d) & 0xFF))) & ~0x80))); |
344 | ahd_outb(ahd, SEQINTCTL, 0)(((ahd)->tags[(0xd9) >> 8])->write_1(((ahd)->bshs [(0xd9) >> 8]), ((0xd9) & 0xFF), (0))); |
345 | ahd_outb(ahd, LASTPHASE, P_BUSFREE)(((ahd)->tags[(0x13c) >> 8])->write_1(((ahd)-> bshs[(0x13c) >> 8]), ((0x13c) & 0xFF), (0x01))); |
346 | ahd_outb(ahd, SEQ_FLAGS, 0)(((ahd)->tags[(0x139) >> 8])->write_1(((ahd)-> bshs[(0x139) >> 8]), ((0x139) & 0xFF), (0))); |
347 | ahd_outb(ahd, SAVED_SCSIID, 0xFF)(((ahd)->tags[(0x13a) >> 8])->write_1(((ahd)-> bshs[(0x13a) >> 8]), ((0x13a) & 0xFF), (0xFF))); |
348 | ahd_outb(ahd, SAVED_LUN, 0xFF)(((ahd)->tags[(0x13b) >> 8])->write_1(((ahd)-> bshs[(0x13b) >> 8]), ((0x13b) & 0xFF), (0xFF))); |
349 | |
350 | /* |
351 | * Ensure that the sequencer's idea of TQINPOS |
352 | * matches our own. The sequencer increments TQINPOS |
353 | * only after it sees a DMA complete and a reset could |
354 | * occur before the increment leaving the kernel to believe |
355 | * the command arrived but the sequencer to not. |
356 | */ |
357 | ahd_outb(ahd, TQINPOS, ahd->tqinfifonext)(((ahd)->tags[(0x13f) >> 8])->write_1(((ahd)-> bshs[(0x13f) >> 8]), ((0x13f) & 0xFF), (ahd->tqinfifonext ))); |
358 | |
359 | /* Always allow reselection */ |
360 | ahd_outb(ahd, SCSISEQ1,(((ahd)->tags[(0x3b) >> 8])->write_1(((ahd)->bshs [(0x3b) >> 8]), ((0x3b) & 0xFF), ((((ahd)->tags[ (0x14b) >> 8])->read_1(((ahd)->bshs[(0x14b) >> 8]), ((0x14b) & 0xFF))) & (0x20|0x10|0x02)))) |
361 | ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP))(((ahd)->tags[(0x3b) >> 8])->write_1(((ahd)->bshs [(0x3b) >> 8]), ((0x3b) & 0xFF), ((((ahd)->tags[ (0x14b) >> 8])->read_1(((ahd)->bshs[(0x14b) >> 8]), ((0x14b) & 0xFF))) & (0x20|0x10|0x02)))); |
362 | ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); |
363 | |
364 | /* |
365 | * Clear any pending sequencer interrupt. It is no |
366 | * longer relevant since we're resetting the Program |
367 | * Counter. |
368 | */ |
369 | ahd_outb(ahd, CLRINT, CLRSEQINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x04))); |
370 | |
371 | ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET)(((ahd)->tags[(0xd6) >> 8])->write_1(((ahd)->bshs [(0xd6) >> 8]), ((0xd6) & 0xFF), (0x10|0x02))); |
372 | ahd_unpause(ahd); |
373 | } |
374 | |
375 | void |
376 | ahd_clear_fifo(struct ahd_softc *ahd, u_int fifo) |
377 | { |
378 | ahd_mode_state saved_modes; |
379 | |
380 | #ifdef AHD_DEBUG |
381 | if ((ahd_debug & AHD_SHOW_FIFOS) != 0) |
382 | printf("%s: Clearing FIFO %d\n", ahd_name(ahd), fifo); |
383 | #endif |
384 | saved_modes = ahd_save_modes(ahd); |
385 | ahd_set_modes(ahd, fifo, fifo); |
386 | ahd_outb(ahd, DFFSXFRCTL, RSTCHN|CLRSHCNT)(((ahd)->tags[(0x5a) >> 8])->write_1(((ahd)->bshs [(0x5a) >> 8]), ((0x5a) & 0xFF), (0x01|0x04))); |
387 | if ((ahd_inb(ahd, SG_STATE)(((ahd)->tags[(0xa6) >> 8])->read_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF))) & FETCH_INPROG0x04) != 0) |
388 | ahd_outb(ahd, CCSGCTL, CCSGRESET)(((ahd)->tags[(0xad) >> 8])->write_1(((ahd)->bshs [(0xad) >> 8]), ((0xad) & 0xFF), (0x01))); |
389 | ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR)(((ahd)->tags[(0xf8 + 1) >> 8])->write_1(((ahd)-> bshs[(0xf8 + 1) >> 8]), ((0xf8 + 1) & 0xFF), (0x80) )); |
390 | ahd_outb(ahd, SG_STATE, 0)(((ahd)->tags[(0xa6) >> 8])->write_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF), (0))); |
391 | ahd_restore_modes(ahd, saved_modes); |
392 | } |
393 | |
394 | /************************* Input/Output Queues ********************************/ |
395 | /* |
396 | * Flush and completed commands that are sitting in the command |
397 | * complete queues down on the chip but have yet to be dma'ed back up. |
398 | */ |
399 | void |
400 | ahd_flush_qoutfifo(struct ahd_softc *ahd) |
401 | { |
402 | struct scb *scb; |
403 | ahd_mode_state saved_modes; |
404 | u_int saved_scbptr; |
405 | u_int ccscbctl; |
406 | u_int scbid; |
407 | u_int next_scbid; |
408 | |
409 | saved_modes = ahd_save_modes(ahd); |
410 | |
411 | /* |
412 | * Flush the good status FIFO for completed packetized commands. |
413 | */ |
414 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
415 | saved_scbptr = ahd_get_scbptr(ahd); |
416 | while ((ahd_inb(ahd, LQISTAT2)(((ahd)->tags[(0x52) >> 8])->read_1(((ahd)->bshs [(0x52) >> 8]), ((0x52) & 0xFF))) & LQIGSAVAIL0x01) != 0) { |
417 | u_int fifo_mode; |
418 | u_int i; |
419 | |
420 | scbid = ahd_inw(ahd, GSFIFO0x58); |
421 | scb = ahd_lookup_scb(ahd, scbid); |
422 | if (scb == NULL((void *)0)) { |
423 | printf("%s: Warning - GSFIFO SCB %d invalid\n", |
424 | ahd_name(ahd), scbid); |
425 | continue; |
426 | } |
427 | /* |
428 | * Determine if this transaction is still active in |
429 | * any FIFO. If it is, we must flush that FIFO to |
430 | * the host before completing the command. |
431 | */ |
432 | fifo_mode = 0; |
433 | rescan_fifos: |
434 | for (i = 0; i < 2; i++) { |
435 | /* Toggle to the other mode. */ |
436 | fifo_mode ^= 1; |
437 | ahd_set_modes(ahd, fifo_mode, fifo_mode); |
438 | |
439 | if (ahd_scb_active_in_fifo(ahd, scb) == 0) |
440 | continue; |
441 | |
442 | ahd_run_data_fifo(ahd, scb); |
443 | |
444 | /* |
445 | * Running this FIFO may cause a CFG4DATA for |
446 | * this same transaction to assert in the other |
447 | * FIFO or a new snapshot SAVEPTRS interrupt |
448 | * in this FIFO. Even running a FIFO may not |
449 | * clear the transaction if we are still waiting |
450 | * for data to drain to the host. We must loop |
451 | * until the transaction is not active in either |
452 | * FIFO just to be sure. Reset our loop counter |
453 | * so we will visit both FIFOs again before |
454 | * declaring this transaction finished. We |
455 | * also delay a bit so that status has a chance |
456 | * to change before we look at this FIFO again. |
457 | */ |
458 | aic_delay(200)(*delay_func)(200); |
459 | goto rescan_fifos; |
460 | } |
461 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
462 | ahd_set_scbptr(ahd, scbid); |
463 | if ((ahd_inb_scbram(ahd, SCB_SGPTR0x1a4) & SG_LIST_NULL0x01) == 0 |
464 | && ((ahd_inb_scbram(ahd, SCB_SGPTR0x1a4) & SG_FULL_RESID0x02) != 0 |
465 | || (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR0x184) |
466 | & SG_LIST_NULL0x01) != 0)) { |
467 | u_int comp_head; |
468 | |
469 | /* |
470 | * The transfer completed with a residual. |
471 | * Place this SCB on the complete DMA list |
472 | * so that we update our in-core copy of the |
473 | * SCB before completing the command. |
474 | */ |
475 | ahd_outb(ahd, SCB_SCSI_STATUS, 0)(((ahd)->tags[(0x188) >> 8])->write_1(((ahd)-> bshs[(0x188) >> 8]), ((0x188) & 0xFF), (0))); |
476 | ahd_outb(ahd, SCB_SGPTR,(((ahd)->tags[(0x1a4) >> 8])->write_1(((ahd)-> bshs[(0x1a4) >> 8]), ((0x1a4) & 0xFF), (ahd_inb_scbram (ahd, 0x1a4) | 0x04))) |
477 | ahd_inb_scbram(ahd, SCB_SGPTR)(((ahd)->tags[(0x1a4) >> 8])->write_1(((ahd)-> bshs[(0x1a4) >> 8]), ((0x1a4) & 0xFF), (ahd_inb_scbram (ahd, 0x1a4) | 0x04))) |
478 | | SG_STATUS_VALID)(((ahd)->tags[(0x1a4) >> 8])->write_1(((ahd)-> bshs[(0x1a4) >> 8]), ((0x1a4) & 0xFF), (ahd_inb_scbram (ahd, 0x1a4) | 0x04))); |
479 | ahd_outw(ahd, SCB_TAG0x190, scbid); |
480 | ahd_outw(ahd, SCB_NEXT_COMPLETE0x18c, SCB_LIST_NULL0xFF00); |
481 | comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD0x12c); |
482 | if (SCBID_IS_NULL(comp_head)(((comp_head) & 0xFF00 ) == 0xFF00)) { |
483 | ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD0x12c, scbid); |
484 | ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL0x12e, scbid); |
485 | } else { |
486 | u_int tail; |
487 | |
488 | tail = ahd_inw(ahd, COMPLETE_DMA_SCB_TAIL0x12e); |
489 | ahd_set_scbptr(ahd, tail); |
490 | ahd_outw(ahd, SCB_NEXT_COMPLETE0x18c, scbid); |
491 | ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL0x12e, scbid); |
492 | ahd_set_scbptr(ahd, scbid); |
493 | } |
494 | } else |
495 | ahd_complete_scb(ahd, scb); |
496 | } |
497 | ahd_set_scbptr(ahd, saved_scbptr); |
498 | |
499 | /* |
500 | * Setup for command channel portion of flush. |
501 | */ |
502 | ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); |
503 | |
504 | /* |
505 | * Wait for any inprogress DMA to complete and clear DMA state |
506 | * if this if for an SCB in the qinfifo. |
507 | */ |
508 | while (((ccscbctl = ahd_inb(ahd, CCSCBCTL)(((ahd)->tags[(0xad) >> 8])->read_1(((ahd)->bshs [(0xad) >> 8]), ((0xad) & 0xFF)))) & (CCARREN0x10|CCSCBEN0x08)) != 0) { |
509 | |
510 | if ((ccscbctl & (CCSCBDIR0x04|CCARREN0x10)) == (CCSCBDIR0x04|CCARREN0x10)) { |
511 | if ((ccscbctl & ARRDONE0x40) != 0) |
512 | break; |
513 | } else if ((ccscbctl & CCSCBDONE0x80) != 0) |
514 | break; |
515 | aic_delay(200)(*delay_func)(200); |
516 | } |
517 | /* |
518 | * We leave the sequencer to cleanup in the case of DMA's to |
519 | * update the qoutfifo. In all other cases (DMA's to the |
520 | * chip or a push of an SCB from the COMPLETE_DMA_SCB list), |
521 | * we disable the DMA engine so that the sequencer will not |
522 | * attempt to handle the DMA completion. |
523 | */ |
524 | if ((ccscbctl & CCSCBDIR0x04) != 0 || (ccscbctl & ARRDONE0x40) != 0) |
525 | ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN))(((ahd)->tags[(0xad) >> 8])->write_1(((ahd)->bshs [(0xad) >> 8]), ((0xad) & 0xFF), (ccscbctl & ~( 0x10|0x08)))); |
526 | |
527 | /* |
528 | * Complete any SCBs that just finished |
529 | * being DMA'ed into the qoutfifo. |
530 | */ |
531 | ahd_run_qoutfifo(ahd); |
532 | |
533 | saved_scbptr = ahd_get_scbptr(ahd); |
534 | /* |
535 | * Manually update/complete any completed SCBs that are waiting to be |
536 | * DMA'ed back up to the host. |
537 | */ |
538 | scbid = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD0x12c); |
539 | while (!SCBID_IS_NULL(scbid)(((scbid) & 0xFF00 ) == 0xFF00)) { |
540 | uint8_t *hscb_ptr; |
541 | u_int i; |
542 | |
543 | ahd_set_scbptr(ahd, scbid); |
544 | next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE0x18c); |
545 | scb = ahd_lookup_scb(ahd, scbid); |
546 | if (scb == NULL((void *)0)) { |
547 | printf("%s: Warning - DMA-up and complete " |
548 | "SCB %d invalid\n", ahd_name(ahd), scbid); |
549 | continue; |
550 | } |
551 | hscb_ptr = (uint8_t *)scb->hscb; |
552 | for (i = 0; i < sizeof(struct hardware_scb); i++) |
553 | *hscb_ptr++ = ahd_inb_scbram(ahd, SCB_BASE0x180 + i); |
554 | |
555 | ahd_complete_scb(ahd, scb); |
556 | scbid = next_scbid; |
557 | } |
558 | ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD0x12c, SCB_LIST_NULL0xFF00); |
559 | ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL0x12e, SCB_LIST_NULL0xFF00); |
560 | |
561 | scbid = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD0x130); |
562 | while (!SCBID_IS_NULL(scbid)(((scbid) & 0xFF00 ) == 0xFF00)) { |
563 | |
564 | ahd_set_scbptr(ahd, scbid); |
565 | next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE0x18c); |
566 | scb = ahd_lookup_scb(ahd, scbid); |
567 | if (scb == NULL((void *)0)) { |
568 | printf("%s: Warning - Complete Qfrz SCB %d invalid\n", |
569 | ahd_name(ahd), scbid); |
570 | continue; |
571 | } |
572 | |
573 | ahd_complete_scb(ahd, scb); |
574 | scbid = next_scbid; |
575 | } |
576 | ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD0x130, SCB_LIST_NULL0xFF00); |
577 | |
578 | scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD0x128); |
579 | while (!SCBID_IS_NULL(scbid)(((scbid) & 0xFF00 ) == 0xFF00)) { |
580 | |
581 | ahd_set_scbptr(ahd, scbid); |
582 | next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE0x18c); |
583 | scb = ahd_lookup_scb(ahd, scbid); |
584 | if (scb == NULL((void *)0)) { |
585 | printf("%s: Warning - Complete SCB %d invalid\n", |
586 | ahd_name(ahd), scbid); |
587 | continue; |
588 | } |
589 | |
590 | ahd_complete_scb(ahd, scb); |
591 | scbid = next_scbid; |
592 | } |
593 | ahd_outw(ahd, COMPLETE_SCB_HEAD0x128, SCB_LIST_NULL0xFF00); |
594 | |
595 | /* |
596 | * Restore state. |
597 | */ |
598 | ahd_set_scbptr(ahd, saved_scbptr); |
599 | ahd_restore_modes(ahd, saved_modes); |
600 | ahd->flags |= AHD_UPDATE_PEND_CMDS; |
601 | } |
602 | |
603 | /* |
604 | * Determine if an SCB for a packetized transaction |
605 | * is active in a FIFO. |
606 | */ |
607 | int |
608 | ahd_scb_active_in_fifo(struct ahd_softc *ahd, struct scb *scb) |
609 | { |
610 | |
611 | /* |
612 | * The FIFO is only active for our transaction if |
613 | * the SCBPTR matches the SCB's ID and the firmware |
614 | * has installed a handler for the FIFO or we have |
615 | * a pending SAVEPTRS or CFG4DATA interrupt. |
616 | */ |
617 | if (ahd_get_scbptr(ahd) != SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)) |
618 | || ((ahd_inb(ahd, LONGJMP_ADDR+1)(((ahd)->tags[(0xf8 +1) >> 8])->read_1(((ahd)-> bshs[(0xf8 +1) >> 8]), ((0xf8 +1) & 0xFF))) & INVALID_ADDR0x80) != 0 |
619 | && (ahd_inb(ahd, SEQINTSRC)(((ahd)->tags[(0x5b) >> 8])->read_1(((ahd)->bshs [(0x5b) >> 8]), ((0x5b) & 0xFF))) & (CFG4DATA0x10|SAVEPTRS0x20)) == 0)) |
620 | return (0); |
621 | |
622 | return (1); |
623 | } |
624 | |
625 | /* |
626 | * Run a data fifo to completion for a transaction we know |
627 | * has completed across the SCSI bus (good status has been |
628 | * received). We are already set to the correct FIFO mode |
629 | * on entry to this routine. |
630 | * |
631 | * This function attempts to operate exactly as the firmware |
632 | * would when running this FIFO. Care must be taken to update |
633 | * this routine any time the firmware's FIFO algorithm is |
634 | * changed. |
635 | */ |
636 | void |
637 | ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb) |
638 | { |
639 | u_int seqintsrc; |
640 | |
641 | seqintsrc = ahd_inb(ahd, SEQINTSRC)(((ahd)->tags[(0x5b) >> 8])->read_1(((ahd)->bshs [(0x5b) >> 8]), ((0x5b) & 0xFF))); |
642 | if ((seqintsrc & CFG4DATA0x10) != 0) { |
643 | uint32_t datacnt; |
644 | uint32_t sgptr; |
645 | |
646 | /* |
647 | * Clear full residual flag. |
648 | */ |
649 | sgptr = ahd_inl_scbram(ahd, SCB_SGPTR0x1a4) & ~SG_FULL_RESID0x02; |
650 | ahd_outb(ahd, SCB_SGPTR, sgptr)(((ahd)->tags[(0x1a4) >> 8])->write_1(((ahd)-> bshs[(0x1a4) >> 8]), ((0x1a4) & 0xFF), (sgptr))); |
651 | |
652 | /* |
653 | * Load datacnt and address. |
654 | */ |
655 | datacnt = ahd_inl_scbram(ahd, SCB_DATACNT0x1a0); |
656 | if ((datacnt & AHD_DMA_LAST_SEG0x80000000) != 0) { |
657 | sgptr |= LAST_SEG0x02; |
658 | ahd_outb(ahd, SG_STATE, 0)(((ahd)->tags[(0xa6) >> 8])->write_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF), (0))); |
659 | } else |
660 | ahd_outb(ahd, SG_STATE, LOADING_NEEDED)(((ahd)->tags[(0xa6) >> 8])->write_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF), (0x02))); |
661 | ahd_outq(ahd, HADDR0x70, ahd_inq_scbram(ahd, SCB_DATAPTR0x198)); |
662 | ahd_outl(ahd, HCNT0x78, datacnt & AHD_SG_LEN_MASK0x00FFFFFF); |
663 | ahd_outb(ahd, SG_CACHE_PRE, sgptr)(((ahd)->tags[(0x1b) >> 8])->write_1(((ahd)->bshs [(0x1b) >> 8]), ((0x1b) & 0xFF), (sgptr))); |
664 | ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN)(((ahd)->tags[(0x19) >> 8])->write_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF), (0x80|0x20|0x08))); |
665 | |
666 | /* |
667 | * Initialize Residual Fields. |
668 | */ |
669 | ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24)(((ahd)->tags[(0x180 +3) >> 8])->write_1(((ahd)-> bshs[(0x180 +3) >> 8]), ((0x180 +3) & 0xFF), (datacnt >> 24))); |
670 | ahd_outl(ahd, SCB_RESIDUAL_SGPTR0x184, sgptr & SG_PTR_MASK0xFFFFFFF8); |
671 | |
672 | /* |
673 | * Mark the SCB as having a FIFO in use. |
674 | */ |
675 | ahd_outb(ahd, SCB_FIFO_USE_COUNT,(((ahd)->tags[(0x190) >> 8])->write_1(((ahd)-> bshs[(0x190) >> 8]), ((0x190) & 0xFF), (ahd_inb_scbram (ahd, 0x190) + 1))) |
676 | ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1)(((ahd)->tags[(0x190) >> 8])->write_1(((ahd)-> bshs[(0x190) >> 8]), ((0x190) & 0xFF), (ahd_inb_scbram (ahd, 0x190) + 1))); |
677 | |
678 | /* |
679 | * Install a "fake" handler for this FIFO. |
680 | */ |
681 | ahd_outw(ahd, LONGJMP_ADDR0xf8, 0); |
682 | |
683 | /* |
684 | * Notify the hardware that we have satisfied |
685 | * this sequencer interrupt. |
686 | */ |
687 | ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA)(((ahd)->tags[(0x5b) >> 8])->write_1(((ahd)->bshs [(0x5b) >> 8]), ((0x5b) & 0xFF), (0x10))); |
688 | } else if ((seqintsrc & SAVEPTRS0x20) != 0) { |
689 | uint32_t sgptr; |
690 | uint32_t resid; |
691 | |
692 | if ((ahd_inb(ahd, LONGJMP_ADDR+1)(((ahd)->tags[(0xf8 +1) >> 8])->read_1(((ahd)-> bshs[(0xf8 +1) >> 8]), ((0xf8 +1) & 0xFF)))&INVALID_ADDR0x80) != 0) { |
693 | /* |
694 | * Snapshot Save Pointers. All that |
695 | * is necessary to clear the snapshot |
696 | * is a CLRCHN. |
697 | */ |
698 | goto clrchn; |
699 | } |
700 | |
701 | /* |
702 | * Disable S/G fetch so the DMA engine |
703 | * is available to future users. |
704 | */ |
705 | if ((ahd_inb(ahd, SG_STATE)(((ahd)->tags[(0xa6) >> 8])->read_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF))) & FETCH_INPROG0x04) != 0) |
706 | ahd_outb(ahd, CCSGCTL, 0)(((ahd)->tags[(0xad) >> 8])->write_1(((ahd)->bshs [(0xad) >> 8]), ((0xad) & 0xFF), (0))); |
707 | ahd_outb(ahd, SG_STATE, 0)(((ahd)->tags[(0xa6) >> 8])->write_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF), (0))); |
708 | |
709 | /* |
710 | * Flush the data FIFO. Strictly only |
711 | * necessary for Rev A parts. |
712 | */ |
713 | ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH)(((ahd)->tags[(0x19) >> 8])->write_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF), ((((ahd)->tags[ (0x19) >> 8])->read_1(((ahd)->bshs[(0x19) >> 8]), ((0x19) & 0xFF))) | 0x02))); |
714 | |
715 | /* |
716 | * Calculate residual. |
717 | */ |
718 | sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR0x184); |
719 | resid = ahd_inl(ahd, SHCNT0x68); |
720 | resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT0x180+3) << 24; |
721 | ahd_outl(ahd, SCB_RESIDUAL_DATACNT0x180, resid); |
722 | if ((ahd_inb(ahd, SG_CACHE_SHADOW)(((ahd)->tags[(0x1b) >> 8])->read_1(((ahd)->bshs [(0x1b) >> 8]), ((0x1b) & 0xFF))) & LAST_SEG0x02) == 0) { |
723 | /* |
724 | * Must back up to the correct S/G element. |
725 | * Typically this just means resetting our |
726 | * low byte to the offset in the SG_CACHE, |
727 | * but if we wrapped, we have to correct |
728 | * the other bytes of the sgptr too. |
729 | */ |
730 | if ((ahd_inb(ahd, SG_CACHE_SHADOW)(((ahd)->tags[(0x1b) >> 8])->read_1(((ahd)->bshs [(0x1b) >> 8]), ((0x1b) & 0xFF))) & 0x80) != 0 |
731 | && (sgptr & 0x80) == 0) |
732 | sgptr -= 0x100; |
733 | sgptr &= ~0xFF; |
734 | sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)(((ahd)->tags[(0x1b) >> 8])->read_1(((ahd)->bshs [(0x1b) >> 8]), ((0x1b) & 0xFF))) |
735 | & SG_ADDR_MASK0xf8; |
736 | ahd_outl(ahd, SCB_RESIDUAL_SGPTR0x184, sgptr); |
737 | ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0)(((ahd)->tags[(0x180 + 3) >> 8])->write_1(((ahd)-> bshs[(0x180 + 3) >> 8]), ((0x180 + 3) & 0xFF), (0)) ); |
738 | } else if ((resid & AHD_SG_LEN_MASK0x00FFFFFF) == 0) { |
739 | ahd_outb(ahd, SCB_RESIDUAL_SGPTR,(((ahd)->tags[(0x184) >> 8])->write_1(((ahd)-> bshs[(0x184) >> 8]), ((0x184) & 0xFF), (sgptr | 0x01 ))) |
740 | sgptr | SG_LIST_NULL)(((ahd)->tags[(0x184) >> 8])->write_1(((ahd)-> bshs[(0x184) >> 8]), ((0x184) & 0xFF), (sgptr | 0x01 ))); |
741 | } |
742 | /* |
743 | * Save Pointers. |
744 | */ |
745 | ahd_outq(ahd, SCB_DATAPTR0x198, ahd_inq(ahd, SHADDR0x60)); |
746 | ahd_outl(ahd, SCB_DATACNT0x1a0, resid); |
747 | ahd_outl(ahd, SCB_SGPTR0x1a4, sgptr); |
748 | ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS)(((ahd)->tags[(0x5b) >> 8])->write_1(((ahd)->bshs [(0x5b) >> 8]), ((0x5b) & 0xFF), (0x20))); |
749 | ahd_outb(ahd, SEQIMODE,(((ahd)->tags[(0x5c) >> 8])->write_1(((ahd)->bshs [(0x5c) >> 8]), ((0x5c) & 0xFF), ((((ahd)->tags[ (0x5c) >> 8])->read_1(((ahd)->bshs[(0x5c) >> 8]), ((0x5c) & 0xFF))) | 0x20))) |
750 | ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS)(((ahd)->tags[(0x5c) >> 8])->write_1(((ahd)->bshs [(0x5c) >> 8]), ((0x5c) & 0xFF), ((((ahd)->tags[ (0x5c) >> 8])->read_1(((ahd)->bshs[(0x5c) >> 8]), ((0x5c) & 0xFF))) | 0x20))); |
751 | /* |
752 | * If the data is to the SCSI bus, we are |
753 | * done, otherwise wait for FIFOEMP. |
754 | */ |
755 | if ((ahd_inb(ahd, DFCNTRL)(((ahd)->tags[(0x19) >> 8])->read_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF))) & DIRECTION0x04) != 0) |
756 | goto clrchn; |
757 | } else if ((ahd_inb(ahd, SG_STATE)(((ahd)->tags[(0xa6) >> 8])->read_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF))) & LOADING_NEEDED0x02) != 0) { |
758 | uint32_t sgptr; |
759 | uint64_t data_addr; |
760 | uint32_t data_len; |
761 | u_int dfcntrl; |
762 | |
763 | /* |
764 | * Disable S/G fetch so the DMA engine |
765 | * is available to future users. We won't |
766 | * be using the DMA engine to load segments. |
767 | */ |
768 | if ((ahd_inb(ahd, SG_STATE)(((ahd)->tags[(0xa6) >> 8])->read_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF))) & FETCH_INPROG0x04) != 0) { |
769 | ahd_outb(ahd, CCSGCTL, 0)(((ahd)->tags[(0xad) >> 8])->write_1(((ahd)->bshs [(0xad) >> 8]), ((0xad) & 0xFF), (0))); |
770 | ahd_outb(ahd, SG_STATE, LOADING_NEEDED)(((ahd)->tags[(0xa6) >> 8])->write_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF), (0x02))); |
771 | } |
772 | |
773 | /* |
774 | * Wait for the DMA engine to notice that the |
775 | * host transfer is enabled and that there is |
776 | * space in the S/G FIFO for new segments before |
777 | * loading more segments. |
778 | */ |
779 | if ((ahd_inb(ahd, DFSTATUS)(((ahd)->tags[(0x1a) >> 8])->read_1(((ahd)->bshs [(0x1a) >> 8]), ((0x1a) & 0xFF))) & PRELOAD_AVAIL0x80) != 0 |
780 | && (ahd_inb(ahd, DFCNTRL)(((ahd)->tags[(0x19) >> 8])->read_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF))) & HDMAENACK0x08) != 0) { |
781 | |
782 | /* |
783 | * Determine the offset of the next S/G |
784 | * element to load. |
785 | */ |
786 | sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR0x184); |
787 | sgptr &= SG_PTR_MASK0xFFFFFFF8; |
788 | if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) { |
789 | struct ahd_dma64_seg *sg; |
790 | |
791 | sg = ahd_sg_bus_to_virt(ahd, scb, sgptr); |
792 | data_addr = sg->addr; |
793 | data_len = sg->len; |
794 | sgptr += sizeof(*sg); |
795 | } else { |
796 | struct ahd_dma_seg *sg; |
797 | |
798 | sg = ahd_sg_bus_to_virt(ahd, scb, sgptr); |
799 | data_addr = sg->len & AHD_SG_HIGH_ADDR_MASK0x7F000000; |
800 | data_addr <<= 8; |
801 | data_addr |= sg->addr; |
802 | data_len = sg->len; |
803 | sgptr += sizeof(*sg); |
804 | } |
805 | |
806 | /* |
807 | * Update residual information. |
808 | */ |
809 | ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, data_len >> 24)(((ahd)->tags[(0x180 +3) >> 8])->write_1(((ahd)-> bshs[(0x180 +3) >> 8]), ((0x180 +3) & 0xFF), (data_len >> 24))); |
810 | ahd_outl(ahd, SCB_RESIDUAL_SGPTR0x184, sgptr); |
811 | |
812 | /* |
813 | * Load the S/G. |
814 | */ |
815 | if (data_len & AHD_DMA_LAST_SEG0x80000000) { |
816 | sgptr |= LAST_SEG0x02; |
817 | ahd_outb(ahd, SG_STATE, 0)(((ahd)->tags[(0xa6) >> 8])->write_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF), (0))); |
818 | } |
819 | ahd_outq(ahd, HADDR0x70, data_addr); |
820 | ahd_outl(ahd, HCNT0x78, data_len & AHD_SG_LEN_MASK0x00FFFFFF); |
821 | ahd_outb(ahd, SG_CACHE_PRE, sgptr & 0xFF)(((ahd)->tags[(0x1b) >> 8])->write_1(((ahd)->bshs [(0x1b) >> 8]), ((0x1b) & 0xFF), (sgptr & 0xFF) )); |
822 | |
823 | /* |
824 | * Advertise the segment to the hardware. |
825 | */ |
826 | dfcntrl = ahd_inb(ahd, DFCNTRL)(((ahd)->tags[(0x19) >> 8])->read_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF)))|PRELOADEN0x80|HDMAEN0x08; |
827 | if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) { |
828 | /* |
829 | * Use SCSIENWRDIS so that SCSIEN |
830 | * is never modified by this |
831 | * operation. |
832 | */ |
833 | dfcntrl |= SCSIENWRDIS0x40; |
834 | } |
835 | ahd_outb(ahd, DFCNTRL, dfcntrl)(((ahd)->tags[(0x19) >> 8])->write_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF), (dfcntrl))); |
836 | } |
837 | } else if ((ahd_inb(ahd, SG_CACHE_SHADOW)(((ahd)->tags[(0x1b) >> 8])->read_1(((ahd)->bshs [(0x1b) >> 8]), ((0x1b) & 0xFF))) & LAST_SEG_DONE0x01) != 0) { |
838 | |
839 | /* |
840 | * Transfer completed to the end of SG list |
841 | * and has flushed to the host. |
842 | */ |
843 | ahd_outb(ahd, SCB_SGPTR,(((ahd)->tags[(0x1a4) >> 8])->write_1(((ahd)-> bshs[(0x1a4) >> 8]), ((0x1a4) & 0xFF), (ahd_inb_scbram (ahd, 0x1a4) | 0x01))) |
844 | ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL)(((ahd)->tags[(0x1a4) >> 8])->write_1(((ahd)-> bshs[(0x1a4) >> 8]), ((0x1a4) & 0xFF), (ahd_inb_scbram (ahd, 0x1a4) | 0x01))); |
845 | goto clrchn; |
846 | } else if ((ahd_inb(ahd, DFSTATUS)(((ahd)->tags[(0x1a) >> 8])->read_1(((ahd)->bshs [(0x1a) >> 8]), ((0x1a) & 0xFF))) & FIFOEMP0x01) != 0) { |
847 | clrchn: |
848 | /* |
849 | * Clear any handler for this FIFO, decrement |
850 | * the FIFO use count for the SCB, and release |
851 | * the FIFO. |
852 | */ |
853 | ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR)(((ahd)->tags[(0xf8 + 1) >> 8])->write_1(((ahd)-> bshs[(0xf8 + 1) >> 8]), ((0xf8 + 1) & 0xFF), (0x80) )); |
854 | ahd_outb(ahd, SCB_FIFO_USE_COUNT,(((ahd)->tags[(0x190) >> 8])->write_1(((ahd)-> bshs[(0x190) >> 8]), ((0x190) & 0xFF), (ahd_inb_scbram (ahd, 0x190) - 1))) |
855 | ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1)(((ahd)->tags[(0x190) >> 8])->write_1(((ahd)-> bshs[(0x190) >> 8]), ((0x190) & 0xFF), (ahd_inb_scbram (ahd, 0x190) - 1))); |
856 | ahd_outb(ahd, DFFSXFRCTL, CLRCHN)(((ahd)->tags[(0x5a) >> 8])->write_1(((ahd)->bshs [(0x5a) >> 8]), ((0x5a) & 0xFF), (0x02))); |
857 | } |
858 | } |
859 | |
860 | /* |
861 | * Look for entries in the QoutFIFO that have completed. |
862 | * The valid_tag completion field indicates the validity |
863 | * of the entry - the valid value toggles each time through |
864 | * the queue. We use the sg_status field in the completion |
865 | * entry to avoid referencing the hscb if the completion |
866 | * occurred with no errors and no residual. sg_status is |
867 | * a copy of the first byte (little endian) of the sgptr |
868 | * hscb field. |
869 | */ |
870 | void |
871 | ahd_run_qoutfifo(struct ahd_softc *ahd) |
872 | { |
873 | struct ahd_completion *completion; |
874 | struct scb *scb; |
875 | u_int scb_index; |
876 | |
877 | if ((ahd->flags & AHD_RUNNING_QOUTFIFO) != 0) |
878 | panic("ahd_run_qoutfifo recursion"); |
879 | ahd->flags |= AHD_RUNNING_QOUTFIFO; |
880 | ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD0x02); |
881 | for (;;) { |
882 | completion = &ahd->qoutfifo[ahd->qoutfifonext]; |
883 | |
884 | if (completion->valid_tag != ahd->qoutfifonext_valid_tag) |
885 | break; |
886 | |
887 | scb_index = aic_le16toh(completion->tag)((__uint16_t)(completion->tag)); |
888 | scb = ahd_lookup_scb(ahd, scb_index); |
889 | if (scb == NULL((void *)0)) { |
890 | printf("%s: WARNING no command for scb %d " |
891 | "(cmdcmplt)\nQOUTPOS = %d\n", |
892 | ahd_name(ahd), scb_index, |
893 | ahd->qoutfifonext); |
894 | ahd_dump_card_state(ahd); |
895 | } else if ((completion->sg_status & SG_STATUS_VALID0x04) != 0) { |
896 | ahd_handle_scb_status(ahd, scb); |
897 | } else { |
898 | ahd_done(ahd, scb); |
899 | } |
900 | |
901 | ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE512-1); |
902 | if (ahd->qoutfifonext == 0) |
903 | ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID0x80; |
904 | } |
905 | ahd->flags &= ~AHD_RUNNING_QOUTFIFO; |
906 | } |
907 | |
908 | /************************* Interrupt Handling *********************************/ |
909 | void |
910 | ahd_handle_hwerrint(struct ahd_softc *ahd) |
911 | { |
912 | /* |
913 | * Some catastrophic hardware error has occurred. |
914 | * Print it for the user and disable the controller. |
915 | */ |
916 | int i; |
917 | int error; |
918 | |
919 | error = ahd_inb(ahd, ERROR)(((ahd)->tags[(0x04) >> 8])->read_1(((ahd)->bshs [(0x04) >> 8]), ((0x04) & 0xFF))); |
920 | for (i = 0; i < num_errors; i++) { |
921 | if ((error & ahd_hard_errors[i].errno) != 0) |
922 | printf("%s: hwerrint, %s\n", |
923 | ahd_name(ahd), ahd_hard_errors[i].errmesg); |
924 | } |
925 | |
926 | ahd_dump_card_state(ahd); |
927 | panic("BRKADRINT"); |
928 | |
929 | /* Tell everyone that this HBA is no longer available */ |
930 | ahd_abort_scbs(ahd, CAM_TARGET_WILDCARD((u_int)~0), ALL_CHANNELS'\0', |
931 | CAM_LUN_WILDCARD-1, SCB_LIST_NULL0xFF00, ROLE_UNKNOWN, |
932 | CAM_NO_HBA); |
933 | |
934 | /* Tell the system that this controller has gone away. */ |
935 | ahd_free(ahd); |
936 | } |
937 | |
938 | void |
939 | ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) |
940 | { |
941 | u_int seqintcode; |
942 | |
943 | /* |
944 | * Save the sequencer interrupt code and clear the SEQINT |
945 | * bit. We will unpause the sequencer, if appropriate, |
946 | * after servicing the request. |
947 | */ |
948 | seqintcode = ahd_inb(ahd, SEQINTCODE)(((ahd)->tags[(0x02) >> 8])->read_1(((ahd)->bshs [(0x02) >> 8]), ((0x02) & 0xFF))); |
949 | ahd_outb(ahd, CLRINT, CLRSEQINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x04))); |
950 | if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) { |
951 | /* |
952 | * Unpause the sequencer and let it clear |
953 | * SEQINT by writing NO_SEQINT to it. This |
954 | * will cause the sequencer to be paused again, |
955 | * which is the expected state of this routine. |
956 | */ |
957 | ahd_unpause(ahd); |
958 | while (!ahd_is_paused(ahd)) |
959 | ; |
960 | ahd_outb(ahd, CLRINT, CLRSEQINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x04))); |
961 | } |
962 | ahd_update_modes(ahd); |
963 | #ifdef AHD_DEBUG |
964 | if ((ahd_debug & AHD_SHOW_MISC) != 0) |
965 | printf("%s: Handle Seqint Called for code %d\n", |
966 | ahd_name(ahd), seqintcode); |
967 | #endif |
968 | switch (seqintcode) { |
969 | case ENTERING_NONPACK0x12: |
970 | { |
971 | struct scb *scb; |
972 | u_int scbid; |
973 | |
974 | AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),ahd_assert_modes(ahd, ~((0x01 << (AHD_MODE_UNKNOWN))|(0x01 << (AHD_MODE_CFG))), ~((0x01 << (AHD_MODE_UNKNOWN ))|(0x01 << (AHD_MODE_CFG))), "/usr/src/sys/dev/ic/aic79xx.c" , 975); |
975 | ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK))ahd_assert_modes(ahd, ~((0x01 << (AHD_MODE_UNKNOWN))|(0x01 << (AHD_MODE_CFG))), ~((0x01 << (AHD_MODE_UNKNOWN ))|(0x01 << (AHD_MODE_CFG))), "/usr/src/sys/dev/ic/aic79xx.c" , 975);; |
976 | scbid = ahd_get_scbptr(ahd); |
977 | scb = ahd_lookup_scb(ahd, scbid); |
978 | if (scb == NULL((void *)0)) { |
979 | /* |
980 | * Somehow need to know if this |
981 | * is from a selection or reselection. |
982 | * From that, we can determine target |
983 | * ID so we at least have an I_T nexus. |
984 | */ |
985 | } else { |
986 | ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid)(((ahd)->tags[(0x13a) >> 8])->write_1(((ahd)-> bshs[(0x13a) >> 8]), ((0x13a) & 0xFF), (scb->hscb ->scsiid))); |
987 | ahd_outb(ahd, SAVED_LUN, scb->hscb->lun)(((ahd)->tags[(0x13b) >> 8])->write_1(((ahd)-> bshs[(0x13b) >> 8]), ((0x13b) & 0xFF), (scb->hscb ->lun))); |
988 | ahd_outb(ahd, SEQ_FLAGS, 0x0)(((ahd)->tags[(0x139) >> 8])->write_1(((ahd)-> bshs[(0x139) >> 8]), ((0x139) & 0xFF), (0x0))); |
989 | } |
990 | if ((ahd_inb(ahd, LQISTAT2)(((ahd)->tags[(0x52) >> 8])->read_1(((ahd)->bshs [(0x52) >> 8]), ((0x52) & 0xFF))) & LQIPHASE_OUTPKT0x40) != 0 |
991 | && (ahd_inb(ahd, SCSISIGO)(((ahd)->tags[(0x40) >> 8])->read_1(((ahd)->bshs [(0x40) >> 8]), ((0x40) & 0xFF))) & ATNO0x10) != 0) { |
992 | /* |
993 | * Phase change after read stream with |
994 | * CRC error with P0 asserted on last |
995 | * packet. |
996 | */ |
997 | #ifdef AHD_DEBUG |
998 | if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) |
999 | printf("%s: Assuming LQIPHASE_NLQ with " |
1000 | "P0 assertion\n", ahd_name(ahd)); |
1001 | #endif |
1002 | } |
1003 | #ifdef AHD_DEBUG |
1004 | if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) |
1005 | printf("%s: Entering NONPACK\n", ahd_name(ahd)); |
1006 | #endif |
1007 | break; |
1008 | } |
1009 | case INVALID_SEQINT0x0e: |
1010 | printf("%s: Invalid Sequencer interrupt occurred.\n", |
1011 | ahd_name(ahd)); |
1012 | ahd_dump_card_state(ahd); |
1013 | ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE1); |
1014 | break; |
1015 | case STATUS_OVERRUN0x10: |
1016 | { |
1017 | struct scb *scb; |
1018 | u_int scbid; |
1019 | |
1020 | scbid = ahd_get_scbptr(ahd); |
1021 | scb = ahd_lookup_scb(ahd, scbid); |
1022 | if (scb != NULL((void *)0)) |
1023 | ahd_print_path(ahd, scb); |
1024 | else |
1025 | printf("%s: ", ahd_name(ahd)); |
1026 | printf("SCB %d Packetized Status Overrun", scbid); |
1027 | ahd_dump_card_state(ahd); |
1028 | ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE1); |
1029 | break; |
1030 | } |
1031 | case CFG4ISTAT_INTR0x0f: |
1032 | { |
1033 | struct scb *scb; |
1034 | u_int scbid; |
1035 | |
1036 | scbid = ahd_get_scbptr(ahd); |
1037 | scb = ahd_lookup_scb(ahd, scbid); |
1038 | if (scb == NULL((void *)0)) { |
1039 | ahd_dump_card_state(ahd); |
1040 | printf("CFG4ISTAT: Free SCB %d referenced", scbid); |
1041 | panic("For safety"); |
1042 | } |
1043 | ahd_outq(ahd, HADDR0x70, scb->sense_busaddr); |
1044 | ahd_outw(ahd, HCNT0x78, AHD_SENSE_BUFSIZE0x100); |
1045 | ahd_outb(ahd, HCNT + 2, 0)(((ahd)->tags[(0x78 + 2) >> 8])->write_1(((ahd)-> bshs[(0x78 + 2) >> 8]), ((0x78 + 2) & 0xFF), (0))); |
1046 | ahd_outb(ahd, SG_CACHE_PRE, SG_LAST_SEG)(((ahd)->tags[(0x1b) >> 8])->write_1(((ahd)->bshs [(0x1b) >> 8]), ((0x1b) & 0xFF), (0x80))); |
1047 | ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN)(((ahd)->tags[(0x19) >> 8])->write_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF), (0x80|0x20|0x08))); |
1048 | break; |
1049 | } |
1050 | case ILLEGAL_PHASE0x0d: |
1051 | { |
1052 | u_int bus_phase; |
1053 | |
1054 | bus_phase = ahd_inb(ahd, SCSISIGI)(((ahd)->tags[(0x41) >> 8])->read_1(((ahd)->bshs [(0x41) >> 8]), ((0x41) & 0xFF))) & PHASE_MASK0xe0; |
1055 | printf("%s: ILLEGAL_PHASE 0x%x\n", |
1056 | ahd_name(ahd), bus_phase); |
1057 | |
1058 | switch (bus_phase) { |
1059 | case P_DATAOUT0x00: |
1060 | case P_DATAIN0x40: |
1061 | case P_DATAOUT_DT0x20: |
1062 | case P_DATAIN_DT0x60: |
1063 | case P_MESGOUT0xa0: |
1064 | case P_STATUS0xc0: |
1065 | case P_MESGIN0xe0: |
1066 | ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE1); |
1067 | printf("%s: Issued Bus Reset.\n", ahd_name(ahd)); |
1068 | break; |
1069 | case P_COMMAND0x80: |
1070 | { |
1071 | struct ahd_devinfo devinfo; |
1072 | struct scb *scb; |
1073 | struct ahd_initiator_tinfo *targ_info; |
1074 | struct ahd_tmode_tstate *tstate; |
1075 | u_int scbid; |
1076 | |
1077 | /* |
1078 | * If a target takes us into the command phase |
1079 | * assume that it has been externally reset and |
1080 | * has thus lost our previous packetized negotiation |
1081 | * agreement. Since we have not sent an identify |
1082 | * message and may not have fully qualified the |
1083 | * connection, we change our command to TUR, assert |
1084 | * ATN and ABORT the task when we go to message in |
1085 | * phase. The OSM will see the REQUEUE_REQUEST |
1086 | * status and retry the command. |
1087 | */ |
1088 | scbid = ahd_get_scbptr(ahd); |
1089 | scb = ahd_lookup_scb(ahd, scbid); |
1090 | if (scb == NULL((void *)0)) { |
1091 | printf("Invalid phase with no valid SCB. " |
1092 | "Resetting bus.\n"); |
1093 | ahd_reset_channel(ahd, 'A', |
1094 | /*Initiate Reset*/TRUE1); |
1095 | break; |
1096 | } |
1097 | ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb)(((scb)->hscb->scsiid) & 0x0f), |
1098 | SCB_GET_TARGET(ahd, scb)((((scb)->hscb->scsiid) & 0xf0) >> 0x04), |
1099 | SCB_GET_LUN(scb)((scb)->hscb->lun), |
1100 | SCB_GET_CHANNEL(ahd, scb)('A'), |
1101 | ROLE_INITIATOR); |
1102 | targ_info = ahd_fetch_transinfo(ahd, |
1103 | devinfo.channel, |
1104 | devinfo.our_scsiid, |
1105 | devinfo.target, |
1106 | &tstate); |
1107 | ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT0x00, |
1108 | AHD_TRANS_ACTIVE0x03, /*paused*/TRUE1); |
1109 | ahd_set_syncrate(ahd, &devinfo, /*period*/0, |
1110 | /*offset*/0, /*ppr_options*/0, |
1111 | AHD_TRANS_ACTIVE0x03, /*paused*/TRUE1); |
1112 | ahd_outb(ahd, SCB_CDB_STORE, 0)(((ahd)->tags[(0x180) >> 8])->write_1(((ahd)-> bshs[(0x180) >> 8]), ((0x180) & 0xFF), (0))); |
1113 | ahd_outb(ahd, SCB_CDB_STORE+1, 0)(((ahd)->tags[(0x180 +1) >> 8])->write_1(((ahd)-> bshs[(0x180 +1) >> 8]), ((0x180 +1) & 0xFF), (0))); |
1114 | ahd_outb(ahd, SCB_CDB_STORE+2, 0)(((ahd)->tags[(0x180 +2) >> 8])->write_1(((ahd)-> bshs[(0x180 +2) >> 8]), ((0x180 +2) & 0xFF), (0))); |
1115 | ahd_outb(ahd, SCB_CDB_STORE+3, 0)(((ahd)->tags[(0x180 +3) >> 8])->write_1(((ahd)-> bshs[(0x180 +3) >> 8]), ((0x180 +3) & 0xFF), (0))); |
1116 | ahd_outb(ahd, SCB_CDB_STORE+4, 0)(((ahd)->tags[(0x180 +4) >> 8])->write_1(((ahd)-> bshs[(0x180 +4) >> 8]), ((0x180 +4) & 0xFF), (0))); |
1117 | ahd_outb(ahd, SCB_CDB_STORE+5, 0)(((ahd)->tags[(0x180 +5) >> 8])->write_1(((ahd)-> bshs[(0x180 +5) >> 8]), ((0x180 +5) & 0xFF), (0))); |
1118 | ahd_outb(ahd, SCB_CDB_LEN, 6)(((ahd)->tags[(0x196) >> 8])->write_1(((ahd)-> bshs[(0x196) >> 8]), ((0x196) & 0xFF), (6))); |
1119 | scb->hscb->control &= ~(TAG_ENB0x20|SCB_TAG_TYPE0x03); |
1120 | scb->hscb->control |= MK_MESSAGE0x10; |
1121 | ahd_outb(ahd, SCB_CONTROL, scb->hscb->control)(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (scb->hscb ->control))); |
1122 | ahd_outb(ahd, MSG_OUT, HOST_MSG)(((ahd)->tags[(0x137) >> 8])->write_1(((ahd)-> bshs[(0x137) >> 8]), ((0x137) & 0xFF), (0xff))); |
1123 | ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid)(((ahd)->tags[(0x13a) >> 8])->write_1(((ahd)-> bshs[(0x13a) >> 8]), ((0x13a) & 0xFF), (scb->hscb ->scsiid))); |
1124 | /* |
1125 | * The lun is 0, regardless of the SCB's lun |
1126 | * as we have not sent an identify message. |
1127 | */ |
1128 | ahd_outb(ahd, SAVED_LUN, 0)(((ahd)->tags[(0x13b) >> 8])->write_1(((ahd)-> bshs[(0x13b) >> 8]), ((0x13b) & 0xFF), (0))); |
1129 | ahd_outb(ahd, SEQ_FLAGS, 0)(((ahd)->tags[(0x139) >> 8])->write_1(((ahd)-> bshs[(0x139) >> 8]), ((0x139) & 0xFF), (0))); |
1130 | ahd_assert_atn(ahd); |
1131 | scb->flags &= ~SCB_PACKETIZED; |
1132 | scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT; |
1133 | ahd_freeze_devq(ahd, scb); |
1134 | aic_set_transaction_status(scb, CAM_REQUEUE_REQ)(scb)->xs->error = (CAM_REQUEUE_REQ); |
1135 | aic_freeze_scb(scb); |
1136 | |
1137 | /* |
1138 | * Allow the sequencer to continue with |
1139 | * non-pack processing. |
1140 | */ |
1141 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
1142 | ahd_outb(ahd, CLRLQOINT1, CLRLQOPHACHGINPKT)(((ahd)->tags[(0x55) >> 8])->write_1(((ahd)->bshs [(0x55) >> 8]), ((0x55) & 0xFF), (0x01))); |
1143 | if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) { |
1144 | ahd_outb(ahd, CLRLQOINT1, 0)(((ahd)->tags[(0x55) >> 8])->write_1(((ahd)->bshs [(0x55) >> 8]), ((0x55) & 0xFF), (0))); |
1145 | } |
1146 | #ifdef AHD_DEBUG |
1147 | if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { |
1148 | ahd_print_path(ahd, scb); |
1149 | printf("Unexpected command phase from " |
1150 | "packetized target\n"); |
1151 | } |
1152 | #endif |
1153 | break; |
1154 | } |
1155 | } |
1156 | break; |
1157 | } |
1158 | case CFG4OVERRUN0x11: |
1159 | { |
1160 | struct scb *scb; |
1161 | u_int scb_index; |
1162 | |
1163 | #ifdef AHD_DEBUG |
1164 | if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { |
1165 | printf("%s: CFG4OVERRUN mode = %x\n", ahd_name(ahd), |
1166 | ahd_inb(ahd, MODE_PTR)(((ahd)->tags[(0x00) >> 8])->read_1(((ahd)->bshs [(0x00) >> 8]), ((0x00) & 0xFF)))); |
1167 | } |
1168 | #endif |
1169 | scb_index = ahd_get_scbptr(ahd); |
1170 | scb = ahd_lookup_scb(ahd, scb_index); |
1171 | if (scb == NULL((void *)0)) { |
1172 | /* |
1173 | * Attempt to transfer to an SCB that is |
1174 | * not outstanding. |
1175 | */ |
1176 | ahd_assert_atn(ahd); |
1177 | ahd_outb(ahd, MSG_OUT, HOST_MSG)(((ahd)->tags[(0x137) >> 8])->write_1(((ahd)-> bshs[(0x137) >> 8]), ((0x137) & 0xFF), (0xff))); |
1178 | ahd->msgout_buf[0] = MSG_ABORT_TASK0x0d; |
1179 | ahd->msgout_len = 1; |
1180 | ahd->msgout_index = 0; |
1181 | ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT; |
1182 | /* |
1183 | * Clear status received flag to prevent any |
1184 | * attempt to complete this bogus SCB. |
1185 | */ |
1186 | ahd_outb(ahd, SCB_CONTROL,(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (ahd_inb_scbram (ahd, 0x192) & ~0x08))) |
1187 | ahd_inb_scbram(ahd, SCB_CONTROL)(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (ahd_inb_scbram (ahd, 0x192) & ~0x08))) |
1188 | & ~STATUS_RCVD)(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (ahd_inb_scbram (ahd, 0x192) & ~0x08))); |
1189 | } |
1190 | break; |
1191 | } |
1192 | case DUMP_CARD_STATE0x0c: |
1193 | { |
1194 | ahd_dump_card_state(ahd); |
1195 | break; |
1196 | } |
1197 | case PDATA_REINIT0x06: |
1198 | { |
1199 | #ifdef AHD_DEBUG |
1200 | if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { |
1201 | printf("%s: PDATA_REINIT - DFCNTRL = 0x%x " |
1202 | "SG_CACHE_SHADOW = 0x%x\n", |
1203 | ahd_name(ahd), ahd_inb(ahd, DFCNTRL)(((ahd)->tags[(0x19) >> 8])->read_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF))), |
1204 | ahd_inb(ahd, SG_CACHE_SHADOW)(((ahd)->tags[(0x1b) >> 8])->read_1(((ahd)->bshs [(0x1b) >> 8]), ((0x1b) & 0xFF)))); |
1205 | } |
1206 | #endif |
1207 | ahd_reinitialize_dataptrs(ahd); |
1208 | break; |
1209 | } |
1210 | case HOST_MSG_LOOP0x07: |
1211 | { |
1212 | struct ahd_devinfo devinfo; |
1213 | |
1214 | /* |
1215 | * The sequencer has encountered a message phase |
1216 | * that requires host assistance for completion. |
1217 | * While handling the message phase(s), we will be |
1218 | * notified by the sequencer after each byte is |
1219 | * transferred so we can track bus phase changes. |
1220 | * |
1221 | * If this is the first time we've seen a HOST_MSG_LOOP |
1222 | * interrupt, initialize the state of the host message |
1223 | * loop. |
1224 | */ |
1225 | ahd_fetch_devinfo(ahd, &devinfo); |
1226 | if (ahd->msg_type == MSG_TYPE_NONE) { |
1227 | struct scb *scb; |
1228 | u_int scb_index; |
1229 | u_int bus_phase; |
1230 | |
1231 | bus_phase = ahd_inb(ahd, SCSISIGI)(((ahd)->tags[(0x41) >> 8])->read_1(((ahd)->bshs [(0x41) >> 8]), ((0x41) & 0xFF))) & PHASE_MASK0xe0; |
1232 | if (bus_phase != P_MESGIN0xe0 |
1233 | && bus_phase != P_MESGOUT0xa0) { |
1234 | printf("ahd_intr: HOST_MSG_LOOP bad " |
1235 | "phase 0x%x\n", bus_phase); |
1236 | /* |
1237 | * Probably transitioned to bus free before |
1238 | * we got here. Just punt the message. |
1239 | */ |
1240 | ahd_dump_card_state(ahd); |
1241 | ahd_clear_intstat(ahd); |
1242 | ahd_restart(ahd); |
1243 | return; |
1244 | } |
1245 | |
1246 | scb_index = ahd_get_scbptr(ahd); |
1247 | scb = ahd_lookup_scb(ahd, scb_index); |
1248 | if (devinfo.role == ROLE_INITIATOR) { |
1249 | if (bus_phase == P_MESGOUT0xa0) |
1250 | ahd_setup_initiator_msgout(ahd, |
1251 | &devinfo, |
1252 | scb); |
1253 | else { |
1254 | ahd->msg_type = |
1255 | MSG_TYPE_INITIATOR_MSGIN; |
1256 | ahd->msgin_index = 0; |
1257 | } |
1258 | } |
1259 | #if AHD_TARGET_MODE |
1260 | else { |
1261 | if (bus_phase == P_MESGOUT0xa0) { |
1262 | ahd->msg_type = |
1263 | MSG_TYPE_TARGET_MSGOUT; |
1264 | ahd->msgin_index = 0; |
1265 | } |
1266 | else |
1267 | ahd_setup_target_msgin(ahd, |
1268 | &devinfo, |
1269 | scb); |
1270 | } |
1271 | #endif |
1272 | } |
1273 | |
1274 | ahd_handle_message_phase(ahd); |
1275 | break; |
1276 | } |
1277 | case NO_MATCH0x04: |
1278 | { |
1279 | /* Ensure we don't leave the selection hardware on */ |
1280 | AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK)ahd_assert_modes(ahd, (0x01 << (AHD_MODE_SCSI)), (0x01 << (AHD_MODE_SCSI)), "/usr/src/sys/dev/ic/aic79xx.c", 1280);; |
1281 | ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO)(((ahd)->tags[(0x3a) >> 8])->write_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF), ((((ahd)->tags[ (0x3a) >> 8])->read_1(((ahd)->bshs[(0x3a) >> 8]), ((0x3a) & 0xFF))) & ~0x40))); |
1282 | |
1283 | printf("%s:%c:%d: no active SCB for reconnecting " |
1284 | "target - issuing BUS DEVICE RESET\n", |
1285 | ahd_name(ahd), 'A', ahd_inb(ahd, SELID)(((ahd)->tags[(0x49) >> 8])->read_1(((ahd)->bshs [(0x49) >> 8]), ((0x49) & 0xFF))) >> 4); |
1286 | printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, " |
1287 | "REG0 == 0x%x ACCUM = 0x%x\n", |
1288 | ahd_inb(ahd, SAVED_SCSIID)(((ahd)->tags[(0x13a) >> 8])->read_1(((ahd)->bshs [(0x13a) >> 8]), ((0x13a) & 0xFF))), ahd_inb(ahd, SAVED_LUN)(((ahd)->tags[(0x13b) >> 8])->read_1(((ahd)->bshs [(0x13b) >> 8]), ((0x13b) & 0xFF))), |
1289 | ahd_inw(ahd, REG00xa0), ahd_inb(ahd, ACCUM)(((ahd)->tags[(0xe0) >> 8])->read_1(((ahd)->bshs [(0xe0) >> 8]), ((0xe0) & 0xFF)))); |
1290 | printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, " |
1291 | "SINDEX == 0x%x\n", |
1292 | ahd_inb(ahd, SEQ_FLAGS)(((ahd)->tags[(0x139) >> 8])->read_1(((ahd)->bshs [(0x139) >> 8]), ((0x139) & 0xFF))), ahd_get_scbptr(ahd), |
1293 | ahd_find_busy_tcl(ahd, |
1294 | BUILD_TCL(ahd_inb(ahd, SAVED_SCSIID),(((((ahd)->tags[(0x13b) >> 8])->read_1(((ahd)-> bshs[(0x13b) >> 8]), ((0x13b) & 0xFF)))) | ((((((ahd )->tags[(0x13a) >> 8])->read_1(((ahd)->bshs[(0x13a ) >> 8]), ((0x13a) & 0xFF)))) & 0xf0) << 4 )) |
1295 | ahd_inb(ahd, SAVED_LUN))(((((ahd)->tags[(0x13b) >> 8])->read_1(((ahd)-> bshs[(0x13b) >> 8]), ((0x13b) & 0xFF)))) | ((((((ahd )->tags[(0x13a) >> 8])->read_1(((ahd)->bshs[(0x13a ) >> 8]), ((0x13a) & 0xFF)))) & 0xf0) << 4 ))), |
1296 | ahd_inw(ahd, SINDEX0xe2)); |
1297 | printf("SELID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, " |
1298 | "SCB_CONTROL == 0x%x\n", |
1299 | ahd_inb(ahd, SELID)(((ahd)->tags[(0x49) >> 8])->read_1(((ahd)->bshs [(0x49) >> 8]), ((0x49) & 0xFF))), ahd_inb_scbram(ahd, SCB_SCSIID0x193), |
1300 | ahd_inb_scbram(ahd, SCB_LUN0x194), |
1301 | ahd_inb_scbram(ahd, SCB_CONTROL0x192)); |
1302 | printf("SCSIBUS[0] == 0x%x, SCSISIGI == 0x%x\n", |
1303 | ahd_inb(ahd, SCSIBUS)(((ahd)->tags[(0x46) >> 8])->read_1(((ahd)->bshs [(0x46) >> 8]), ((0x46) & 0xFF))), ahd_inb(ahd, SCSISIGI)(((ahd)->tags[(0x41) >> 8])->read_1(((ahd)->bshs [(0x41) >> 8]), ((0x41) & 0xFF)))); |
1304 | printf("SXFRCTL0 == 0x%x\n", ahd_inb(ahd, SXFRCTL0)(((ahd)->tags[(0x3c) >> 8])->read_1(((ahd)->bshs [(0x3c) >> 8]), ((0x3c) & 0xFF)))); |
1305 | printf("SEQCTL0 == 0x%x\n", ahd_inb(ahd, SEQCTL0)(((ahd)->tags[(0xd6) >> 8])->read_1(((ahd)->bshs [(0xd6) >> 8]), ((0xd6) & 0xFF)))); |
1306 | ahd_dump_card_state(ahd); |
1307 | ahd->msgout_buf[0] = MSG_BUS_DEV_RESET0x0c; |
1308 | ahd->msgout_len = 1; |
1309 | ahd->msgout_index = 0; |
1310 | ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT; |
1311 | ahd_outb(ahd, MSG_OUT, HOST_MSG)(((ahd)->tags[(0x137) >> 8])->write_1(((ahd)-> bshs[(0x137) >> 8]), ((0x137) & 0xFF), (0xff))); |
1312 | ahd_assert_atn(ahd); |
1313 | break; |
1314 | } |
1315 | case PROTO_VIOLATION0x03: |
1316 | { |
1317 | ahd_handle_proto_violation(ahd); |
1318 | break; |
1319 | } |
1320 | case IGN_WIDE_RES0x05: |
1321 | { |
1322 | struct ahd_devinfo devinfo; |
1323 | |
1324 | ahd_fetch_devinfo(ahd, &devinfo); |
1325 | ahd_handle_ign_wide_residue(ahd, &devinfo); |
1326 | break; |
1327 | } |
1328 | case BAD_PHASE0x01: |
1329 | { |
1330 | u_int lastphase; |
1331 | |
1332 | lastphase = ahd_inb(ahd, LASTPHASE)(((ahd)->tags[(0x13c) >> 8])->read_1(((ahd)->bshs [(0x13c) >> 8]), ((0x13c) & 0xFF))); |
1333 | printf("%s:%c:%d: unknown scsi bus phase %x, " |
1334 | "lastphase = 0x%x. Attempting to continue\n", |
1335 | ahd_name(ahd), 'A', |
1336 | SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID))((((((ahd)->tags[(0x13a) >> 8])->read_1(((ahd)-> bshs[(0x13a) >> 8]), ((0x13a) & 0xFF)))) & 0xf0 ) >> 0x04), |
1337 | lastphase, ahd_inb(ahd, SCSISIGI)(((ahd)->tags[(0x41) >> 8])->read_1(((ahd)->bshs [(0x41) >> 8]), ((0x41) & 0xFF)))); |
1338 | break; |
1339 | } |
1340 | case MISSED_BUSFREE0x0b: |
1341 | { |
1342 | u_int lastphase; |
1343 | |
1344 | lastphase = ahd_inb(ahd, LASTPHASE)(((ahd)->tags[(0x13c) >> 8])->read_1(((ahd)->bshs [(0x13c) >> 8]), ((0x13c) & 0xFF))); |
1345 | printf("%s:%c:%d: Missed busfree. " |
1346 | "Lastphase = 0x%x, Curphase = 0x%x\n", |
1347 | ahd_name(ahd), 'A', |
1348 | SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID))((((((ahd)->tags[(0x13a) >> 8])->read_1(((ahd)-> bshs[(0x13a) >> 8]), ((0x13a) & 0xFF)))) & 0xf0 ) >> 0x04), |
1349 | lastphase, ahd_inb(ahd, SCSISIGI)(((ahd)->tags[(0x41) >> 8])->read_1(((ahd)->bshs [(0x41) >> 8]), ((0x41) & 0xFF)))); |
1350 | ahd_restart(ahd); |
1351 | return; |
1352 | } |
1353 | case DATA_OVERRUN0x09: |
1354 | { |
1355 | /* |
1356 | * When the sequencer detects an overrun, it |
1357 | * places the controller in "BITBUCKET" mode |
1358 | * and allows the target to complete its transfer. |
1359 | * Unfortunately, none of the counters get updated |
1360 | * when the controller is in this mode, so we have |
1361 | * no way of knowing how large the overrun was. |
1362 | */ |
1363 | struct scb *scb; |
1364 | u_int scbindex; |
1365 | #ifdef AHD_DEBUG |
1366 | u_int lastphase; |
1367 | #endif |
1368 | |
1369 | scbindex = ahd_get_scbptr(ahd); |
1370 | scb = ahd_lookup_scb(ahd, scbindex); |
1371 | #ifdef AHD_DEBUG |
1372 | lastphase = ahd_inb(ahd, LASTPHASE)(((ahd)->tags[(0x13c) >> 8])->read_1(((ahd)->bshs [(0x13c) >> 8]), ((0x13c) & 0xFF))); |
1373 | if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { |
1374 | ahd_print_path(ahd, scb); |
1375 | printf("data overrun detected %s. Tag == 0x%x.\n", |
1376 | ahd_lookup_phase_entry(lastphase)->phasemsg, |
1377 | SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag))); |
1378 | ahd_print_path(ahd, scb); |
1379 | printf("%s seen Data Phase. Length = %d. " |
1380 | "NumSGs = %d.\n", |
1381 | ahd_inb(ahd, SEQ_FLAGS)(((ahd)->tags[(0x139) >> 8])->read_1(((ahd)->bshs [(0x139) >> 8]), ((0x139) & 0xFF))) & DPHASE0x20 |
1382 | ? "Have" : "Haven't", |
1383 | aic_get_transfer_length(scb)((scb)->xs->datalen), scb->sg_count); |
1384 | ahd_dump_sglist(scb); |
1385 | } |
1386 | #endif |
1387 | |
1388 | /* |
1389 | * Set this and it will take effect when the |
1390 | * target does a command complete. |
1391 | */ |
1392 | ahd_freeze_devq(ahd, scb); |
1393 | aic_set_transaction_status(scb, CAM_DATA_RUN_ERR)(scb)->xs->error = (CAM_DATA_RUN_ERR); |
1394 | aic_freeze_scb(scb); |
1395 | break; |
1396 | } |
1397 | case MKMSG_FAILED0x0a: |
1398 | { |
1399 | struct ahd_devinfo devinfo; |
1400 | struct scb *scb; |
1401 | u_int scbid; |
1402 | |
1403 | ahd_fetch_devinfo(ahd, &devinfo); |
1404 | printf("%s:%c:%d:%d: Attempt to issue message failed\n", |
1405 | ahd_name(ahd), devinfo.channel, devinfo.target, |
1406 | devinfo.lun); |
1407 | scbid = ahd_get_scbptr(ahd); |
1408 | scb = ahd_lookup_scb(ahd, scbid); |
1409 | if (scb != NULL((void *)0)) |
1410 | /* |
1411 | * Ensure that we didn't put a second instance of this |
1412 | * SCB into the QINFIFO. |
1413 | */ |
1414 | ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb)((((scb)->hscb->scsiid) & 0xf0) >> 0x04), |
1415 | SCB_GET_CHANNEL(ahd, scb)('A'), |
1416 | SCB_GET_LUN(scb)((scb)->hscb->lun), SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)), |
1417 | ROLE_INITIATOR, /*status*/0, |
1418 | SEARCH_REMOVE); |
1419 | ahd_outb(ahd, SCB_CONTROL,(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (ahd_inb_scbram (ahd, 0x192) & ~0x10))) |
1420 | ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE)(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (ahd_inb_scbram (ahd, 0x192) & ~0x10))); |
1421 | break; |
1422 | } |
1423 | case TASKMGMT_FUNC_COMPLETE0x13: |
1424 | { |
1425 | u_int scbid; |
1426 | struct scb *scb; |
1427 | |
1428 | scbid = ahd_get_scbptr(ahd); |
1429 | scb = ahd_lookup_scb(ahd, scbid); |
1430 | if (scb != NULL((void *)0)) { |
1431 | u_int lun; |
1432 | u_int tag; |
1433 | cam_status error; |
1434 | |
1435 | ahd_print_path(ahd, scb); |
1436 | printf("Task Management Func 0x%x Complete\n", |
1437 | scb->hscb->task_management); |
1438 | lun = CAM_LUN_WILDCARD-1; |
1439 | tag = SCB_LIST_NULL0xFF00; |
1440 | |
1441 | switch (scb->hscb->task_management) { |
1442 | case SIU_TASKMGMT_ABORT_TASK0x01: |
1443 | tag = SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)); |
1444 | case SIU_TASKMGMT_ABORT_TASK_SET0x02: |
1445 | case SIU_TASKMGMT_CLEAR_TASK_SET0x04: |
1446 | lun = scb->hscb->lun; |
1447 | error = CAM_REQ_ABORTED; |
1448 | ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb)((((scb)->hscb->scsiid) & 0xf0) >> 0x04), |
1449 | 'A', lun, tag, ROLE_INITIATOR, |
1450 | error); |
1451 | break; |
1452 | case SIU_TASKMGMT_LUN_RESET0x08: |
1453 | lun = scb->hscb->lun; |
1454 | case SIU_TASKMGMT_TARGET_RESET0x20: |
1455 | { |
1456 | struct ahd_devinfo devinfo; |
1457 | |
1458 | ahd_scb_devinfo(ahd, &devinfo, scb); |
1459 | error = CAM_BDR_SENT; |
1460 | ahd_handle_devreset(ahd, &devinfo, lun, |
1461 | CAM_BDR_SENT, |
1462 | lun != CAM_LUN_WILDCARD-1 |
1463 | ? "Lun Reset" |
1464 | : "Target Reset", |
1465 | /*verbose_level*/0); |
1466 | break; |
1467 | } |
1468 | default: |
1469 | panic("Unexpected TaskMgmt Func"); |
1470 | break; |
1471 | } |
1472 | } |
1473 | break; |
1474 | } |
1475 | case TASKMGMT_CMD_CMPLT_OKAY0x14: |
1476 | { |
1477 | u_int scbid; |
1478 | struct scb *scb; |
1479 | |
1480 | /* |
1481 | * An ABORT TASK TMF failed to be delivered before |
1482 | * the targeted command completed normally. |
1483 | */ |
1484 | scbid = ahd_get_scbptr(ahd); |
1485 | scb = ahd_lookup_scb(ahd, scbid); |
1486 | if (scb != NULL((void *)0)) { |
1487 | /* |
1488 | * Remove the second instance of this SCB from |
1489 | * the QINFIFO if it is still there. |
1490 | */ |
1491 | ahd_print_path(ahd, scb); |
1492 | printf("SCB completes before TMF\n"); |
1493 | /* |
1494 | * Handle losing the race. Wait until any |
1495 | * current selection completes. We will then |
1496 | * set the TMF back to zero in this SCB so that |
1497 | * the sequencer doesn't bother to issue another |
1498 | * sequencer interrupt for its completion. |
1499 | */ |
1500 | while ((ahd_inb(ahd, SCSISEQ0)(((ahd)->tags[(0x3a) >> 8])->read_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF))) & ENSELO0x40) != 0 |
1501 | && (ahd_inb(ahd, SSTAT0)(((ahd)->tags[(0x4b) >> 8])->read_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF))) & SELDO0x40) == 0 |
1502 | && (ahd_inb(ahd, SSTAT1)(((ahd)->tags[(0x4c) >> 8])->read_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF))) & SELTO0x80) == 0) |
1503 | ; |
1504 | ahd_outb(ahd, SCB_TASK_MANAGEMENT, 0)(((ahd)->tags[(0x197) >> 8])->write_1(((ahd)-> bshs[(0x197) >> 8]), ((0x197) & 0xFF), (0))); |
1505 | ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb)((((scb)->hscb->scsiid) & 0xf0) >> 0x04), |
1506 | SCB_GET_CHANNEL(ahd, scb)('A'), |
1507 | SCB_GET_LUN(scb)((scb)->hscb->lun), SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)), |
1508 | ROLE_INITIATOR, /*status*/0, |
1509 | SEARCH_REMOVE); |
1510 | } |
1511 | break; |
1512 | } |
1513 | case TRACEPOINT00x15: |
1514 | case TRACEPOINT10x16: |
1515 | case TRACEPOINT20x17: |
1516 | case TRACEPOINT30x18: |
1517 | printf("%s: Tracepoint %d\n", ahd_name(ahd), |
1518 | seqintcode - TRACEPOINT00x15); |
1519 | break; |
1520 | case NO_SEQINT0x00: |
1521 | break; |
1522 | case SAW_HWERR0x19: |
1523 | ahd_handle_hwerrint(ahd); |
1524 | break; |
1525 | default: |
1526 | printf("%s: Unexpected SEQINTCODE %d\n", ahd_name(ahd), |
1527 | seqintcode); |
1528 | break; |
1529 | } |
1530 | /* |
1531 | * The sequencer is paused immediately on |
1532 | * a SEQINT, so we should restart it when |
1533 | * we're done. |
1534 | */ |
1535 | ahd_unpause(ahd); |
1536 | } |
1537 | |
1538 | void |
1539 | ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) |
1540 | { |
1541 | struct scb *scb; |
1542 | u_int status0; |
1543 | u_int status3; |
1544 | u_int status; |
1545 | u_int lqistat1; |
1546 | u_int lqostat0; |
1547 | u_int scbid; |
1548 | u_int busfreetime; |
1549 | |
1550 | ahd_update_modes(ahd); |
1551 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
1552 | |
1553 | status3 = ahd_inb(ahd, SSTAT3)(((ahd)->tags[(0x53) >> 8])->read_1(((ahd)->bshs [(0x53) >> 8]), ((0x53) & 0xFF))) & (NTRAMPERR0x02|OSRAMPERR0x01); |
1554 | status0 = ahd_inb(ahd, SSTAT0)(((ahd)->tags[(0x4b) >> 8])->read_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF))) & (IOERR0x08|OVERRUN0x04|SELDI0x20|SELDO0x40); |
1555 | status = ahd_inb(ahd, SSTAT1)(((ahd)->tags[(0x4c) >> 8])->read_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF))) & (SELTO0x80|SCSIRSTI0x20|BUSFREE0x08|SCSIPERR0x04); |
1556 | lqistat1 = ahd_inb(ahd, LQISTAT1)(((ahd)->tags[(0x51) >> 8])->read_1(((ahd)->bshs [(0x51) >> 8]), ((0x51) & 0xFF))); |
1557 | lqostat0 = ahd_inb(ahd, LQOSTAT0)(((ahd)->tags[(0x54) >> 8])->read_1(((ahd)->bshs [(0x54) >> 8]), ((0x54) & 0xFF))); |
1558 | busfreetime = ahd_inb(ahd, SSTAT2)(((ahd)->tags[(0x4d) >> 8])->read_1(((ahd)->bshs [(0x4d) >> 8]), ((0x4d) & 0xFF))) & BUSFREETIME0xc0; |
1559 | if ((status0 & (SELDI0x20|SELDO0x40)) != 0) { |
1560 | u_int simode0; |
1561 | |
1562 | ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); |
1563 | simode0 = ahd_inb(ahd, SIMODE0)(((ahd)->tags[(0x4b) >> 8])->read_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF))); |
1564 | status0 &= simode0 & (IOERR0x08|OVERRUN0x04|SELDI0x20|SELDO0x40); |
1565 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
1566 | } |
1567 | scbid = ahd_get_scbptr(ahd); |
1568 | scb = ahd_lookup_scb(ahd, scbid); |
1569 | if (scb != NULL((void *)0) |
1570 | && (ahd_inb(ahd, SEQ_FLAGS)(((ahd)->tags[(0x139) >> 8])->read_1(((ahd)->bshs [(0x139) >> 8]), ((0x139) & 0xFF))) & NOT_IDENTIFIED0x80) != 0) |
1571 | scb = NULL((void *)0); |
1572 | |
1573 | if ((status0 & IOERR0x08) != 0) { |
1574 | u_int now_lvd; |
1575 | |
1576 | now_lvd = ahd_inb(ahd, SBLKCTL)(((ahd)->tags[(0x4a) >> 8])->read_1(((ahd)->bshs [(0x4a) >> 8]), ((0x4a) & 0xFF))) & ENAB400x08; |
1577 | printf("%s: Transceiver State Has Changed to %s mode\n", |
1578 | ahd_name(ahd), now_lvd ? "LVD" : "SE"); |
1579 | ahd_outb(ahd, CLRSINT0, CLRIOERR)(((ahd)->tags[(0x4b) >> 8])->write_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF), (0x08))); |
1580 | /* |
1581 | * A change in I/O mode is equivalent to a bus reset. |
1582 | */ |
1583 | ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE1); |
1584 | ahd_pause(ahd); |
1585 | ahd_setup_iocell_workaround(ahd); |
1586 | ahd_unpause(ahd); |
1587 | } else if ((status0 & OVERRUN0x04) != 0) { |
1588 | |
1589 | printf("%s: SCSI offset overrun detected. Resetting bus.\n", |
1590 | ahd_name(ahd)); |
1591 | ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE1); |
1592 | } else if ((status & SCSIRSTI0x20) != 0) { |
1593 | |
1594 | printf("%s: Someone reset channel A\n", ahd_name(ahd)); |
1595 | ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE0); |
1596 | } else if ((status & SCSIPERR0x04) != 0) { |
1597 | |
1598 | /* Make sure the sequencer is in a safe location. */ |
1599 | ahd_clear_critical_section(ahd); |
1600 | |
1601 | ahd_handle_transmission_error(ahd); |
1602 | } else if (lqostat0 != 0) { |
1603 | |
1604 | printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0); |
1605 | ahd_outb(ahd, CLRLQOINT0, lqostat0)(((ahd)->tags[(0x54) >> 8])->write_1(((ahd)->bshs [(0x54) >> 8]), ((0x54) & 0xFF), (lqostat0))); |
1606 | if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) |
1607 | ahd_outb(ahd, CLRLQOINT1, 0)(((ahd)->tags[(0x55) >> 8])->write_1(((ahd)->bshs [(0x55) >> 8]), ((0x55) & 0xFF), (0))); |
1608 | } else if ((status & SELTO0x80) != 0) { |
1609 | |
1610 | /* Stop the selection */ |
1611 | ahd_outb(ahd, SCSISEQ0, 0)(((ahd)->tags[(0x3a) >> 8])->write_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF), (0))); |
1612 | |
1613 | /* Make sure the sequencer is in a safe location. */ |
1614 | ahd_clear_critical_section(ahd); |
1615 | |
1616 | /* No more pending messages */ |
1617 | ahd_clear_msg_state(ahd); |
1618 | |
1619 | /* Clear interrupt state */ |
1620 | ahd_outb(ahd, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR)(((ahd)->tags[(0x4c) >> 8])->write_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF), (0x80|0x08|0x04))); |
1621 | |
1622 | /* |
1623 | * Although the driver does not care about the |
1624 | * 'Selection in Progress' status bit, the busy |
1625 | * LED does. SELINGO is only cleared by a successful |
1626 | * selection, so we must manually clear it to insure |
1627 | * the LED turns off just incase no future successful |
1628 | * selections occur (e.g. no devices on the bus). |
1629 | */ |
1630 | ahd_outb(ahd, CLRSINT0, CLRSELINGO)(((ahd)->tags[(0x4b) >> 8])->write_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF), (0x10))); |
1631 | |
1632 | scbid = ahd_inw(ahd, WAITING_TID_HEAD0x120); |
1633 | scb = ahd_lookup_scb(ahd, scbid); |
1634 | if (scb == NULL((void *)0)) { |
1635 | printf("%s: ahd_intr - referenced scb not " |
1636 | "valid during SELTO scb(0x%x)\n", |
1637 | ahd_name(ahd), scbid); |
1638 | ahd_dump_card_state(ahd); |
1639 | } else { |
1640 | struct ahd_devinfo devinfo; |
1641 | #ifdef AHD_DEBUG |
1642 | if ((ahd_debug & AHD_SHOW_SELTO) != 0) { |
1643 | ahd_print_path(ahd, scb); |
1644 | printf("Saw Selection Timeout for SCB 0x%x\n", |
1645 | scbid); |
1646 | } |
1647 | #endif |
1648 | ahd_scb_devinfo(ahd, &devinfo, scb); |
1649 | aic_set_transaction_status(scb, CAM_SEL_TIMEOUT)(scb)->xs->error = (CAM_SEL_TIMEOUT); |
1650 | ahd_freeze_devq(ahd, scb); |
1651 | |
1652 | /* |
1653 | * Cancel any pending transactions on the device |
1654 | * now that it seems to be missing. This will |
1655 | * also revert us to async/narrow transfers until |
1656 | * we can renegotiate with the device. |
1657 | */ |
1658 | ahd_handle_devreset(ahd, &devinfo, |
1659 | CAM_LUN_WILDCARD-1, |
1660 | CAM_SEL_TIMEOUT, |
1661 | "Selection Timeout", |
1662 | /*verbose_level*/1); |
1663 | } |
1664 | ahd_outb(ahd, CLRINT, CLRSCSIINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x08))); |
1665 | ahd_iocell_first_selection(ahd); |
1666 | ahd_unpause(ahd); |
1667 | } else if ((status0 & (SELDI0x20|SELDO0x40)) != 0) { |
1668 | |
1669 | ahd_iocell_first_selection(ahd); |
1670 | ahd_unpause(ahd); |
1671 | } else if (status3 != 0) { |
1672 | printf("%s: SCSI Cell parity error SSTAT3 == 0x%x\n", |
1673 | ahd_name(ahd), status3); |
1674 | ahd_outb(ahd, CLRSINT3, status3)(((ahd)->tags[(0x53) >> 8])->write_1(((ahd)->bshs [(0x53) >> 8]), ((0x53) & 0xFF), (status3))); |
1675 | } else if ((lqistat1 & (LQIPHASE_LQ0x80|LQIPHASE_NLQ0x40)) != 0) { |
1676 | |
1677 | /* Make sure the sequencer is in a safe location. */ |
1678 | ahd_clear_critical_section(ahd); |
1679 | |
1680 | ahd_handle_lqiphase_error(ahd, lqistat1); |
1681 | } else if ((lqistat1 & LQICRCI_NLQ0x08) != 0) { |
1682 | /* |
1683 | * This status can be delayed during some |
1684 | * streaming operations. The SCSIPHASE |
1685 | * handler has already dealt with this case |
1686 | * so just clear the error. |
1687 | */ |
1688 | ahd_outb(ahd, CLRLQIINT1, CLRLQICRCI_NLQ)(((ahd)->tags[(0x51) >> 8])->write_1(((ahd)->bshs [(0x51) >> 8]), ((0x51) & 0xFF), (0x08))); |
1689 | } else if ((status & BUSFREE0x08) != 0 |
1690 | || (lqistat1 & LQOBUSFREE0x02) != 0) { |
1691 | u_int lqostat1; |
1692 | int restart; |
1693 | int clear_fifo; |
1694 | int packetized; |
1695 | u_int mode; |
1696 | |
1697 | /* |
1698 | * Clear our selection hardware as soon as possible. |
1699 | * We may have an entry in the waiting Q for this target, |
1700 | * that is affected by this busfree and we don't want to |
1701 | * go about selecting the target while we handle the event. |
1702 | */ |
1703 | ahd_outb(ahd, SCSISEQ0, 0)(((ahd)->tags[(0x3a) >> 8])->write_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF), (0))); |
1704 | |
1705 | /* Make sure the sequencer is in a safe location. */ |
1706 | ahd_clear_critical_section(ahd); |
1707 | |
1708 | /* |
1709 | * Determine what we were up to at the time of |
1710 | * the busfree. |
1711 | */ |
1712 | mode = AHD_MODE_SCSI; |
1713 | busfreetime = ahd_inb(ahd, SSTAT2)(((ahd)->tags[(0x4d) >> 8])->read_1(((ahd)->bshs [(0x4d) >> 8]), ((0x4d) & 0xFF))) & BUSFREETIME0xc0; |
1714 | lqostat1 = ahd_inb(ahd, LQOSTAT1)(((ahd)->tags[(0x55) >> 8])->read_1(((ahd)->bshs [(0x55) >> 8]), ((0x55) & 0xFF))); |
1715 | switch (busfreetime) { |
1716 | case BUSFREE_DFF00x80: |
1717 | case BUSFREE_DFF10xc0: |
1718 | mode = busfreetime == BUSFREE_DFF00x80 |
1719 | ? AHD_MODE_DFF0 : AHD_MODE_DFF1; |
1720 | ahd_set_modes(ahd, mode, mode); |
1721 | scbid = ahd_get_scbptr(ahd); |
1722 | scb = ahd_lookup_scb(ahd, scbid); |
1723 | if (scb == NULL((void *)0)) { |
1724 | printf("%s: Invalid SCB %d in DFF%d " |
1725 | "during unexpected busfree\n", |
1726 | ahd_name(ahd), scbid, mode); |
1727 | packetized = 0; |
1728 | } else |
1729 | packetized = (scb->flags & SCB_PACKETIZED) != 0; |
1730 | clear_fifo = 1; |
1731 | break; |
1732 | case BUSFREE_LQO0x40: |
1733 | clear_fifo = 0; |
1734 | packetized = 1; |
1735 | break; |
1736 | default: |
1737 | clear_fifo = 0; |
1738 | packetized = (lqostat1 & LQOBUSFREE0x02) != 0; |
1739 | if (!packetized |
1740 | && ahd_inb(ahd, LASTPHASE)(((ahd)->tags[(0x13c) >> 8])->read_1(((ahd)->bshs [(0x13c) >> 8]), ((0x13c) & 0xFF))) == P_BUSFREE0x01 |
1741 | && (ahd_inb(ahd, SSTAT0)(((ahd)->tags[(0x4b) >> 8])->read_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF))) & SELDI0x20) == 0 |
1742 | && ((ahd_inb(ahd, SSTAT0)(((ahd)->tags[(0x4b) >> 8])->read_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF))) & SELDO0x40) == 0 |
1743 | || (ahd_inb(ahd, SCSISEQ0)(((ahd)->tags[(0x3a) >> 8])->read_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF))) & ENSELO0x40) == 0)) |
1744 | /* |
1745 | * Assume packetized if we are not |
1746 | * on the bus in a non-packetized |
1747 | * capacity and any pending selection |
1748 | * was a packetized selection. |
1749 | */ |
1750 | packetized = 1; |
1751 | break; |
1752 | } |
1753 | |
1754 | #ifdef AHD_DEBUG |
1755 | if ((ahd_debug & AHD_SHOW_MISC) != 0) |
1756 | printf("Saw Busfree. Busfreetime = 0x%x.\n", |
1757 | busfreetime); |
1758 | #endif |
1759 | /* |
1760 | * Busfrees that occur in non-packetized phases are |
1761 | * handled by the nonpkt_busfree handler. |
1762 | */ |
1763 | if (packetized && ahd_inb(ahd, LASTPHASE)(((ahd)->tags[(0x13c) >> 8])->read_1(((ahd)->bshs [(0x13c) >> 8]), ((0x13c) & 0xFF))) == P_BUSFREE0x01) { |
1764 | restart = ahd_handle_pkt_busfree(ahd, busfreetime); |
1765 | } else { |
1766 | packetized = 0; |
1767 | restart = ahd_handle_nonpkt_busfree(ahd); |
1768 | } |
1769 | /* |
1770 | * Clear the busfree interrupt status. The setting of |
1771 | * the interrupt is a pulse, so in a perfect world, we |
1772 | * would not need to muck with the ENBUSFREE logic. This |
1773 | * would ensure that if the bus moves on to another |
1774 | * connection, busfree protection is still in force. If |
1775 | * BUSFREEREV is broken, however, we must manually clear |
1776 | * the ENBUSFREE if the busfree occurred during a non-pack |
1777 | * connection so that we don't get false positives during |
1778 | * future, packetized, connections. |
1779 | */ |
1780 | ahd_outb(ahd, CLRSINT1, CLRBUSFREE)(((ahd)->tags[(0x4c) >> 8])->write_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF), (0x08))); |
1781 | if (packetized == 0 |
1782 | && (ahd->bugs & AHD_BUSFREEREV_BUG) != 0) |
1783 | ahd_outb(ahd, SIMODE1,(((ahd)->tags[(0x57) >> 8])->write_1(((ahd)->bshs [(0x57) >> 8]), ((0x57) & 0xFF), ((((ahd)->tags[ (0x57) >> 8])->read_1(((ahd)->bshs[(0x57) >> 8]), ((0x57) & 0xFF))) & ~0x08))) |
1784 | ahd_inb(ahd, SIMODE1) & ~ENBUSFREE)(((ahd)->tags[(0x57) >> 8])->write_1(((ahd)->bshs [(0x57) >> 8]), ((0x57) & 0xFF), ((((ahd)->tags[ (0x57) >> 8])->read_1(((ahd)->bshs[(0x57) >> 8]), ((0x57) & 0xFF))) & ~0x08))); |
1785 | |
1786 | if (clear_fifo) |
1787 | ahd_clear_fifo(ahd, mode); |
1788 | |
1789 | ahd_clear_msg_state(ahd); |
1790 | ahd_outb(ahd, CLRINT, CLRSCSIINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x08))); |
1791 | if (restart) { |
1792 | ahd_restart(ahd); |
1793 | } else { |
1794 | ahd_unpause(ahd); |
1795 | } |
1796 | } else { |
1797 | printf("%s: Missing case in ahd_handle_scsiint. status = %x\n", |
1798 | ahd_name(ahd), status); |
1799 | ahd_dump_card_state(ahd); |
1800 | ahd_clear_intstat(ahd); |
1801 | ahd_unpause(ahd); |
1802 | } |
1803 | } |
1804 | |
1805 | void |
1806 | ahd_handle_transmission_error(struct ahd_softc *ahd) |
1807 | { |
1808 | struct scb *scb; |
1809 | u_int scbid; |
1810 | u_int lqistat1; |
1811 | u_int lqistat2; |
1812 | u_int msg_out; |
1813 | u_int curphase; |
1814 | u_int lastphase; |
1815 | u_int perrdiag; |
1816 | u_int cur_col; |
1817 | int silent; |
1818 | |
1819 | scb = NULL((void *)0); |
1820 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
1821 | lqistat1 = ahd_inb(ahd, LQISTAT1)(((ahd)->tags[(0x51) >> 8])->read_1(((ahd)->bshs [(0x51) >> 8]), ((0x51) & 0xFF))) & ~(LQIPHASE_LQ0x80|LQIPHASE_NLQ0x40); |
1822 | lqistat2 = ahd_inb(ahd, LQISTAT2)(((ahd)->tags[(0x52) >> 8])->read_1(((ahd)->bshs [(0x52) >> 8]), ((0x52) & 0xFF))); |
1823 | if ((lqistat1 & (LQICRCI_NLQ0x08|LQICRCI_LQ0x10)) == 0 |
1824 | && (ahd->bugs & AHD_NLQICRC_DELAYED_BUG) != 0) { |
1825 | u_int lqistate; |
1826 | |
1827 | ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); |
1828 | lqistate = ahd_inb(ahd, LQISTATE)(((ahd)->tags[(0x4e) >> 8])->read_1(((ahd)->bshs [(0x4e) >> 8]), ((0x4e) & 0xFF))); |
1829 | if ((lqistate >= 0x1E && lqistate <= 0x24) |
1830 | || (lqistate == 0x29)) { |
1831 | #ifdef AHD_DEBUG |
1832 | if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { |
1833 | printf("%s: NLQCRC found via LQISTATE\n", |
1834 | ahd_name(ahd)); |
1835 | } |
1836 | #endif |
1837 | lqistat1 |= LQICRCI_NLQ0x08; |
1838 | } |
1839 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
1840 | } |
1841 | |
1842 | ahd_outb(ahd, CLRLQIINT1, lqistat1)(((ahd)->tags[(0x51) >> 8])->write_1(((ahd)->bshs [(0x51) >> 8]), ((0x51) & 0xFF), (lqistat1))); |
1843 | lastphase = ahd_inb(ahd, LASTPHASE)(((ahd)->tags[(0x13c) >> 8])->read_1(((ahd)->bshs [(0x13c) >> 8]), ((0x13c) & 0xFF))); |
1844 | curphase = ahd_inb(ahd, SCSISIGI)(((ahd)->tags[(0x41) >> 8])->read_1(((ahd)->bshs [(0x41) >> 8]), ((0x41) & 0xFF))) & PHASE_MASK0xe0; |
1845 | perrdiag = ahd_inb(ahd, PERRDIAG)(((ahd)->tags[(0x4e) >> 8])->read_1(((ahd)->bshs [(0x4e) >> 8]), ((0x4e) & 0xFF))); |
1846 | msg_out = MSG_INITIATOR_DET_ERR0x05; |
1847 | ahd_outb(ahd, CLRSINT1, CLRSCSIPERR)(((ahd)->tags[(0x4c) >> 8])->write_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF), (0x04))); |
1848 | |
1849 | /* |
1850 | * Try to find the SCB associated with this error. |
1851 | */ |
1852 | silent = FALSE0; |
1853 | if (lqistat1 == 0 |
1854 | || (lqistat1 & LQICRCI_NLQ0x08) != 0) { |
1855 | if ((lqistat1 & (LQICRCI_NLQ0x08|LQIOVERI_NLQ0x01)) != 0) |
1856 | ahd_set_active_fifo(ahd); |
1857 | scbid = ahd_get_scbptr(ahd); |
1858 | scb = ahd_lookup_scb(ahd, scbid); |
1859 | if (scb != NULL((void *)0) && SCB_IS_SILENT(scb)(((scb)->flags & SCB_SILENT) != 0)) |
1860 | silent = TRUE1; |
1861 | } |
1862 | |
1863 | cur_col = 0; |
1864 | if (silent == FALSE0) { |
1865 | printf("%s: Transmission error detected\n", ahd_name(ahd)); |
1866 | ahd_lqistat1_print(lqistat1, &cur_col, 50)ahd_print_register(((void *)0), 0, "LQISTAT1", 0x51, lqistat1 , &cur_col, 50); |
1867 | ahd_lastphase_print(lastphase, &cur_col, 50)ahd_print_register(((void *)0), 0, "LASTPHASE", 0x13c, lastphase , &cur_col, 50); |
1868 | ahd_scsisigi_print(curphase, &cur_col, 50)ahd_print_register(((void *)0), 0, "SCSISIGI", 0x41, curphase , &cur_col, 50); |
1869 | ahd_perrdiag_print(perrdiag, &cur_col, 50)ahd_print_register(((void *)0), 0, "PERRDIAG", 0x4e, perrdiag , &cur_col, 50); |
1870 | printf("\n"); |
1871 | ahd_dump_card_state(ahd); |
1872 | } |
1873 | |
1874 | if ((lqistat1 & (LQIOVERI_LQ0x02|LQIOVERI_NLQ0x01)) != 0) { |
1875 | if (silent == FALSE0) { |
1876 | printf("%s: Gross protocol error during incoming " |
1877 | "packet. lqistat1 == 0x%x. Resetting bus.\n", |
1878 | ahd_name(ahd), lqistat1); |
1879 | } |
1880 | ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE1); |
1881 | return; |
1882 | } else if ((lqistat1 & LQICRCI_LQ0x10) != 0) { |
1883 | /* |
1884 | * A CRC error has been detected on an incoming LQ. |
1885 | * The bus is currently hung on the last ACK. |
1886 | * Hit LQIRETRY to release the last ack, and |
1887 | * wait for the sequencer to determine that ATNO |
1888 | * is asserted while in message out to take us |
1889 | * to our host message loop. No NONPACKREQ or |
1890 | * LQIPHASE type errors will occur in this |
1891 | * scenario. After this first LQIRETRY, the LQI |
1892 | * manager will be in ISELO where it will |
1893 | * happily sit until another packet phase begins. |
1894 | * Unexpected bus free detection is enabled |
1895 | * through any phases that occur after we release |
1896 | * this last ack until the LQI manager sees a |
1897 | * packet phase. This implies we may have to |
1898 | * ignore a perfectly valid "unexpected busfree" |
1899 | * after our "initiator detected error" message is |
1900 | * sent. A busfree is the expected response after |
1901 | * we tell the target that its L_Q was corrupted. |
1902 | * (SPI4R09 10.7.3.3.3) |
1903 | */ |
1904 | ahd_outb(ahd, LQCTL2, LQIRETRY)(((ahd)->tags[(0x39) >> 8])->write_1(((ahd)->bshs [(0x39) >> 8]), ((0x39) & 0xFF), (0x80))); |
1905 | printf("LQIRetry for LQICRCI_LQ to release ACK\n"); |
1906 | } else if ((lqistat1 & LQICRCI_NLQ0x08) != 0) { |
1907 | /* |
1908 | * We detected a CRC error in a NON-LQ packet. |
1909 | * The hardware has varying behavior in this situation |
1910 | * depending on whether this packet was part of a |
1911 | * stream or not. |
1912 | * |
1913 | * PKT by PKT mode: |
1914 | * The hardware has already acked the complete packet. |
1915 | * If the target honors our outstanding ATN condition, |
1916 | * we should be (or soon will be) in MSGOUT phase. |
1917 | * This will trigger the LQIPHASE_LQ status bit as the |
1918 | * hardware was expecting another LQ. Unexpected |
1919 | * busfree detection is enabled. Once LQIPHASE_LQ is |
1920 | * true (first entry into host message loop is much |
1921 | * the same), we must clear LQIPHASE_LQ and hit |
1922 | * LQIRETRY so the hardware is ready to handle |
1923 | * a future LQ. NONPACKREQ will not be asserted again |
1924 | * once we hit LQIRETRY until another packet is |
1925 | * processed. The target may either go busfree |
1926 | * or start another packet in response to our message. |
1927 | * |
1928 | * Read Streaming P0 asserted: |
1929 | * If we raise ATN and the target completes the entire |
1930 | * stream (P0 asserted during the last packet), the |
1931 | * hardware will ack all data and return to the ISTART |
1932 | * state. When the target responds to our ATN condition, |
1933 | * LQIPHASE_LQ will be asserted. We should respond to |
1934 | * this with an LQIRETRY to prepare for any future |
1935 | * packets. NONPACKREQ will not be asserted again |
1936 | * once we hit LQIRETRY until another packet is |
1937 | * processed. The target may either go busfree or |
1938 | * start another packet in response to our message. |
1939 | * Busfree detection is enabled. |
1940 | * |
1941 | * Read Streaming P0 not asserted: |
1942 | * If we raise ATN and the target transitions to |
1943 | * MSGOUT in or after a packet where P0 is not |
1944 | * asserted, the hardware will assert LQIPHASE_NLQ. |
1945 | * We should respond to the LQIPHASE_NLQ with an |
1946 | * LQIRETRY. Should the target stay in a non-pkt |
1947 | * phase after we send our message, the hardware |
1948 | * will assert LQIPHASE_LQ. Recovery is then just as |
1949 | * listed above for the read streaming with P0 asserted. |
1950 | * Busfree detection is enabled. |
1951 | */ |
1952 | if (silent == FALSE0) |
1953 | printf("LQICRC_NLQ\n"); |
1954 | if (scb == NULL((void *)0)) { |
1955 | printf("%s: No SCB valid for LQICRC_NLQ. " |
1956 | "Resetting bus\n", ahd_name(ahd)); |
1957 | ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE1); |
1958 | return; |
1959 | } |
1960 | } else if ((lqistat1 & LQIBADLQI0x04) != 0) { |
1961 | printf("Need to handle BADLQI!\n"); |
1962 | ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE1); |
1963 | return; |
1964 | } else if ((perrdiag & (PARITYERR0x10|PREVPHASE0x20)) == PARITYERR0x10) { |
1965 | if ((curphase & ~P_DATAIN_DT0x60) != 0) { |
1966 | /* Ack the byte. So we can continue. */ |
1967 | if (silent == FALSE0) |
1968 | printf("Acking %s to clear perror\n", |
1969 | ahd_lookup_phase_entry(curphase)->phasemsg); |
1970 | ahd_inb(ahd, SCSIDAT)(((ahd)->tags[(0x44) >> 8])->read_1(((ahd)->bshs [(0x44) >> 8]), ((0x44) & 0xFF))); |
1971 | } |
1972 | |
1973 | if (curphase == P_MESGIN0xe0) |
1974 | msg_out = MSG_PARITY_ERROR0x09; |
1975 | } |
1976 | |
1977 | /* |
1978 | * We've set the hardware to assert ATN if we |
1979 | * get a parity error on "in" phases, so all we |
1980 | * need to do is stuff the message buffer with |
1981 | * the appropriate message. "In" phases have set |
1982 | * mesg_out to something other than MSG_NOP. |
1983 | */ |
1984 | ahd->send_msg_perror = msg_out; |
1985 | if (scb != NULL((void *)0) && msg_out == MSG_INITIATOR_DET_ERR0x05) |
1986 | scb->flags |= SCB_TRANSMISSION_ERROR; |
1987 | ahd_outb(ahd, MSG_OUT, HOST_MSG)(((ahd)->tags[(0x137) >> 8])->write_1(((ahd)-> bshs[(0x137) >> 8]), ((0x137) & 0xFF), (0xff))); |
1988 | ahd_outb(ahd, CLRINT, CLRSCSIINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x08))); |
1989 | ahd_unpause(ahd); |
1990 | } |
1991 | |
1992 | void |
1993 | ahd_handle_lqiphase_error(struct ahd_softc *ahd, u_int lqistat1) |
1994 | { |
1995 | /* |
1996 | * Clear the sources of the interrupts. |
1997 | */ |
1998 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
1999 | ahd_outb(ahd, CLRLQIINT1, lqistat1)(((ahd)->tags[(0x51) >> 8])->write_1(((ahd)->bshs [(0x51) >> 8]), ((0x51) & 0xFF), (lqistat1))); |
2000 | |
2001 | /* |
2002 | * If the "illegal" phase changes were in response |
2003 | * to our ATN to flag a CRC error, AND we ended up |
2004 | * on packet boundaries, clear the error, restart the |
2005 | * LQI manager as appropriate, and go on our merry |
2006 | * way toward sending the message. Otherwise, reset |
2007 | * the bus to clear the error. |
2008 | */ |
2009 | ahd_set_active_fifo(ahd); |
2010 | if ((ahd_inb(ahd, SCSISIGO)(((ahd)->tags[(0x40) >> 8])->read_1(((ahd)->bshs [(0x40) >> 8]), ((0x40) & 0xFF))) & ATNO0x10) != 0 |
2011 | && (ahd_inb(ahd, MDFFSTAT)(((ahd)->tags[(0x5d) >> 8])->read_1(((ahd)->bshs [(0x5d) >> 8]), ((0x5d) & 0xFF))) & DLZERO0x04) != 0) { |
2012 | if ((lqistat1 & LQIPHASE_LQ0x80) != 0) { |
2013 | printf("LQIRETRY for LQIPHASE_LQ\n"); |
2014 | ahd_outb(ahd, LQCTL2, LQIRETRY)(((ahd)->tags[(0x39) >> 8])->write_1(((ahd)->bshs [(0x39) >> 8]), ((0x39) & 0xFF), (0x80))); |
2015 | } else if ((lqistat1 & LQIPHASE_NLQ0x40) != 0) { |
2016 | printf("LQIRETRY for LQIPHASE_NLQ\n"); |
2017 | ahd_outb(ahd, LQCTL2, LQIRETRY)(((ahd)->tags[(0x39) >> 8])->write_1(((ahd)->bshs [(0x39) >> 8]), ((0x39) & 0xFF), (0x80))); |
2018 | } else |
2019 | panic("ahd_handle_lqiphase_error: No phase errors"); |
2020 | ahd_dump_card_state(ahd); |
2021 | ahd_outb(ahd, CLRINT, CLRSCSIINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x08))); |
2022 | ahd_unpause(ahd); |
2023 | } else { |
2024 | printf("Resetting Channel for LQI Phase error\n"); |
2025 | ahd_dump_card_state(ahd); |
2026 | ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE1); |
2027 | } |
2028 | } |
2029 | |
2030 | /* |
2031 | * Packetized unexpected or expected busfree. |
2032 | * Entered in mode based on busfreetime. |
2033 | */ |
2034 | int |
2035 | ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime) |
2036 | { |
2037 | u_int lqostat1; |
2038 | |
2039 | AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),ahd_assert_modes(ahd, ~((0x01 << (AHD_MODE_UNKNOWN))|(0x01 << (AHD_MODE_CFG))), ~((0x01 << (AHD_MODE_UNKNOWN ))|(0x01 << (AHD_MODE_CFG))), "/usr/src/sys/dev/ic/aic79xx.c" , 2040); |
2040 | ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK))ahd_assert_modes(ahd, ~((0x01 << (AHD_MODE_UNKNOWN))|(0x01 << (AHD_MODE_CFG))), ~((0x01 << (AHD_MODE_UNKNOWN ))|(0x01 << (AHD_MODE_CFG))), "/usr/src/sys/dev/ic/aic79xx.c" , 2040);; |
2041 | lqostat1 = ahd_inb(ahd, LQOSTAT1)(((ahd)->tags[(0x55) >> 8])->read_1(((ahd)->bshs [(0x55) >> 8]), ((0x55) & 0xFF))); |
2042 | if ((lqostat1 & LQOBUSFREE0x02) != 0) { |
2043 | struct scb *scb; |
2044 | u_int scbid; |
2045 | u_int saved_scbptr; |
2046 | u_int waiting_h; |
2047 | u_int waiting_t; |
2048 | u_int next; |
2049 | |
2050 | /* |
2051 | * The LQO manager detected an unexpected busfree |
2052 | * either: |
2053 | * |
2054 | * 1) During an outgoing LQ. |
2055 | * 2) After an outgoing LQ but before the first |
2056 | * REQ of the command packet. |
2057 | * 3) During an outgoing command packet. |
2058 | * |
2059 | * In all cases, CURRSCB is pointing to the |
2060 | * SCB that encountered the failure. Clean |
2061 | * up the queue, clear SELDO and LQOBUSFREE, |
2062 | * and allow the sequencer to restart the select |
2063 | * out at its lesure. |
2064 | */ |
2065 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
2066 | scbid = ahd_inw(ahd, CURRSCB0x5c); |
2067 | scb = ahd_lookup_scb(ahd, scbid); |
2068 | if (scb == NULL((void *)0)) |
2069 | panic("SCB not valid during LQOBUSFREE"); |
2070 | /* |
2071 | * Clear the status. |
2072 | */ |
2073 | ahd_outb(ahd, CLRLQOINT1, CLRLQOBUSFREE)(((ahd)->tags[(0x55) >> 8])->write_1(((ahd)->bshs [(0x55) >> 8]), ((0x55) & 0xFF), (0x02))); |
2074 | if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) |
2075 | ahd_outb(ahd, CLRLQOINT1, 0)(((ahd)->tags[(0x55) >> 8])->write_1(((ahd)->bshs [(0x55) >> 8]), ((0x55) & 0xFF), (0))); |
2076 | ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO)(((ahd)->tags[(0x3a) >> 8])->write_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF), ((((ahd)->tags[ (0x3a) >> 8])->read_1(((ahd)->bshs[(0x3a) >> 8]), ((0x3a) & 0xFF))) & ~0x40))); |
2077 | ahd_flush_device_writes(ahd); |
2078 | ahd_outb(ahd, CLRSINT0, CLRSELDO)(((ahd)->tags[(0x4b) >> 8])->write_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF), (0x40))); |
2079 | |
2080 | /* |
2081 | * Return the LQO manager to its idle loop. It will |
2082 | * not do this automatically if the busfree occurs |
2083 | * after the first REQ of either the LQ or command |
2084 | * packet or between the LQ and command packet. |
2085 | */ |
2086 | ahd_outb(ahd, LQCTL2, ahd_inb(ahd, LQCTL2) | LQOTOIDLE)(((ahd)->tags[(0x39) >> 8])->write_1(((ahd)->bshs [(0x39) >> 8]), ((0x39) & 0xFF), ((((ahd)->tags[ (0x39) >> 8])->read_1(((ahd)->bshs[(0x39) >> 8]), ((0x39) & 0xFF))) | 0x02))); |
2087 | |
2088 | /* |
2089 | * Update the waiting for selection queue so |
2090 | * we restart on the correct SCB. |
2091 | */ |
2092 | waiting_h = ahd_inw(ahd, WAITING_TID_HEAD0x120); |
2093 | saved_scbptr = ahd_get_scbptr(ahd); |
2094 | if (waiting_h != scbid) { |
2095 | |
2096 | ahd_outw(ahd, WAITING_TID_HEAD0x120, scbid); |
2097 | waiting_t = ahd_inw(ahd, WAITING_TID_TAIL0x122); |
2098 | if (waiting_t == waiting_h) { |
2099 | ahd_outw(ahd, WAITING_TID_TAIL0x122, scbid); |
2100 | next = SCB_LIST_NULL0xFF00; |
2101 | } else { |
2102 | ahd_set_scbptr(ahd, waiting_h); |
2103 | next = ahd_inw_scbram(ahd, SCB_NEXT20x1ae); |
2104 | } |
2105 | ahd_set_scbptr(ahd, scbid); |
2106 | ahd_outw(ahd, SCB_NEXT20x1ae, next); |
2107 | } |
2108 | ahd_set_scbptr(ahd, saved_scbptr); |
2109 | if (scb->crc_retry_count < AHD_MAX_LQ_CRC_ERRORS5) { |
2110 | if (SCB_IS_SILENT(scb)(((scb)->flags & SCB_SILENT) != 0) == FALSE0) { |
2111 | ahd_print_path(ahd, scb); |
2112 | printf("Probable outgoing LQ CRC error. " |
2113 | "Retrying command\n"); |
2114 | } |
2115 | scb->crc_retry_count++; |
2116 | } else { |
2117 | aic_set_transaction_status(scb, CAM_UNCOR_PARITY)(scb)->xs->error = (CAM_UNCOR_PARITY); |
2118 | aic_freeze_scb(scb); |
2119 | ahd_freeze_devq(ahd, scb); |
2120 | } |
2121 | /* Return unpausing the sequencer. */ |
2122 | return (0); |
2123 | } else if ((ahd_inb(ahd, PERRDIAG)(((ahd)->tags[(0x4e) >> 8])->read_1(((ahd)->bshs [(0x4e) >> 8]), ((0x4e) & 0xFF))) & PARITYERR0x10) != 0) { |
2124 | /* |
2125 | * Ignore what are really parity errors that |
2126 | * occur on the last REQ of a free running |
2127 | * clock prior to going busfree. Some drives |
2128 | * do not properly active negate just before |
2129 | * going busfree resulting in a parity glitch. |
2130 | */ |
2131 | ahd_outb(ahd, CLRSINT1, CLRSCSIPERR|CLRBUSFREE)(((ahd)->tags[(0x4c) >> 8])->write_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF), (0x04|0x08))); |
2132 | #ifdef AHD_DEBUG |
2133 | if ((ahd_debug & AHD_SHOW_MASKED_ERRORS) != 0) |
2134 | printf("%s: Parity on last REQ detected " |
2135 | "during busfree phase.\n", |
2136 | ahd_name(ahd)); |
2137 | #endif |
2138 | /* Return unpausing the sequencer. */ |
2139 | return (0); |
2140 | } |
2141 | if (ahd->src_mode != AHD_MODE_SCSI) { |
2142 | u_int scbid; |
2143 | struct scb *scb; |
2144 | |
2145 | scbid = ahd_get_scbptr(ahd); |
2146 | scb = ahd_lookup_scb(ahd, scbid); |
2147 | ahd_print_path(ahd, scb); |
2148 | printf("Unexpected PKT busfree condition\n"); |
2149 | ahd_dump_card_state(ahd); |
2150 | ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb)((((scb)->hscb->scsiid) & 0xf0) >> 0x04), 'A', |
2151 | SCB_GET_LUN(scb)((scb)->hscb->lun), SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)), |
2152 | ROLE_INITIATOR, CAM_UNEXP_BUSFREE); |
2153 | |
2154 | /* Return restarting the sequencer. */ |
2155 | return (1); |
2156 | } |
2157 | printf("%s: Unexpected PKT busfree condition\n", ahd_name(ahd)); |
2158 | ahd_dump_card_state(ahd); |
2159 | /* Restart the sequencer. */ |
2160 | return (1); |
2161 | } |
2162 | |
2163 | /* |
2164 | * Non-packetized unexpected or expected busfree. |
2165 | */ |
2166 | int |
2167 | ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) |
2168 | { |
2169 | struct ahd_devinfo devinfo; |
2170 | struct scb *scb; |
2171 | u_int lastphase; |
2172 | u_int saved_scsiid; |
2173 | u_int saved_lun; |
2174 | u_int target; |
2175 | u_int initiator_role_id; |
2176 | u_int scbid; |
2177 | u_int ppr_busfree; |
2178 | int printerror; |
2179 | |
2180 | /* |
2181 | * Look at what phase we were last in. If its message out, |
2182 | * chances are pretty good that the busfree was in response |
2183 | * to one of our abort requests. |
2184 | */ |
2185 | lastphase = ahd_inb(ahd, LASTPHASE)(((ahd)->tags[(0x13c) >> 8])->read_1(((ahd)->bshs [(0x13c) >> 8]), ((0x13c) & 0xFF))); |
2186 | saved_scsiid = ahd_inb(ahd, SAVED_SCSIID)(((ahd)->tags[(0x13a) >> 8])->read_1(((ahd)->bshs [(0x13a) >> 8]), ((0x13a) & 0xFF))); |
2187 | saved_lun = ahd_inb(ahd, SAVED_LUN)(((ahd)->tags[(0x13b) >> 8])->read_1(((ahd)->bshs [(0x13b) >> 8]), ((0x13b) & 0xFF))); |
2188 | target = SCSIID_TARGET(ahd, saved_scsiid)(((saved_scsiid) & 0xf0) >> 0x04); |
2189 | initiator_role_id = SCSIID_OUR_ID(saved_scsiid)((saved_scsiid) & 0x0f); |
2190 | ahd_compile_devinfo(&devinfo, initiator_role_id, |
2191 | target, saved_lun, 'A', ROLE_INITIATOR); |
2192 | printerror = 1; |
2193 | |
2194 | scbid = ahd_get_scbptr(ahd); |
2195 | scb = ahd_lookup_scb(ahd, scbid); |
2196 | if (scb != NULL((void *)0) |
2197 | && (ahd_inb(ahd, SEQ_FLAGS)(((ahd)->tags[(0x139) >> 8])->read_1(((ahd)->bshs [(0x139) >> 8]), ((0x139) & 0xFF))) & NOT_IDENTIFIED0x80) != 0) |
2198 | scb = NULL((void *)0); |
2199 | |
2200 | ppr_busfree = (ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0; |
2201 | if (lastphase == P_MESGOUT0xa0) { |
2202 | u_int tag; |
2203 | |
2204 | tag = SCB_LIST_NULL0xFF00; |
2205 | if (ahd_sent_msg(ahd, AHDMSG_1B, MSG_ABORT_TAG0x0d, TRUE1) |
2206 | || ahd_sent_msg(ahd, AHDMSG_1B, MSG_ABORT0x06, TRUE1)) { |
2207 | int found; |
2208 | int sent_msg; |
2209 | |
2210 | if (scb == NULL((void *)0)) { |
2211 | ahd_print_devinfo(ahd, &devinfo); |
2212 | printf("Abort for unidentified " |
2213 | "connection completed.\n"); |
2214 | /* restart the sequencer. */ |
2215 | return (1); |
2216 | } |
2217 | sent_msg = ahd->msgout_buf[ahd->msgout_index - 1]; |
2218 | ahd_print_path(ahd, scb); |
2219 | printf("SCB %d - Abort%s Completed.\n", |
2220 | SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)), |
2221 | sent_msg == MSG_ABORT_TAG0x0d ? "" : " Tag"); |
2222 | |
2223 | if (sent_msg == MSG_ABORT_TAG0x0d) |
2224 | tag = SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)); |
2225 | |
2226 | if ((scb->flags & SCB_CMDPHASE_ABORT) != 0) { |
2227 | /* |
2228 | * This abort is in response to an |
2229 | * unexpected switch to command phase |
2230 | * for a packetized connection. Since |
2231 | * the identify message was never sent, |
2232 | * "saved lun" is 0. We really want to |
2233 | * abort only the SCB that encountered |
2234 | * this error, which could have a different |
2235 | * lun. The SCB will be retried so the OS |
2236 | * will see the UA after renegotiating to |
2237 | * packetized. |
2238 | */ |
2239 | tag = SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)); |
2240 | saved_lun = scb->hscb->lun; |
2241 | } |
2242 | found = ahd_abort_scbs(ahd, target, 'A', saved_lun, |
2243 | tag, ROLE_INITIATOR, |
2244 | CAM_REQ_ABORTED); |
2245 | printerror = 0; |
2246 | } else if (ahd_sent_msg(ahd, AHDMSG_1B, |
2247 | MSG_BUS_DEV_RESET0x0c, TRUE1)) { |
2248 | #ifdef __FreeBSD__ |
2249 | /* |
2250 | * Don't mark the user's request for this BDR |
2251 | * as completing with CAM_BDR_SENT. CAM3 |
2252 | * specifies CAM_REQ_CMP. |
2253 | */ |
2254 | if (scb != NULL((void *)0) |
2255 | && scb->io_ctx->ccb_h.func_code== XPT_RESET_DEV |
2256 | && ahd_match_scb(ahd, scb, target, 'A', |
2257 | CAM_LUN_WILDCARD-1, SCB_LIST_NULL0xFF00, |
2258 | ROLE_INITIATOR)) |
2259 | aic_set_transaction_status(scb, CAM_REQ_CMP)(scb)->xs->error = (CAM_REQ_CMP); |
2260 | #endif |
2261 | ahd_handle_devreset(ahd, &devinfo, CAM_LUN_WILDCARD-1, |
2262 | CAM_BDR_SENT, "Bus Device Reset", |
2263 | /*verbose_level*/0); |
2264 | printerror = 0; |
2265 | } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR0x04, FALSE0) |
2266 | && ppr_busfree == 0) { |
2267 | struct ahd_initiator_tinfo *tinfo; |
2268 | struct ahd_tmode_tstate *tstate; |
2269 | |
2270 | /* |
2271 | * PPR Rejected. |
2272 | * |
2273 | * If the previous negotiation was packetized, |
2274 | * this could be because the device has been |
2275 | * reset without our knowledge. Force our |
2276 | * current negotiation to async and retry the |
2277 | * negotiation. Otherwise retry the command |
2278 | * with non-ppr negotiation. |
2279 | */ |
2280 | #ifdef AHD_DEBUG |
2281 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) |
2282 | printf("PPR negotiation rejected busfree.\n"); |
2283 | #endif |
2284 | tinfo = ahd_fetch_transinfo(ahd, devinfo.channel, |
2285 | devinfo.our_scsiid, |
2286 | devinfo.target, &tstate); |
2287 | if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ0x01)!=0) { |
2288 | ahd_set_width(ahd, &devinfo, |
2289 | MSG_EXT_WDTR_BUS_8_BIT0x00, |
2290 | AHD_TRANS_CUR0x01, |
2291 | /*paused*/TRUE1); |
2292 | ahd_set_syncrate(ahd, &devinfo, |
2293 | /*period*/0, /*offset*/0, |
2294 | /*ppr_options*/0, |
2295 | AHD_TRANS_CUR0x01, |
2296 | /*paused*/TRUE1); |
2297 | /* |
2298 | * The expect PPR busfree handler below |
2299 | * will effect the retry and necessary |
2300 | * abort. |
2301 | */ |
2302 | } else { |
2303 | tinfo->curr.transport_version = 2; |
2304 | tinfo->goal.transport_version = 2; |
2305 | tinfo->goal.ppr_options = 0; |
2306 | /* |
2307 | * Remove any SCBs in the waiting for selection |
2308 | * queue that may also be for this target so |
2309 | * that command ordering is preserved. |
2310 | */ |
2311 | ahd_freeze_devq(ahd, scb); |
2312 | ahd_qinfifo_requeue_tail(ahd, scb); |
2313 | printerror = 0; |
2314 | } |
2315 | } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR0x03, FALSE0) |
2316 | && ppr_busfree == 0) { |
2317 | /* |
2318 | * Negotiation Rejected. Go-narrow and |
2319 | * retry command. |
2320 | */ |
2321 | #ifdef AHD_DEBUG |
2322 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) |
2323 | printf("WDTR negotiation rejected busfree.\n"); |
2324 | #endif |
2325 | ahd_set_width(ahd, &devinfo, |
2326 | MSG_EXT_WDTR_BUS_8_BIT0x00, |
2327 | AHD_TRANS_CUR0x01|AHD_TRANS_GOAL0x04, |
2328 | /*paused*/TRUE1); |
2329 | /* |
2330 | * Remove any SCBs in the waiting for selection |
2331 | * queue that may also be for this target so that |
2332 | * command ordering is preserved. |
2333 | */ |
2334 | ahd_freeze_devq(ahd, scb); |
2335 | ahd_qinfifo_requeue_tail(ahd, scb); |
2336 | printerror = 0; |
2337 | } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR0x01, FALSE0) |
2338 | && ppr_busfree == 0) { |
2339 | /* |
2340 | * Negotiation Rejected. Go-async and |
2341 | * retry command. |
2342 | */ |
2343 | #ifdef AHD_DEBUG |
2344 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) |
2345 | printf("SDTR negotiation rejected busfree.\n"); |
2346 | #endif |
2347 | ahd_set_syncrate(ahd, &devinfo, |
2348 | /*period*/0, /*offset*/0, |
2349 | /*ppr_options*/0, |
2350 | AHD_TRANS_CUR0x01|AHD_TRANS_GOAL0x04, |
2351 | /*paused*/TRUE1); |
2352 | /* |
2353 | * Remove any SCBs in the waiting for selection |
2354 | * queue that may also be for this target so that |
2355 | * command ordering is preserved. |
2356 | */ |
2357 | ahd_freeze_devq(ahd, scb); |
2358 | ahd_qinfifo_requeue_tail(ahd, scb); |
2359 | printerror = 0; |
2360 | } else if ((ahd->msg_flags & MSG_FLAG_EXPECT_IDE_BUSFREE) != 0 |
2361 | && ahd_sent_msg(ahd, AHDMSG_1B, |
2362 | MSG_INITIATOR_DET_ERR0x05, TRUE1)) { |
2363 | |
2364 | #ifdef AHD_DEBUG |
2365 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) |
2366 | printf("Expected IDE Busfree\n"); |
2367 | #endif |
2368 | printerror = 0; |
2369 | } else if ((ahd->msg_flags & MSG_FLAG_EXPECT_QASREJ_BUSFREE) |
2370 | && ahd_sent_msg(ahd, AHDMSG_1B, |
2371 | MSG_MESSAGE_REJECT0x07, TRUE1)) { |
2372 | |
2373 | #ifdef AHD_DEBUG |
2374 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) |
2375 | printf("Expected QAS Reject Busfree\n"); |
2376 | #endif |
2377 | printerror = 0; |
2378 | } |
2379 | } |
2380 | |
2381 | /* |
2382 | * The busfree required flag is honored at the end of |
2383 | * the message phases. We check it last in case we |
2384 | * had to send some other message that caused a busfree. |
2385 | */ |
2386 | if (printerror != 0 |
2387 | && (lastphase == P_MESGIN0xe0 || lastphase == P_MESGOUT0xa0) |
2388 | && ((ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0) |
2389 | && (scb != NULL((void *)0))) { |
2390 | |
2391 | ahd_freeze_devq(ahd, scb); |
2392 | aic_set_transaction_status(scb, CAM_REQUEUE_REQ)(scb)->xs->error = (CAM_REQUEUE_REQ); |
2393 | aic_freeze_scb(scb); |
2394 | if ((ahd->msg_flags & MSG_FLAG_IU_REQ_CHANGED) != 0) { |
2395 | ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb)((((scb)->hscb->scsiid) & 0xf0) >> 0x04), |
2396 | SCB_GET_CHANNEL(ahd, scb)('A'), |
2397 | SCB_GET_LUN(scb)((scb)->hscb->lun), SCB_LIST_NULL0xFF00, |
2398 | ROLE_INITIATOR, CAM_REQ_ABORTED); |
2399 | } else { |
2400 | #ifdef AHD_DEBUG |
2401 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) |
2402 | printf("PPR Negotiation Busfree.\n"); |
2403 | #endif |
2404 | ahd_done(ahd, scb); |
2405 | } |
2406 | printerror = 0; |
2407 | } |
2408 | if (printerror != 0) { |
2409 | int aborted; |
2410 | |
2411 | aborted = 0; |
2412 | if (scb != NULL((void *)0)) { |
2413 | u_int tag; |
2414 | |
2415 | if ((scb->hscb->control & TAG_ENB0x20) != 0) |
2416 | tag = SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)); |
2417 | else |
2418 | tag = SCB_LIST_NULL0xFF00; |
2419 | ahd_print_path(ahd, scb); |
2420 | aborted = ahd_abort_scbs(ahd, target, 'A', |
2421 | SCB_GET_LUN(scb)((scb)->hscb->lun), tag, |
2422 | ROLE_INITIATOR, |
2423 | CAM_UNEXP_BUSFREE); |
2424 | } else { |
2425 | /* |
2426 | * We had not fully identified this connection, |
2427 | * so we cannot abort anything. |
2428 | */ |
2429 | printf("%s: ", ahd_name(ahd)); |
2430 | } |
2431 | printf("Unexpected busfree %s, %d SCBs aborted, " |
2432 | "PRGMCNT == 0x%x\n", |
2433 | ahd_lookup_phase_entry(lastphase)->phasemsg, |
2434 | aborted, |
2435 | ahd_inw(ahd, PRGMCNT0xde)); |
2436 | ahd_dump_card_state(ahd); |
2437 | if (lastphase != P_BUSFREE0x01) |
2438 | ahd_force_renegotiation(ahd, &devinfo); |
2439 | } |
2440 | /* Always restart the sequencer. */ |
2441 | return (1); |
2442 | } |
2443 | |
2444 | void |
2445 | ahd_handle_proto_violation(struct ahd_softc *ahd) |
2446 | { |
2447 | struct ahd_devinfo devinfo; |
2448 | struct scb *scb; |
2449 | u_int scbid; |
2450 | u_int seq_flags; |
2451 | u_int curphase; |
2452 | u_int lastphase; |
2453 | int found; |
2454 | |
2455 | ahd_fetch_devinfo(ahd, &devinfo); |
2456 | scbid = ahd_get_scbptr(ahd); |
2457 | scb = ahd_lookup_scb(ahd, scbid); |
2458 | seq_flags = ahd_inb(ahd, SEQ_FLAGS)(((ahd)->tags[(0x139) >> 8])->read_1(((ahd)->bshs [(0x139) >> 8]), ((0x139) & 0xFF))); |
2459 | curphase = ahd_inb(ahd, SCSISIGI)(((ahd)->tags[(0x41) >> 8])->read_1(((ahd)->bshs [(0x41) >> 8]), ((0x41) & 0xFF))) & PHASE_MASK0xe0; |
2460 | lastphase = ahd_inb(ahd, LASTPHASE)(((ahd)->tags[(0x13c) >> 8])->read_1(((ahd)->bshs [(0x13c) >> 8]), ((0x13c) & 0xFF))); |
2461 | if ((seq_flags & NOT_IDENTIFIED0x80) != 0) { |
2462 | |
2463 | /* |
2464 | * The reconnecting target either did not send an |
2465 | * identify message, or did, but we didn't find an SCB |
2466 | * to match. |
2467 | */ |
2468 | ahd_print_devinfo(ahd, &devinfo); |
2469 | printf("Target did not send an IDENTIFY message. " |
2470 | "LASTPHASE = 0x%x.\n", lastphase); |
2471 | scb = NULL((void *)0); |
2472 | } else if (scb == NULL((void *)0)) { |
2473 | /* |
2474 | * We don't seem to have an SCB active for this |
2475 | * transaction. Print an error and reset the bus. |
2476 | */ |
2477 | ahd_print_devinfo(ahd, &devinfo); |
2478 | printf("No SCB found during protocol violation\n"); |
2479 | goto proto_violation_reset; |
2480 | } else { |
2481 | aic_set_transaction_status(scb, CAM_SEQUENCE_FAIL)(scb)->xs->error = (CAM_SEQUENCE_FAIL); |
2482 | if ((seq_flags & NO_CDB_SENT0x40) != 0) { |
2483 | ahd_print_path(ahd, scb); |
2484 | printf("No or incomplete CDB sent to device.\n"); |
2485 | } else if ((ahd_inb_scbram(ahd, SCB_CONTROL0x192) |
2486 | & STATUS_RCVD0x08) == 0) { |
2487 | /* |
2488 | * The target never bothered to provide status to |
2489 | * us prior to completing the command. Since we don't |
2490 | * know the disposition of this command, we must attempt |
2491 | * to abort it. Assert ATN and prepare to send an abort |
2492 | * message. |
2493 | */ |
2494 | ahd_print_path(ahd, scb); |
2495 | printf("Completed command without status.\n"); |
2496 | } else { |
2497 | ahd_print_path(ahd, scb); |
2498 | printf("Unknown protocol violation.\n"); |
2499 | ahd_dump_card_state(ahd); |
2500 | } |
2501 | } |
2502 | if ((lastphase & ~P_DATAIN_DT0x60) == 0 |
2503 | || lastphase == P_COMMAND0x80) { |
2504 | proto_violation_reset: |
2505 | /* |
2506 | * Target either went directly to data |
2507 | * phase or didn't respond to our ATN. |
2508 | * The only safe thing to do is to blow |
2509 | * it away with a bus reset. |
2510 | */ |
2511 | found = ahd_reset_channel(ahd, 'A', TRUE1); |
2512 | printf("%s: Issued Channel %c Bus Reset. " |
2513 | "%d SCBs aborted\n", ahd_name(ahd), 'A', found); |
2514 | } else { |
2515 | /* |
2516 | * Leave the selection hardware off in case |
2517 | * this abort attempt will affect yet to |
2518 | * be sent commands. |
2519 | */ |
2520 | ahd_outb(ahd, SCSISEQ0,(((ahd)->tags[(0x3a) >> 8])->write_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF), ((((ahd)->tags[ (0x3a) >> 8])->read_1(((ahd)->bshs[(0x3a) >> 8]), ((0x3a) & 0xFF))) & ~0x40))) |
2521 | ahd_inb(ahd, SCSISEQ0) & ~ENSELO)(((ahd)->tags[(0x3a) >> 8])->write_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF), ((((ahd)->tags[ (0x3a) >> 8])->read_1(((ahd)->bshs[(0x3a) >> 8]), ((0x3a) & 0xFF))) & ~0x40))); |
2522 | ahd_assert_atn(ahd); |
2523 | ahd_outb(ahd, MSG_OUT, HOST_MSG)(((ahd)->tags[(0x137) >> 8])->write_1(((ahd)-> bshs[(0x137) >> 8]), ((0x137) & 0xFF), (0xff))); |
2524 | if (scb == NULL((void *)0)) { |
2525 | ahd_print_devinfo(ahd, &devinfo); |
2526 | ahd->msgout_buf[0] = MSG_ABORT_TASK0x0d; |
2527 | ahd->msgout_len = 1; |
2528 | ahd->msgout_index = 0; |
2529 | ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT; |
2530 | } else { |
2531 | ahd_print_path(ahd, scb); |
2532 | scb->flags |= SCB_ABORT; |
2533 | } |
2534 | printf("Protocol violation %s. Attempting to abort.\n", |
2535 | ahd_lookup_phase_entry(curphase)->phasemsg); |
2536 | } |
2537 | } |
2538 | |
2539 | /* |
2540 | * Force renegotiation to occur the next time we initiate |
2541 | * a command to the current device. |
2542 | */ |
2543 | void |
2544 | ahd_force_renegotiation(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) |
2545 | { |
2546 | struct ahd_initiator_tinfo *targ_info; |
2547 | struct ahd_tmode_tstate *tstate; |
2548 | |
2549 | #ifdef AHD_DEBUG |
2550 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { |
2551 | ahd_print_devinfo(ahd, devinfo); |
2552 | printf("Forcing renegotiation\n"); |
2553 | } |
2554 | #endif |
2555 | targ_info = ahd_fetch_transinfo(ahd, |
2556 | devinfo->channel, |
2557 | devinfo->our_scsiid, |
2558 | devinfo->target, |
2559 | &tstate); |
2560 | ahd_update_neg_request(ahd, devinfo, tstate, |
2561 | targ_info, AHD_NEG_IF_NON_ASYNC); |
2562 | } |
2563 | |
2564 | #define AHD_MAX_STEPS2000 2000 |
2565 | void |
2566 | ahd_clear_critical_section(struct ahd_softc *ahd) |
2567 | { |
2568 | ahd_mode_state saved_modes; |
2569 | int stepping; |
2570 | int steps; |
2571 | int first_instr; |
2572 | u_int simode0; |
2573 | u_int simode1; |
2574 | u_int simode3; |
2575 | u_int lqimode0; |
2576 | u_int lqimode1; |
2577 | u_int lqomode0; |
2578 | u_int lqomode1; |
2579 | |
2580 | if (ahd->num_critical_sections == 0) |
2581 | return; |
2582 | |
2583 | stepping = FALSE0; |
2584 | steps = 0; |
2585 | first_instr = 0; |
2586 | simode0 = 0; |
2587 | simode1 = 0; |
2588 | simode3 = 0; |
2589 | lqimode0 = 0; |
2590 | lqimode1 = 0; |
2591 | lqomode0 = 0; |
2592 | lqomode1 = 0; |
2593 | saved_modes = ahd_save_modes(ahd); |
2594 | for (;;) { |
2595 | struct cs *cs; |
2596 | u_int seqaddr; |
2597 | u_int i; |
2598 | |
2599 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
2600 | seqaddr = ahd_inw(ahd, CURADDR0xf4); |
2601 | |
2602 | cs = ahd->critical_sections; |
2603 | for (i = 0; i < ahd->num_critical_sections; i++, cs++) { |
2604 | |
2605 | if (cs->begin < seqaddr && cs->end >= seqaddr) |
2606 | break; |
2607 | } |
2608 | |
2609 | if (i == ahd->num_critical_sections) |
2610 | break; |
2611 | |
2612 | if (steps > AHD_MAX_STEPS2000) { |
2613 | printf("%s: Infinite loop in critical section\n" |
2614 | "%s: First Instruction 0x%x now 0x%x\n", |
2615 | ahd_name(ahd), ahd_name(ahd), first_instr, |
2616 | seqaddr); |
2617 | ahd_dump_card_state(ahd); |
2618 | panic("critical section loop"); |
2619 | } |
2620 | |
2621 | steps++; |
2622 | #ifdef AHD_DEBUG |
2623 | if ((ahd_debug & AHD_SHOW_MISC) != 0) |
2624 | printf("%s: Single stepping at 0x%x\n", ahd_name(ahd), |
2625 | seqaddr); |
2626 | #endif |
2627 | if (stepping == FALSE0) { |
2628 | |
2629 | first_instr = seqaddr; |
2630 | ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); |
2631 | simode0 = ahd_inb(ahd, SIMODE0)(((ahd)->tags[(0x4b) >> 8])->read_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF))); |
2632 | simode3 = ahd_inb(ahd, SIMODE3)(((ahd)->tags[(0x53) >> 8])->read_1(((ahd)->bshs [(0x53) >> 8]), ((0x53) & 0xFF))); |
2633 | lqimode0 = ahd_inb(ahd, LQIMODE0)(((ahd)->tags[(0x50) >> 8])->read_1(((ahd)->bshs [(0x50) >> 8]), ((0x50) & 0xFF))); |
2634 | lqimode1 = ahd_inb(ahd, LQIMODE1)(((ahd)->tags[(0x51) >> 8])->read_1(((ahd)->bshs [(0x51) >> 8]), ((0x51) & 0xFF))); |
2635 | lqomode0 = ahd_inb(ahd, LQOMODE0)(((ahd)->tags[(0x54) >> 8])->read_1(((ahd)->bshs [(0x54) >> 8]), ((0x54) & 0xFF))); |
2636 | lqomode1 = ahd_inb(ahd, LQOMODE1)(((ahd)->tags[(0x55) >> 8])->read_1(((ahd)->bshs [(0x55) >> 8]), ((0x55) & 0xFF))); |
2637 | ahd_outb(ahd, SIMODE0, 0)(((ahd)->tags[(0x4b) >> 8])->write_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF), (0))); |
2638 | ahd_outb(ahd, SIMODE3, 0)(((ahd)->tags[(0x53) >> 8])->write_1(((ahd)->bshs [(0x53) >> 8]), ((0x53) & 0xFF), (0))); |
2639 | ahd_outb(ahd, LQIMODE0, 0)(((ahd)->tags[(0x50) >> 8])->write_1(((ahd)->bshs [(0x50) >> 8]), ((0x50) & 0xFF), (0))); |
2640 | ahd_outb(ahd, LQIMODE1, 0)(((ahd)->tags[(0x51) >> 8])->write_1(((ahd)->bshs [(0x51) >> 8]), ((0x51) & 0xFF), (0))); |
2641 | ahd_outb(ahd, LQOMODE0, 0)(((ahd)->tags[(0x54) >> 8])->write_1(((ahd)->bshs [(0x54) >> 8]), ((0x54) & 0xFF), (0))); |
2642 | ahd_outb(ahd, LQOMODE1, 0)(((ahd)->tags[(0x55) >> 8])->write_1(((ahd)->bshs [(0x55) >> 8]), ((0x55) & 0xFF), (0))); |
2643 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
2644 | simode1 = ahd_inb(ahd, SIMODE1)(((ahd)->tags[(0x57) >> 8])->read_1(((ahd)->bshs [(0x57) >> 8]), ((0x57) & 0xFF))); |
2645 | /* |
2646 | * We don't clear ENBUSFREE. Unfortunately |
2647 | * we cannot re-enable busfree detection within |
2648 | * the current connection, so we must leave it |
2649 | * on while single stepping. |
2650 | */ |
2651 | ahd_outb(ahd, SIMODE1, simode1 & ENBUSFREE)(((ahd)->tags[(0x57) >> 8])->write_1(((ahd)->bshs [(0x57) >> 8]), ((0x57) & 0xFF), (simode1 & 0x08 ))); |
2652 | ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) | STEP)(((ahd)->tags[(0xd6) >> 8])->write_1(((ahd)->bshs [(0xd6) >> 8]), ((0xd6) & 0xFF), ((((ahd)->tags[ (0xd6) >> 8])->read_1(((ahd)->bshs[(0xd6) >> 8]), ((0xd6) & 0xFF))) | 0x04))); |
2653 | stepping = TRUE1; |
2654 | } |
2655 | ahd_outb(ahd, CLRSINT1, CLRBUSFREE)(((ahd)->tags[(0x4c) >> 8])->write_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF), (0x08))); |
2656 | ahd_outb(ahd, CLRINT, CLRSCSIINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x08))); |
2657 | ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode); |
2658 | ahd_outb(ahd, HCNTRL, ahd->unpause)(((ahd)->tags[(0x05) >> 8])->write_1(((ahd)->bshs [(0x05) >> 8]), ((0x05) & 0xFF), (ahd->unpause)) ); |
2659 | while (!ahd_is_paused(ahd)) |
2660 | aic_delay(200)(*delay_func)(200); |
2661 | ahd_update_modes(ahd); |
2662 | } |
2663 | if (stepping) { |
2664 | ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); |
2665 | ahd_outb(ahd, SIMODE0, simode0)(((ahd)->tags[(0x4b) >> 8])->write_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF), (simode0))); |
2666 | ahd_outb(ahd, SIMODE3, simode3)(((ahd)->tags[(0x53) >> 8])->write_1(((ahd)->bshs [(0x53) >> 8]), ((0x53) & 0xFF), (simode3))); |
2667 | ahd_outb(ahd, LQIMODE0, lqimode0)(((ahd)->tags[(0x50) >> 8])->write_1(((ahd)->bshs [(0x50) >> 8]), ((0x50) & 0xFF), (lqimode0))); |
2668 | ahd_outb(ahd, LQIMODE1, lqimode1)(((ahd)->tags[(0x51) >> 8])->write_1(((ahd)->bshs [(0x51) >> 8]), ((0x51) & 0xFF), (lqimode1))); |
2669 | ahd_outb(ahd, LQOMODE0, lqomode0)(((ahd)->tags[(0x54) >> 8])->write_1(((ahd)->bshs [(0x54) >> 8]), ((0x54) & 0xFF), (lqomode0))); |
2670 | ahd_outb(ahd, LQOMODE1, lqomode1)(((ahd)->tags[(0x55) >> 8])->write_1(((ahd)->bshs [(0x55) >> 8]), ((0x55) & 0xFF), (lqomode1))); |
2671 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
2672 | ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) & ~STEP)(((ahd)->tags[(0xd6) >> 8])->write_1(((ahd)->bshs [(0xd6) >> 8]), ((0xd6) & 0xFF), ((((ahd)->tags[ (0xd6) >> 8])->read_1(((ahd)->bshs[(0xd6) >> 8]), ((0xd6) & 0xFF))) & ~0x04))); |
2673 | ahd_outb(ahd, SIMODE1, simode1)(((ahd)->tags[(0x57) >> 8])->write_1(((ahd)->bshs [(0x57) >> 8]), ((0x57) & 0xFF), (simode1))); |
2674 | /* |
2675 | * SCSIINT seems to glitch occasionally when |
2676 | * the interrupt masks are restored. Clear SCSIINT |
2677 | * one more time so that only persistent errors |
2678 | * are seen as a real interrupt. |
2679 | */ |
2680 | ahd_outb(ahd, CLRINT, CLRSCSIINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x08))); |
2681 | } |
2682 | ahd_restore_modes(ahd, saved_modes); |
2683 | } |
2684 | |
2685 | /* |
2686 | * Clear any pending interrupt status. |
2687 | */ |
2688 | void |
2689 | ahd_clear_intstat(struct ahd_softc *ahd) |
2690 | { |
2691 | AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),ahd_assert_modes(ahd, ~((0x01 << (AHD_MODE_UNKNOWN))|(0x01 << (AHD_MODE_CFG))), ~((0x01 << (AHD_MODE_UNKNOWN ))|(0x01 << (AHD_MODE_CFG))), "/usr/src/sys/dev/ic/aic79xx.c" , 2692); |
2692 | ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK))ahd_assert_modes(ahd, ~((0x01 << (AHD_MODE_UNKNOWN))|(0x01 << (AHD_MODE_CFG))), ~((0x01 << (AHD_MODE_UNKNOWN ))|(0x01 << (AHD_MODE_CFG))), "/usr/src/sys/dev/ic/aic79xx.c" , 2692);; |
2693 | /* Clear any interrupt conditions this may have caused */ |
2694 | ahd_outb(ahd, CLRLQIINT0, CLRLQIATNQAS|CLRLQICRCT1|CLRLQICRCT2(((ahd)->tags[(0x50) >> 8])->write_1(((ahd)->bshs [(0x50) >> 8]), ((0x50) & 0xFF), (0x20|0x10|0x08 |0x04 |0x02|0x01))) |
2695 | |CLRLQIBADLQT|CLRLQIATNLQ|CLRLQIATNCMD)(((ahd)->tags[(0x50) >> 8])->write_1(((ahd)->bshs [(0x50) >> 8]), ((0x50) & 0xFF), (0x20|0x10|0x08 |0x04 |0x02|0x01))); |
2696 | ahd_outb(ahd, CLRLQIINT1, CLRLQIPHASE_LQ|CLRLQIPHASE_NLQ|CLRLIQABORT(((ahd)->tags[(0x51) >> 8])->write_1(((ahd)->bshs [(0x51) >> 8]), ((0x51) & 0xFF), (0x80|0x40|0x20 |0x10 |0x08|0x04 |0x02|0x01|0x20))) |
2697 | |CLRLQICRCI_LQ|CLRLQICRCI_NLQ|CLRLQIBADLQI(((ahd)->tags[(0x51) >> 8])->write_1(((ahd)->bshs [(0x51) >> 8]), ((0x51) & 0xFF), (0x80|0x40|0x20 |0x10 |0x08|0x04 |0x02|0x01|0x20))) |
2698 | |CLRLQIOVERI_LQ|CLRLQIOVERI_NLQ|CLRNONPACKREQ)(((ahd)->tags[(0x51) >> 8])->write_1(((ahd)->bshs [(0x51) >> 8]), ((0x51) & 0xFF), (0x80|0x40|0x20 |0x10 |0x08|0x04 |0x02|0x01|0x20))); |
2699 | ahd_outb(ahd, CLRLQOINT0, CLRLQOTARGSCBPERR|CLRLQOSTOPT2|CLRLQOATNLQ(((ahd)->tags[(0x54) >> 8])->write_1(((ahd)->bshs [(0x54) >> 8]), ((0x54) & 0xFF), (0x10|0x08|0x04 |0x02 |0x01))) |
2700 | |CLRLQOATNPKT|CLRLQOTCRC)(((ahd)->tags[(0x54) >> 8])->write_1(((ahd)->bshs [(0x54) >> 8]), ((0x54) & 0xFF), (0x10|0x08|0x04 |0x02 |0x01))); |
2701 | ahd_outb(ahd, CLRLQOINT1, CLRLQOINITSCBPERR|CLRLQOSTOPI2|CLRLQOBADQAS(((ahd)->tags[(0x55) >> 8])->write_1(((ahd)->bshs [(0x55) >> 8]), ((0x55) & 0xFF), (0x10|0x08|0x04 |0x02 |0x01))) |
2702 | |CLRLQOBUSFREE|CLRLQOPHACHGINPKT)(((ahd)->tags[(0x55) >> 8])->write_1(((ahd)->bshs [(0x55) >> 8]), ((0x55) & 0xFF), (0x10|0x08|0x04 |0x02 |0x01))); |
2703 | if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) { |
2704 | ahd_outb(ahd, CLRLQOINT0, 0)(((ahd)->tags[(0x54) >> 8])->write_1(((ahd)->bshs [(0x54) >> 8]), ((0x54) & 0xFF), (0))); |
2705 | ahd_outb(ahd, CLRLQOINT1, 0)(((ahd)->tags[(0x55) >> 8])->write_1(((ahd)->bshs [(0x55) >> 8]), ((0x55) & 0xFF), (0))); |
2706 | } |
2707 | ahd_outb(ahd, CLRSINT3, CLRNTRAMPERR|CLROSRAMPERR)(((ahd)->tags[(0x53) >> 8])->write_1(((ahd)->bshs [(0x53) >> 8]), ((0x53) & 0xFF), (0x02|0x01))); |
2708 | ahd_outb(ahd, CLRSINT1, CLRSELTIMEO|CLRATNO|CLRSCSIRSTI(((ahd)->tags[(0x4c) >> 8])->write_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF), (0x80|0x40|0x20 |0x08 |0x04|0x01))) |
2709 | |CLRBUSFREE|CLRSCSIPERR|CLRREQINIT)(((ahd)->tags[(0x4c) >> 8])->write_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF), (0x80|0x40|0x20 |0x08 |0x04|0x01))); |
2710 | ahd_outb(ahd, CLRSINT0, CLRSELDO|CLRSELDI|CLRSELINGO(((ahd)->tags[(0x4b) >> 8])->write_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF), (0x40|0x20|0x10 |0x08 |0x04))) |
2711 | |CLRIOERR|CLROVERRUN)(((ahd)->tags[(0x4b) >> 8])->write_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF), (0x40|0x20|0x10 |0x08 |0x04))); |
2712 | ahd_outb(ahd, CLRINT, CLRSCSIINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x08))); |
2713 | } |
2714 | |
2715 | /**************************** Debugging Routines ******************************/ |
2716 | #ifdef AHD_DEBUG |
2717 | uint32_t ahd_debug = AHD_DEBUG_OPTS; |
2718 | #endif |
2719 | void |
2720 | ahd_print_scb(struct scb *scb) |
2721 | { |
2722 | struct hardware_scb *hscb; |
2723 | int i; |
2724 | |
2725 | hscb = scb->hscb; |
2726 | printf("scb:%p control:0x%x scsiid:0x%x lun:%d cdb_len:%d\n", |
2727 | (void *)scb, |
2728 | hscb->control, |
2729 | hscb->scsiid, |
2730 | hscb->lun, |
2731 | hscb->cdb_len); |
2732 | printf("Shared Data: "); |
2733 | for (i = 0; i < sizeof(hscb->shared_data.idata.cdb); i++) |
2734 | printf("%#02x", hscb->shared_data.idata.cdb[i]); |
2735 | printf(" dataptr:%#x%x datacnt:%#x sgptr:%#x tag:%#x\n", |
2736 | (uint32_t)((aic_le64toh(hscb->dataptr)((__uint64_t)(hscb->dataptr)) >> 32) & 0xFFFFFFFF), |
2737 | (uint32_t)(aic_le64toh(hscb->dataptr)((__uint64_t)(hscb->dataptr)) & 0xFFFFFFFF), |
2738 | aic_le32toh(hscb->datacnt)((__uint32_t)(hscb->datacnt)), |
2739 | aic_le32toh(hscb->sgptr)((__uint32_t)(hscb->sgptr)), |
2740 | SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag))); |
2741 | ahd_dump_sglist(scb); |
2742 | } |
2743 | |
2744 | void |
2745 | ahd_dump_sglist(struct scb *scb) |
2746 | { |
2747 | int i; |
2748 | |
2749 | if (scb->sg_count > 0) { |
2750 | if ((scb->ahd_softc->flags & AHD_64BIT_ADDRESSING) != 0) { |
2751 | struct ahd_dma64_seg *sg_list; |
2752 | |
2753 | sg_list = (struct ahd_dma64_seg*)scb->sg_list; |
2754 | for (i = 0; i < scb->sg_count; i++) { |
2755 | uint64_t addr; |
2756 | uint32_t len; |
2757 | |
2758 | addr = aic_le64toh(sg_list[i].addr)((__uint64_t)(sg_list[i].addr)); |
2759 | len = aic_le32toh(sg_list[i].len)((__uint32_t)(sg_list[i].len)); |
Value stored to 'len' is never read | |
2760 | printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", |
2761 | i, |
2762 | (uint32_t)((addr >> 32) & 0xFFFFFFFF), |
2763 | (uint32_t)(addr & 0xFFFFFFFF), |
2764 | sg_list[i].len & AHD_SG_LEN_MASK0x00FFFFFF, |
2765 | (sg_list[i].len & AHD_DMA_LAST_SEG0x80000000) |
2766 | ? " Last" : ""); |
2767 | } |
2768 | } else { |
2769 | struct ahd_dma_seg *sg_list; |
2770 | |
2771 | sg_list = (struct ahd_dma_seg*)scb->sg_list; |
2772 | for (i = 0; i < scb->sg_count; i++) { |
2773 | uint32_t len; |
2774 | |
2775 | len = aic_le32toh(sg_list[i].len)((__uint32_t)(sg_list[i].len)); |
2776 | printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", |
2777 | i, |
2778 | (len & AHD_SG_HIGH_ADDR_MASK0x7F000000) >> 24, |
2779 | aic_le32toh(sg_list[i].addr)((__uint32_t)(sg_list[i].addr)), |
2780 | len & AHD_SG_LEN_MASK0x00FFFFFF, |
2781 | len & AHD_DMA_LAST_SEG0x80000000 ? " Last" : ""); |
2782 | } |
2783 | } |
2784 | } |
2785 | } |
2786 | |
2787 | /************************* Transfer Negotiation *******************************/ |
2788 | /* |
2789 | * Allocate per target mode instance (ID we respond to as a target) |
2790 | * transfer negotiation data structures. |
2791 | */ |
2792 | struct ahd_tmode_tstate * |
2793 | ahd_alloc_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel) |
2794 | { |
2795 | struct ahd_tmode_tstate *master_tstate; |
2796 | struct ahd_tmode_tstate *tstate; |
2797 | int i; |
2798 | |
2799 | master_tstate = ahd->enabled_targets[ahd->our_id]; |
2800 | if (ahd->enabled_targets[scsi_id] != NULL((void *)0) |
2801 | && ahd->enabled_targets[scsi_id] != master_tstate) |
2802 | panic("%s: ahd_alloc_tstate - Target already allocated", |
2803 | ahd_name(ahd)); |
2804 | tstate = malloc(sizeof(*tstate), M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008); |
2805 | if (tstate == NULL((void *)0)) |
2806 | return (NULL((void *)0)); |
2807 | |
2808 | /* |
2809 | * If we have allocated a master tstate, copy user settings from |
2810 | * the master tstate (taken from SRAM or the EEPROM) for this |
2811 | * channel, but reset our current and goal settings to async/narrow |
2812 | * until an initiator talks to us. |
2813 | */ |
2814 | if (master_tstate != NULL((void *)0)) { |
2815 | memcpy(tstate, master_tstate, sizeof(*tstate))__builtin_memcpy((tstate), (master_tstate), (sizeof(*tstate)) ); |
2816 | memset(tstate->enabled_luns, 0, sizeof(tstate->enabled_luns))__builtin_memset((tstate->enabled_luns), (0), (sizeof(tstate ->enabled_luns))); |
2817 | for (i = 0; i < 16; i++) { |
2818 | memset(&tstate->transinfo[i].curr, 0,__builtin_memset((&tstate->transinfo[i].curr), (0), (sizeof (tstate->transinfo[i].curr))) |
2819 | sizeof(tstate->transinfo[i].curr))__builtin_memset((&tstate->transinfo[i].curr), (0), (sizeof (tstate->transinfo[i].curr))); |
2820 | memset(&tstate->transinfo[i].goal, 0,__builtin_memset((&tstate->transinfo[i].goal), (0), (sizeof (tstate->transinfo[i].goal))) |
2821 | sizeof(tstate->transinfo[i].goal))__builtin_memset((&tstate->transinfo[i].goal), (0), (sizeof (tstate->transinfo[i].goal))); |
2822 | } |
2823 | } |
2824 | ahd->enabled_targets[scsi_id] = tstate; |
2825 | return (tstate); |
2826 | } |
2827 | |
2828 | #ifdef AHD_TARGET_MODE |
2829 | /* |
2830 | * Free per target mode instance (ID we respond to as a target) |
2831 | * transfer negotiation data structures. |
2832 | */ |
2833 | void |
2834 | ahd_free_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel, int force) |
2835 | { |
2836 | struct ahd_tmode_tstate *tstate; |
2837 | |
2838 | /* |
2839 | * Don't clean up our "master" tstate. |
2840 | * It has our default user settings. |
2841 | */ |
2842 | if (scsi_id == ahd->our_id |
2843 | && force == FALSE0) |
2844 | return; |
2845 | |
2846 | tstate = ahd->enabled_targets[scsi_id]; |
2847 | if (tstate != NULL((void *)0)) |
2848 | free(tstate, M_DEVBUF2, 0); |
2849 | ahd->enabled_targets[scsi_id] = NULL((void *)0); |
2850 | } |
2851 | #endif |
2852 | |
2853 | /* |
2854 | * Called when we have an active connection to a target on the bus, |
2855 | * this function finds the nearest period to the input period limited |
2856 | * by the capabilities of the bus connectivity of and sync settings for |
2857 | * the target. |
2858 | */ |
2859 | void |
2860 | ahd_devlimited_syncrate(struct ahd_softc *ahd, |
2861 | struct ahd_initiator_tinfo *tinfo, |
2862 | u_int *period, u_int *ppr_options, role_t role) |
2863 | { |
2864 | struct ahd_transinfo *transinfo; |
2865 | u_int maxsync; |
2866 | |
2867 | if ((ahd_inb(ahd, SBLKCTL)(((ahd)->tags[(0x4a) >> 8])->read_1(((ahd)->bshs [(0x4a) >> 8]), ((0x4a) & 0xFF))) & ENAB400x08) != 0 |
2868 | && (ahd_inb(ahd, SSTAT2)(((ahd)->tags[(0x4d) >> 8])->read_1(((ahd)->bshs [(0x4d) >> 8]), ((0x4d) & 0xFF))) & EXP_ACTIVE0x10) == 0) { |
2869 | maxsync = AHD_SYNCRATE_PACED0x8; |
2870 | } else { |
2871 | maxsync = AHD_SYNCRATE_ULTRA0xc; |
2872 | /* Can't do DT related options on an SE bus */ |
2873 | *ppr_options &= MSG_EXT_PPR_QAS_REQ0x04; |
2874 | } |
2875 | /* |
2876 | * Never allow a value higher than our current goal |
2877 | * period otherwise we may allow a target initiated |
2878 | * negotiation to go above the limit as set by the |
2879 | * user. In the case of an initiator initiated |
2880 | * sync negotiation, we limit based on the user |
2881 | * setting. This allows the system to still accept |
2882 | * incoming negotiations even if target initiated |
2883 | * negotiation is not performed. |
2884 | */ |
2885 | if (role == ROLE_TARGET) |
2886 | transinfo = &tinfo->user; |
2887 | else |
2888 | transinfo = &tinfo->goal; |
2889 | *ppr_options &= (transinfo->ppr_options|MSG_EXT_PPR_PCOMP_EN0x80); |
2890 | if (transinfo->width == MSG_EXT_WDTR_BUS_8_BIT0x00) { |
2891 | maxsync = MAX(maxsync, AHD_SYNCRATE_ULTRA2)(((maxsync)>(0xa))?(maxsync):(0xa)); |
2892 | *ppr_options &= ~MSG_EXT_PPR_DT_REQ0x02; |
2893 | } |
2894 | if (transinfo->period == 0) { |
2895 | *period = 0; |
2896 | *ppr_options = 0; |
2897 | } else { |
2898 | *period = MAX(*period, transinfo->period)(((*period)>(transinfo->period))?(*period):(transinfo-> period)); |
2899 | ahd_find_syncrate(ahd, period, ppr_options, maxsync); |
2900 | } |
2901 | } |
2902 | |
2903 | /* |
2904 | * Look up the valid period to SCSIRATE conversion in our table. |
2905 | * Return the period and offset that should be sent to the target |
2906 | * if this was the beginning of an SDTR. |
2907 | */ |
2908 | void |
2909 | ahd_find_syncrate(struct ahd_softc *ahd, u_int *period, |
2910 | u_int *ppr_options, u_int maxsync) |
2911 | { |
2912 | if (*period < maxsync) |
2913 | *period = maxsync; |
2914 | |
2915 | if ((*ppr_options & MSG_EXT_PPR_DT_REQ0x02) != 0 |
2916 | && *period > AHD_SYNCRATE_MIN_DT0x19) |
2917 | *ppr_options &= ~MSG_EXT_PPR_DT_REQ0x02; |
2918 | |
2919 | if (*period > AHD_SYNCRATE_MIN0x60) |
2920 | *period = 0; |
2921 | |
2922 | /* Honor PPR option conformance rules. */ |
2923 | if (*period > AHD_SYNCRATE_PACED0x8) |
2924 | *ppr_options &= ~MSG_EXT_PPR_RTI0x40; |
2925 | |
2926 | if ((*ppr_options & MSG_EXT_PPR_IU_REQ0x01) == 0) |
2927 | *ppr_options &= (MSG_EXT_PPR_DT_REQ0x02|MSG_EXT_PPR_QAS_REQ0x04); |
2928 | |
2929 | if ((*ppr_options & MSG_EXT_PPR_DT_REQ0x02) == 0) |
2930 | *ppr_options &= MSG_EXT_PPR_QAS_REQ0x04; |
2931 | |
2932 | /* Skip all PACED only entries if IU is not available */ |
2933 | if ((*ppr_options & MSG_EXT_PPR_IU_REQ0x01) == 0 |
2934 | && *period < AHD_SYNCRATE_DT0x9) |
2935 | *period = AHD_SYNCRATE_DT0x9; |
2936 | |
2937 | /* Skip all DT only entries if DT is not available */ |
2938 | if ((*ppr_options & MSG_EXT_PPR_DT_REQ0x02) == 0 |
2939 | && *period < AHD_SYNCRATE_ULTRA20xa) |
2940 | *period = AHD_SYNCRATE_ULTRA20xa; |
2941 | } |
2942 | |
2943 | /* |
2944 | * Truncate the given synchronous offset to a value the |
2945 | * current adapter type and syncrate are capable of. |
2946 | */ |
2947 | void |
2948 | ahd_validate_offset(struct ahd_softc *ahd, |
2949 | struct ahd_initiator_tinfo *tinfo, |
2950 | u_int period, u_int *offset, int wide, |
2951 | role_t role) |
2952 | { |
2953 | u_int maxoffset; |
2954 | |
2955 | /* Limit offset to what we can do */ |
2956 | if (period == 0) |
2957 | maxoffset = 0; |
2958 | else if (period <= AHD_SYNCRATE_PACED0x8) { |
2959 | if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) |
2960 | maxoffset = MAX_OFFSET_PACED_BUG0x7f; |
2961 | else |
2962 | maxoffset = MAX_OFFSET_PACED0xfe; |
2963 | } else |
2964 | maxoffset = MAX_OFFSET_NON_PACED0x7f; |
2965 | *offset = MIN(*offset, maxoffset)(((*offset)<(maxoffset))?(*offset):(maxoffset)); |
2966 | if (tinfo != NULL((void *)0)) { |
2967 | if (role == ROLE_TARGET) |
2968 | *offset = MIN(*offset, tinfo->user.offset)(((*offset)<(tinfo->user.offset))?(*offset):(tinfo-> user.offset)); |
2969 | else |
2970 | *offset = MIN(*offset, tinfo->goal.offset)(((*offset)<(tinfo->goal.offset))?(*offset):(tinfo-> goal.offset)); |
2971 | } |
2972 | } |
2973 | |
2974 | /* |
2975 | * Truncate the given transfer width parameter to a value the |
2976 | * current adapter type is capable of. |
2977 | */ |
2978 | void |
2979 | ahd_validate_width(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo, |
2980 | u_int *bus_width, role_t role) |
2981 | { |
2982 | switch (*bus_width) { |
2983 | default: |
2984 | if (ahd->features & AHD_WIDE) { |
2985 | /* Respond Wide */ |
2986 | *bus_width = MSG_EXT_WDTR_BUS_16_BIT0x01; |
2987 | break; |
2988 | } |
2989 | /* FALLTHROUGH */ |
2990 | case MSG_EXT_WDTR_BUS_8_BIT0x00: |
2991 | *bus_width = MSG_EXT_WDTR_BUS_8_BIT0x00; |
2992 | break; |
2993 | } |
2994 | if (tinfo != NULL((void *)0)) { |
2995 | if (role == ROLE_TARGET) |
2996 | *bus_width = MIN(tinfo->user.width, *bus_width)(((tinfo->user.width)<(*bus_width))?(tinfo->user.width ):(*bus_width)); |
2997 | else |
2998 | *bus_width = MIN(tinfo->goal.width, *bus_width)(((tinfo->goal.width)<(*bus_width))?(tinfo->goal.width ):(*bus_width)); |
2999 | } |
3000 | } |
3001 | |
3002 | /* |
3003 | * Update the bitmask of targets for which the controller should |
3004 | * negotiate with at the next convenient opportunity. This currently |
3005 | * means the next time we send the initial identify messages for |
3006 | * a new transaction. |
3007 | */ |
3008 | int |
3009 | ahd_update_neg_request(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, |
3010 | struct ahd_tmode_tstate *tstate, |
3011 | struct ahd_initiator_tinfo *tinfo, ahd_neg_type neg_type) |
3012 | { |
3013 | u_int auto_negotiate_orig; |
3014 | |
3015 | auto_negotiate_orig = tstate->auto_negotiate; |
3016 | if (neg_type == AHD_NEG_ALWAYS) { |
3017 | /* |
3018 | * Force our "current" settings to be |
3019 | * unknown so that unless a bus reset |
3020 | * occurs the need to renegotiate is |
3021 | * recorded persistently. |
3022 | */ |
3023 | if ((ahd->features & AHD_WIDE) != 0) |
3024 | tinfo->curr.width = AHD_WIDTH_UNKNOWN0xFF; |
3025 | tinfo->curr.period = AHD_PERIOD_UNKNOWN0xFF; |
3026 | tinfo->curr.offset = AHD_OFFSET_UNKNOWN0xFF; |
3027 | } |
3028 | if (tinfo->curr.period != tinfo->goal.period |
3029 | || tinfo->curr.width != tinfo->goal.width |
3030 | || tinfo->curr.offset != tinfo->goal.offset |
3031 | || tinfo->curr.ppr_options != tinfo->goal.ppr_options |
3032 | || (neg_type == AHD_NEG_IF_NON_ASYNC |
3033 | && (tinfo->goal.offset != 0 |
3034 | || tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT0x00 |
3035 | || tinfo->goal.ppr_options != 0))) |
3036 | tstate->auto_negotiate |= devinfo->target_mask; |
3037 | else |
3038 | tstate->auto_negotiate &= ~devinfo->target_mask; |
3039 | |
3040 | return (auto_negotiate_orig != tstate->auto_negotiate); |
3041 | } |
3042 | |
3043 | /* |
3044 | * Update the user/goal/curr tables of synchronous negotiation |
3045 | * parameters as well as, in the case of a current or active update, |
3046 | * any data structures on the host controller. In the case of an |
3047 | * active update, the specified target is currently talking to us on |
3048 | * the bus, so the transfer parameter update must take effect |
3049 | * immediately. |
3050 | */ |
3051 | void |
3052 | ahd_set_syncrate(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, |
3053 | u_int period, u_int offset, u_int ppr_options, |
3054 | u_int type, int paused) |
3055 | { |
3056 | struct ahd_initiator_tinfo *tinfo; |
3057 | struct ahd_tmode_tstate *tstate; |
3058 | u_int old_period; |
3059 | u_int old_offset; |
3060 | u_int old_ppr; |
3061 | int active; |
3062 | int update_needed; |
3063 | |
3064 | active = (type & AHD_TRANS_ACTIVE0x03) == AHD_TRANS_ACTIVE0x03; |
3065 | update_needed = 0; |
3066 | |
3067 | if (period == 0 || offset == 0) { |
3068 | period = 0; |
3069 | offset = 0; |
3070 | } |
3071 | |
3072 | tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid, |
3073 | devinfo->target, &tstate); |
3074 | |
3075 | if ((type & AHD_TRANS_USER0x08) != 0) { |
3076 | tinfo->user.period = period; |
3077 | tinfo->user.offset = offset; |
3078 | tinfo->user.ppr_options = ppr_options; |
3079 | } |
3080 | |
3081 | if ((type & AHD_TRANS_GOAL0x04) != 0) { |
3082 | tinfo->goal.period = period; |
3083 | tinfo->goal.offset = offset; |
3084 | tinfo->goal.ppr_options = ppr_options; |
3085 | } |
3086 | |
3087 | old_period = tinfo->curr.period; |
3088 | old_offset = tinfo->curr.offset; |
3089 | old_ppr = tinfo->curr.ppr_options; |
3090 | |
3091 | if ((type & AHD_TRANS_CUR0x01) != 0 |
3092 | && (old_period != period |
3093 | || old_offset != offset |
3094 | || old_ppr != ppr_options)) { |
3095 | |
3096 | update_needed++; |
3097 | |
3098 | tinfo->curr.period = period; |
3099 | tinfo->curr.offset = offset; |
3100 | tinfo->curr.ppr_options = ppr_options; |
3101 | #if 0 |
3102 | ahd_send_async(ahd, devinfo->channel, devinfo->target, |
3103 | CAM_LUN_WILDCARD-1, AC_TRANSFER_NEG, NULL((void *)0)); |
3104 | #endif |
3105 | if (1 /*bootverbose*/) { |
3106 | if (offset != 0) { |
3107 | int options; |
3108 | |
3109 | printf("%s: target %d synchronous with " |
3110 | "period = 0x%x, offset = 0x%x", |
3111 | ahd_name(ahd), devinfo->target, |
3112 | period, offset); |
3113 | options = 0; |
3114 | if ((ppr_options & MSG_EXT_PPR_RD_STRM0x20) != 0) { |
3115 | printf("(RDSTRM"); |
3116 | options++; |
3117 | } |
3118 | if ((ppr_options & MSG_EXT_PPR_DT_REQ0x02) != 0) { |
3119 | printf("%s", options ? "|DT" : "(DT"); |
3120 | options++; |
3121 | } |
3122 | if ((ppr_options & MSG_EXT_PPR_IU_REQ0x01) != 0) { |
3123 | printf("%s", options ? "|IU" : "(IU"); |
3124 | options++; |
3125 | } |
3126 | if ((ppr_options & MSG_EXT_PPR_RTI0x40) != 0) { |
3127 | printf("%s", options ? "|RTI" : "(RTI"); |
3128 | options++; |
3129 | } |
3130 | if ((ppr_options & MSG_EXT_PPR_QAS_REQ0x04) != 0) { |
3131 | printf("%s", options ? "|QAS" : "(QAS"); |
3132 | options++; |
3133 | } |
3134 | if (options != 0) |
3135 | printf(")\n"); |
3136 | else |
3137 | printf("\n"); |
3138 | } else { |
3139 | printf("%s: target %d using " |
3140 | "asynchronous transfers%s\n", |
3141 | ahd_name(ahd), devinfo->target, |
3142 | (ppr_options & MSG_EXT_PPR_QAS_REQ0x04) != 0 |
3143 | ? "(QAS)" : ""); |
3144 | } |
3145 | } |
3146 | } |
3147 | /* |
3148 | * Always refresh the neg-table to handle the case of the |
3149 | * sequencer setting the ENATNO bit for a MK_MESSAGE request. |
3150 | * We will always renegotiate in that case if this is a |
3151 | * packetized request. Also manage the busfree expected flag |
3152 | * from this common routine so that we catch changes due to |
3153 | * WDTR or SDTR messages. |
3154 | */ |
3155 | if ((type & AHD_TRANS_CUR0x01) != 0) { |
3156 | if (!paused) |
3157 | ahd_pause(ahd); |
3158 | ahd_update_neg_table(ahd, devinfo, &tinfo->curr); |
3159 | if (!paused) |
3160 | ahd_unpause(ahd); |
3161 | if (ahd->msg_type != MSG_TYPE_NONE) { |
3162 | if ((old_ppr & MSG_EXT_PPR_IU_REQ0x01) |
3163 | != (ppr_options & MSG_EXT_PPR_IU_REQ0x01)) { |
3164 | #ifdef AHD_DEBUG |
3165 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { |
3166 | ahd_print_devinfo(ahd, devinfo); |
3167 | printf("Expecting IU Change busfree\n"); |
3168 | } |
3169 | #endif |
3170 | ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE |
3171 | | MSG_FLAG_IU_REQ_CHANGED; |
3172 | } |
3173 | if ((old_ppr & MSG_EXT_PPR_IU_REQ0x01) != 0) { |
3174 | #ifdef AHD_DEBUG |
3175 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) |
3176 | printf("PPR with IU_REQ outstanding\n"); |
3177 | #endif |
3178 | ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE; |
3179 | } |
3180 | } |
3181 | } |
3182 | |
3183 | update_needed += ahd_update_neg_request(ahd, devinfo, tstate, |
3184 | tinfo, AHD_NEG_TO_GOAL); |
3185 | |
3186 | if (update_needed && active) |
3187 | ahd_update_pending_scbs(ahd); |
3188 | } |
3189 | |
3190 | /* |
3191 | * Update the user/goal/curr tables of wide negotiation |
3192 | * parameters as well as, in the case of a current or active update, |
3193 | * any data structures on the host controller. In the case of an |
3194 | * active update, the specified target is currently talking to us on |
3195 | * the bus, so the transfer parameter update must take effect |
3196 | * immediately. |
3197 | */ |
3198 | void |
3199 | ahd_set_width(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, |
3200 | u_int width, u_int type, int paused) |
3201 | { |
3202 | struct ahd_initiator_tinfo *tinfo; |
3203 | struct ahd_tmode_tstate *tstate; |
3204 | u_int oldwidth; |
3205 | int active; |
3206 | int update_needed; |
3207 | |
3208 | active = (type & AHD_TRANS_ACTIVE0x03) == AHD_TRANS_ACTIVE0x03; |
3209 | update_needed = 0; |
3210 | tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid, |
3211 | devinfo->target, &tstate); |
3212 | |
3213 | if ((type & AHD_TRANS_USER0x08) != 0) |
3214 | tinfo->user.width = width; |
3215 | |
3216 | if ((type & AHD_TRANS_GOAL0x04) != 0) |
3217 | tinfo->goal.width = width; |
3218 | |
3219 | oldwidth = tinfo->curr.width; |
3220 | if ((type & AHD_TRANS_CUR0x01) != 0 && oldwidth != width) { |
3221 | |
3222 | update_needed++; |
3223 | |
3224 | tinfo->curr.width = width; |
3225 | #if 0 |
3226 | ahd_send_async(ahd, devinfo->channel, devinfo->target, |
3227 | CAM_LUN_WILDCARD-1, AC_TRANSFER_NEG, NULL((void *)0)); |
3228 | #endif |
3229 | if (bootverbose0) { |
3230 | printf("%s: target %d using %dbit transfers\n", |
3231 | ahd_name(ahd), devinfo->target, |
3232 | 8 * (0x01 << width)); |
3233 | } |
3234 | } |
3235 | |
3236 | if ((type & AHD_TRANS_CUR0x01) != 0) { |
3237 | if (!paused) |
3238 | ahd_pause(ahd); |
3239 | ahd_update_neg_table(ahd, devinfo, &tinfo->curr); |
3240 | if (!paused) |
3241 | ahd_unpause(ahd); |
3242 | } |
3243 | |
3244 | update_needed += ahd_update_neg_request(ahd, devinfo, tstate, |
3245 | tinfo, AHD_NEG_TO_GOAL); |
3246 | if (update_needed && active) |
3247 | ahd_update_pending_scbs(ahd); |
3248 | |
3249 | } |
3250 | |
3251 | /* |
3252 | * Update the current state of tagged queuing for a given target. |
3253 | */ |
3254 | void |
3255 | ahd_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, |
3256 | ahd_queue_alg alg) |
3257 | { |
3258 | ahd_platform_set_tags(ahd, devinfo, alg); |
3259 | #if 0 |
3260 | ahd_send_async(ahd, devinfo->channel, devinfo->target, |
3261 | devinfo->lun, AC_TRANSFER_NEG, &alg); |
3262 | #endif |
3263 | } |
3264 | |
3265 | void |
3266 | ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, |
3267 | struct ahd_transinfo *tinfo) |
3268 | { |
3269 | ahd_mode_state saved_modes; |
3270 | u_int period; |
3271 | u_int ppr_opts; |
3272 | u_int con_opts; |
3273 | u_int offset; |
3274 | u_int saved_negoaddr; |
3275 | uint8_t iocell_opts[sizeof(ahd->iocell_opts)]; |
3276 | |
3277 | saved_modes = ahd_save_modes(ahd); |
3278 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
3279 | |
3280 | saved_negoaddr = ahd_inb(ahd, NEGOADDR)(((ahd)->tags[(0x60) >> 8])->read_1(((ahd)->bshs [(0x60) >> 8]), ((0x60) & 0xFF))); |
3281 | ahd_outb(ahd, NEGOADDR, devinfo->target)(((ahd)->tags[(0x60) >> 8])->write_1(((ahd)->bshs [(0x60) >> 8]), ((0x60) & 0xFF), (devinfo->target ))); |
3282 | period = tinfo->period; |
3283 | offset = tinfo->offset; |
3284 | memcpy(iocell_opts, ahd->iocell_opts, sizeof(ahd->iocell_opts))__builtin_memcpy((iocell_opts), (ahd->iocell_opts), (sizeof (ahd->iocell_opts))); |
3285 | ppr_opts = tinfo->ppr_options & (MSG_EXT_PPR_QAS_REQ0x04|MSG_EXT_PPR_DT_REQ0x02 |
3286 | |MSG_EXT_PPR_IU_REQ0x01|MSG_EXT_PPR_RTI0x40); |
3287 | con_opts = 0; |
3288 | if (period == 0) |
3289 | period = AHD_SYNCRATE_ASYNC0xFF; |
3290 | if (period == AHD_SYNCRATE_1600x8) { |
3291 | |
3292 | if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) { |
3293 | /* |
3294 | * When the SPI4 spec was finalized, PACE transfers |
3295 | * was not made a configurable option in the PPR |
3296 | * message. Instead it is assumed to be enabled for |
3297 | * any syncrate faster than 80MHz. Nevertheless, |
3298 | * Harpoon2A4 allows this to be configurable. |
3299 | * |
3300 | * Harpoon2A4 also assumes at most 2 data bytes per |
3301 | * negotiated REQ/ACK offset. Paced transfers take |
3302 | * 4, so we must adjust our offset. |
3303 | */ |
3304 | ppr_opts |= PPROPT_PACE0x08; |
3305 | offset *= 2; |
3306 | |
3307 | /* |
3308 | * Harpoon2A assumed that there would be a |
3309 | * fallback rate between 160MHz and 80MHz, |
3310 | * so 7 is used as the period factor rather |
3311 | * than 8 for 160MHz. |
3312 | */ |
3313 | period = AHD_SYNCRATE_REVA_1600x7; |
3314 | } |
3315 | if ((tinfo->ppr_options & MSG_EXT_PPR_PCOMP_EN0x80) == 0) |
3316 | iocell_opts[AHD_PRECOMP_SLEW_INDEX(0x04 - 0x04)] &= |
3317 | ~AHD_PRECOMP_MASK0x07; |
3318 | } else { |
3319 | /* |
3320 | * Precomp should be disabled for non-paced transfers. |
3321 | */ |
3322 | iocell_opts[AHD_PRECOMP_SLEW_INDEX(0x04 - 0x04)] &= ~AHD_PRECOMP_MASK0x07; |
3323 | |
3324 | if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0 |
3325 | && (ppr_opts & MSG_EXT_PPR_DT_REQ0x02) != 0 |
3326 | && (ppr_opts & MSG_EXT_PPR_IU_REQ0x01) == 0) { |
3327 | /* |
3328 | * Slow down our CRC interval to be |
3329 | * compatible with non-packetized |
3330 | * U160 devices that can't handle a |
3331 | * CRC at full speed. |
3332 | */ |
3333 | con_opts |= ENSLOWCRC0x08; |
3334 | } |
3335 | |
3336 | if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) { |
3337 | /* |
3338 | * On H2A4, revert to a slower slewrate |
3339 | * on non-paced transfers. |
3340 | */ |
3341 | iocell_opts[AHD_PRECOMP_SLEW_INDEX(0x04 - 0x04)] &= |
3342 | ~AHD_SLEWRATE_MASK0x78; |
3343 | } |
3344 | } |
3345 | |
3346 | ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW)(((ahd)->tags[(0x65) >> 8])->write_1(((ahd)->bshs [(0x65) >> 8]), ((0x65) & 0xFF), (0x04))); |
3347 | ahd_outb(ahd, ANNEXDAT, iocell_opts[AHD_PRECOMP_SLEW_INDEX])(((ahd)->tags[(0x66) >> 8])->write_1(((ahd)->bshs [(0x66) >> 8]), ((0x66) & 0xFF), (iocell_opts[(0x04 - 0x04)]))); |
3348 | ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_AMPLITUDE)(((ahd)->tags[(0x65) >> 8])->write_1(((ahd)->bshs [(0x65) >> 8]), ((0x65) & 0xFF), (0x06))); |
3349 | ahd_outb(ahd, ANNEXDAT, iocell_opts[AHD_AMPLITUDE_INDEX])(((ahd)->tags[(0x66) >> 8])->write_1(((ahd)->bshs [(0x66) >> 8]), ((0x66) & 0xFF), (iocell_opts[(0x06 - 0x04)]))); |
3350 | |
3351 | ahd_outb(ahd, NEGPERIOD, period)(((ahd)->tags[(0x61) >> 8])->write_1(((ahd)->bshs [(0x61) >> 8]), ((0x61) & 0xFF), (period))); |
3352 | ahd_outb(ahd, NEGPPROPTS, ppr_opts)(((ahd)->tags[(0x63) >> 8])->write_1(((ahd)->bshs [(0x63) >> 8]), ((0x63) & 0xFF), (ppr_opts))); |
3353 | ahd_outb(ahd, NEGOFFSET, offset)(((ahd)->tags[(0x62) >> 8])->write_1(((ahd)->bshs [(0x62) >> 8]), ((0x62) & 0xFF), (offset))); |
3354 | |
3355 | if (tinfo->width == MSG_EXT_WDTR_BUS_16_BIT0x01) |
3356 | con_opts |= WIDEXFER0x01; |
3357 | |
3358 | /* |
3359 | * During packetized transfers, the target will |
3360 | * give us the opportunity to send command packets |
3361 | * without us asserting attention. |
3362 | */ |
3363 | if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ0x01) == 0) |
3364 | con_opts |= ENAUTOATNO0x02; |
3365 | ahd_outb(ahd, NEGCONOPTS, con_opts)(((ahd)->tags[(0x64) >> 8])->write_1(((ahd)->bshs [(0x64) >> 8]), ((0x64) & 0xFF), (con_opts))); |
3366 | ahd_outb(ahd, NEGOADDR, saved_negoaddr)(((ahd)->tags[(0x60) >> 8])->write_1(((ahd)->bshs [(0x60) >> 8]), ((0x60) & 0xFF), (saved_negoaddr))); |
3367 | ahd_restore_modes(ahd, saved_modes); |
3368 | } |
3369 | |
3370 | /* |
3371 | * When the transfer settings for a connection change, setup for |
3372 | * negotiation in pending SCBs to effect the change as quickly as |
3373 | * possible. We also cancel any negotiations that are scheduled |
3374 | * for inflight SCBs that have not been started yet. |
3375 | */ |
3376 | void |
3377 | ahd_update_pending_scbs(struct ahd_softc *ahd) |
3378 | { |
3379 | struct scb *pending_scb; |
3380 | int pending_scb_count; |
3381 | int paused; |
3382 | u_int saved_scbptr; |
3383 | ahd_mode_state saved_modes; |
3384 | |
3385 | /* |
3386 | * Traverse the pending SCB list and ensure that all of the |
3387 | * SCBs there have the proper settings. We can only safely |
3388 | * clear the negotiation required flag (setting requires the |
3389 | * execution queue to be modified) and this is only possible |
3390 | * if we are not already attempting to select out for this |
3391 | * SCB. For this reason, all callers only call this routine |
3392 | * if we are changing the negotiation settings for the currently |
3393 | * active transaction on the bus. |
3394 | */ |
3395 | pending_scb_count = 0; |
3396 | TAILQ_FOREACH(pending_scb, &ahd->pending_scbs, next)for((pending_scb) = ((&ahd->pending_scbs)->tqh_first ); (pending_scb) != ((void *)0); (pending_scb) = ((pending_scb )->next.tqe_next)) { |
3397 | struct ahd_devinfo devinfo; |
3398 | struct ahd_initiator_tinfo *tinfo; |
3399 | struct ahd_tmode_tstate *tstate; |
3400 | |
3401 | ahd_scb_devinfo(ahd, &devinfo, pending_scb); |
3402 | tinfo = ahd_fetch_transinfo(ahd, devinfo.channel, |
3403 | devinfo.our_scsiid, |
3404 | devinfo.target, &tstate); |
3405 | if ((tstate->auto_negotiate & devinfo.target_mask) == 0 |
3406 | && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) { |
3407 | pending_scb->flags &= ~SCB_AUTO_NEGOTIATE; |
3408 | pending_scb->hscb->control &= ~MK_MESSAGE0x10; |
3409 | } |
3410 | ahd_sync_scb(ahd, pending_scb, |
3411 | BUS_DMASYNC_PREREAD0x01|BUS_DMASYNC_PREWRITE0x04); |
3412 | pending_scb_count++; |
3413 | } |
3414 | |
3415 | if (pending_scb_count == 0) |
3416 | return; |
3417 | |
3418 | if (ahd_is_paused(ahd)) { |
3419 | paused = 1; |
3420 | } else { |
3421 | paused = 0; |
3422 | ahd_pause(ahd); |
3423 | } |
3424 | |
3425 | /* |
3426 | * Force the sequencer to reinitialize the selection for |
3427 | * the command at the head of the execution queue if it |
3428 | * has already been setup. The negotiation changes may |
3429 | * effect whether we select-out with ATN. It is only |
3430 | * safe to clear ENSELO when the bus is not free and no |
3431 | * selection is in progress or completed. |
3432 | */ |
3433 | saved_modes = ahd_save_modes(ahd); |
3434 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
3435 | if ((ahd_inb(ahd, SCSISIGI)(((ahd)->tags[(0x41) >> 8])->read_1(((ahd)->bshs [(0x41) >> 8]), ((0x41) & 0xFF))) & BSYI0x04) != 0 |
3436 | && (ahd_inb(ahd, SSTAT0)(((ahd)->tags[(0x4b) >> 8])->read_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF))) & (SELDO0x40|SELINGO0x10)) == 0) |
3437 | ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO)(((ahd)->tags[(0x3a) >> 8])->write_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF), ((((ahd)->tags[ (0x3a) >> 8])->read_1(((ahd)->bshs[(0x3a) >> 8]), ((0x3a) & 0xFF))) & ~0x40))); |
3438 | saved_scbptr = ahd_get_scbptr(ahd); |
3439 | /* Ensure that the hscbs down on the card match the new information */ |
3440 | TAILQ_FOREACH(pending_scb, &ahd->pending_scbs, next)for((pending_scb) = ((&ahd->pending_scbs)->tqh_first ); (pending_scb) != ((void *)0); (pending_scb) = ((pending_scb )->next.tqe_next)) { |
3441 | u_int scb_tag; |
3442 | u_int control; |
3443 | |
3444 | scb_tag = SCB_GET_TAG(pending_scb)((__uint16_t)(pending_scb->hscb->tag)); |
3445 | ahd_set_scbptr(ahd, scb_tag); |
3446 | control = ahd_inb_scbram(ahd, SCB_CONTROL0x192); |
3447 | control &= ~MK_MESSAGE0x10; |
3448 | control |= pending_scb->hscb->control & MK_MESSAGE0x10; |
3449 | ahd_outb(ahd, SCB_CONTROL, control)(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (control))); |
3450 | } |
3451 | ahd_set_scbptr(ahd, saved_scbptr); |
3452 | ahd_restore_modes(ahd, saved_modes); |
3453 | |
3454 | if (paused == 0) |
3455 | ahd_unpause(ahd); |
3456 | } |
3457 | |
3458 | /**************************** Pathing Information *****************************/ |
3459 | void |
3460 | ahd_fetch_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) |
3461 | { |
3462 | ahd_mode_state saved_modes; |
3463 | u_int saved_scsiid; |
3464 | role_t role; |
3465 | int our_id; |
3466 | |
3467 | saved_modes = ahd_save_modes(ahd); |
3468 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
3469 | |
3470 | if (ahd_inb(ahd, SSTAT0)(((ahd)->tags[(0x4b) >> 8])->read_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF))) & TARGET0x80) |
3471 | role = ROLE_TARGET; |
3472 | else |
3473 | role = ROLE_INITIATOR; |
3474 | |
3475 | if (role == ROLE_TARGET |
3476 | && (ahd_inb(ahd, SEQ_FLAGS)(((ahd)->tags[(0x139) >> 8])->read_1(((ahd)->bshs [(0x139) >> 8]), ((0x139) & 0xFF))) & CMDPHASE_PENDING0x08) != 0) { |
3477 | /* We were selected, so pull our id from TARGIDIN */ |
3478 | our_id = ahd_inb(ahd, TARGIDIN)(((ahd)->tags[(0x48) >> 8])->read_1(((ahd)->bshs [(0x48) >> 8]), ((0x48) & 0xFF))) & OID0x0f; |
3479 | } else if (role == ROLE_TARGET) |
3480 | our_id = ahd_inb(ahd, TOWNID)(((ahd)->tags[(0x69) >> 8])->read_1(((ahd)->bshs [(0x69) >> 8]), ((0x69) & 0xFF))); |
3481 | else |
3482 | our_id = ahd_inb(ahd, IOWNID)(((ahd)->tags[(0x67) >> 8])->read_1(((ahd)->bshs [(0x67) >> 8]), ((0x67) & 0xFF))); |
3483 | |
3484 | saved_scsiid = ahd_inb(ahd, SAVED_SCSIID)(((ahd)->tags[(0x13a) >> 8])->read_1(((ahd)->bshs [(0x13a) >> 8]), ((0x13a) & 0xFF))); |
3485 | ahd_compile_devinfo(devinfo, |
3486 | our_id, |
3487 | SCSIID_TARGET(ahd, saved_scsiid)(((saved_scsiid) & 0xf0) >> 0x04), |
3488 | ahd_inb(ahd, SAVED_LUN)(((ahd)->tags[(0x13b) >> 8])->read_1(((ahd)->bshs [(0x13b) >> 8]), ((0x13b) & 0xFF))), |
3489 | SCSIID_CHANNEL(ahd, saved_scsiid)('A'), |
3490 | role); |
3491 | ahd_restore_modes(ahd, saved_modes); |
3492 | } |
3493 | |
3494 | void |
3495 | ahd_print_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) |
3496 | { |
3497 | printf("%s:%c:%d:%d: ", ahd_name(ahd), 'A', |
3498 | devinfo->target, devinfo->lun); |
3499 | } |
3500 | |
3501 | struct ahd_phase_table_entry* |
3502 | ahd_lookup_phase_entry(int phase) |
3503 | { |
3504 | struct ahd_phase_table_entry *entry; |
3505 | struct ahd_phase_table_entry *last_entry; |
3506 | |
3507 | /* |
3508 | * num_phases doesn't include the default entry which |
3509 | * will be returned if the phase doesn't match. |
3510 | */ |
3511 | last_entry = &ahd_phase_table[num_phases]; |
3512 | for (entry = ahd_phase_table; entry < last_entry; entry++) { |
3513 | if (phase == entry->phase) |
3514 | break; |
3515 | } |
3516 | return (entry); |
3517 | } |
3518 | |
3519 | void |
3520 | ahd_compile_devinfo(struct ahd_devinfo *devinfo, u_int our_id, u_int target, |
3521 | u_int lun, char channel, role_t role) |
3522 | { |
3523 | devinfo->our_scsiid = our_id; |
3524 | devinfo->target = target; |
3525 | devinfo->lun = lun; |
3526 | devinfo->target_offset = target; |
3527 | devinfo->channel = channel; |
3528 | devinfo->role = role; |
3529 | if (channel == 'B') |
3530 | devinfo->target_offset += 8; |
3531 | devinfo->target_mask = (0x01 << devinfo->target_offset); |
3532 | } |
3533 | |
3534 | void |
3535 | ahd_scb_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, |
3536 | struct scb *scb) |
3537 | { |
3538 | role_t role; |
3539 | int our_id; |
3540 | |
3541 | our_id = SCSIID_OUR_ID(scb->hscb->scsiid)((scb->hscb->scsiid) & 0x0f); |
3542 | role = ROLE_INITIATOR; |
3543 | if ((scb->hscb->control & TARGET_SCB0x80) != 0) |
3544 | role = ROLE_TARGET; |
3545 | ahd_compile_devinfo(devinfo, our_id, SCB_GET_TARGET(ahd, scb)((((scb)->hscb->scsiid) & 0xf0) >> 0x04), |
3546 | SCB_GET_LUN(scb)((scb)->hscb->lun), SCB_GET_CHANNEL(ahd, scb)('A'), role); |
3547 | } |
3548 | |
3549 | |
3550 | /************************ Message Phase Processing ****************************/ |
3551 | /* |
3552 | * When an initiator transaction with the MK_MESSAGE flag either reconnects |
3553 | * or enters the initial message out phase, we are interrupted. Fill our |
3554 | * outgoing message buffer with the appropriate message and begin handing |
3555 | * the message phase(s) manually. |
3556 | */ |
3557 | void |
3558 | ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, |
3559 | struct scb *scb) |
3560 | { |
3561 | /* |
3562 | * To facilitate adding multiple messages together, |
3563 | * each routine should increment the index and len |
3564 | * variables instead of setting them explicitly. |
3565 | */ |
3566 | ahd->msgout_index = 0; |
3567 | ahd->msgout_len = 0; |
3568 | |
3569 | if (ahd_currently_packetized(ahd)) |
3570 | ahd->msg_flags |= MSG_FLAG_PACKETIZED; |
3571 | |
3572 | if (ahd->send_msg_perror |
3573 | && ahd_inb(ahd, MSG_OUT)(((ahd)->tags[(0x137) >> 8])->read_1(((ahd)->bshs [(0x137) >> 8]), ((0x137) & 0xFF))) == HOST_MSG0xff) { |
3574 | ahd->msgout_buf[ahd->msgout_index++] = ahd->send_msg_perror; |
3575 | ahd->msgout_len++; |
3576 | ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT; |
3577 | #ifdef AHD_DEBUG |
3578 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) |
3579 | printf("Setting up for Parity Error delivery\n"); |
3580 | #endif |
3581 | return; |
3582 | } else if (scb == NULL((void *)0)) { |
3583 | printf("%s: WARNING. No pending message for " |
3584 | "I_T msgin. Issuing NO-OP\n", ahd_name(ahd)); |
3585 | ahd->msgout_buf[ahd->msgout_index++] = MSG_NOOP0x08; |
3586 | ahd->msgout_len++; |
3587 | ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT; |
3588 | return; |
3589 | } |
3590 | |
3591 | if ((scb->flags & SCB_DEVICE_RESET) == 0 |
3592 | && (scb->flags & SCB_PACKETIZED) == 0 |
3593 | && ahd_inb(ahd, MSG_OUT)(((ahd)->tags[(0x137) >> 8])->read_1(((ahd)->bshs [(0x137) >> 8]), ((0x137) & 0xFF))) == MSG_IDENTIFYFLAG0x80) { |
3594 | u_int identify_msg; |
3595 | |
3596 | identify_msg = MSG_IDENTIFYFLAG0x80 | SCB_GET_LUN(scb)((scb)->hscb->lun); |
3597 | if ((scb->hscb->control & DISCENB0x40) != 0) |
3598 | identify_msg |= MSG_IDENTIFY_DISCFLAG0x40; |
3599 | ahd->msgout_buf[ahd->msgout_index++] = identify_msg; |
3600 | ahd->msgout_len++; |
3601 | |
3602 | if ((scb->hscb->control & TAG_ENB0x20) != 0) { |
3603 | ahd->msgout_buf[ahd->msgout_index++] = |
3604 | scb->hscb->control & (TAG_ENB0x20|SCB_TAG_TYPE0x03); |
3605 | ahd->msgout_buf[ahd->msgout_index++] = SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)); |
3606 | ahd->msgout_len += 2; |
3607 | } |
3608 | } |
3609 | |
3610 | if (scb->flags & SCB_DEVICE_RESET) { |
3611 | ahd->msgout_buf[ahd->msgout_index++] = MSG_BUS_DEV_RESET0x0c; |
3612 | ahd->msgout_len++; |
3613 | ahd_print_path(ahd, scb); |
3614 | printf("Bus Device Reset Message Sent\n"); |
3615 | /* |
3616 | * Clear our selection hardware in advance of |
3617 | * the busfree. We may have an entry in the waiting |
3618 | * Q for this target, and we don't want to go about |
3619 | * selecting while we handle the busfree and blow it |
3620 | * away. |
3621 | */ |
3622 | ahd_outb(ahd, SCSISEQ0, 0)(((ahd)->tags[(0x3a) >> 8])->write_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF), (0))); |
3623 | } else if ((scb->flags & SCB_ABORT) != 0) { |
3624 | |
3625 | if ((scb->hscb->control & TAG_ENB0x20) != 0) { |
3626 | ahd->msgout_buf[ahd->msgout_index++] = MSG_ABORT_TAG0x0d; |
3627 | } else { |
3628 | ahd->msgout_buf[ahd->msgout_index++] = MSG_ABORT0x06; |
3629 | } |
3630 | ahd->msgout_len++; |
3631 | ahd_print_path(ahd, scb); |
3632 | printf("Abort%s Message Sent\n", |
3633 | (scb->hscb->control & TAG_ENB0x20) != 0 ? " Tag" : ""); |
3634 | /* |
3635 | * Clear our selection hardware in advance of |
3636 | * the busfree. We may have an entry in the waiting |
3637 | * Q for this target, and we don't want to go about |
3638 | * selecting while we handle the busfree and blow it |
3639 | * away. |
3640 | */ |
3641 | ahd_outb(ahd, SCSISEQ0, 0)(((ahd)->tags[(0x3a) >> 8])->write_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF), (0))); |
3642 | } else if ((scb->flags & (SCB_AUTO_NEGOTIATE|SCB_NEGOTIATE)) != 0) { |
3643 | ahd_build_transfer_msg(ahd, devinfo); |
3644 | /* |
3645 | * Clear our selection hardware in advance of potential |
3646 | * PPR IU status change busfree. We may have an entry in |
3647 | * the waiting Q for this target, and we don't want to go |
3648 | * about selecting while we handle the busfree and blow |
3649 | * it away. |
3650 | */ |
3651 | ahd_outb(ahd, SCSISEQ0, 0)(((ahd)->tags[(0x3a) >> 8])->write_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF), (0))); |
3652 | } else { |
3653 | printf("ahd_intr: AWAITING_MSG for an SCB that " |
3654 | "does not have a waiting message\n"); |
3655 | printf("SCSIID = %x, target_mask = %x\n", scb->hscb->scsiid, |
3656 | devinfo->target_mask); |
3657 | panic("SCB = %d, SCB Control = %x:%x, MSG_OUT = %x " |
3658 | "SCB flags = %x", SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)), scb->hscb->control, |
3659 | ahd_inb_scbram(ahd, SCB_CONTROL0x192), ahd_inb(ahd, MSG_OUT)(((ahd)->tags[(0x137) >> 8])->read_1(((ahd)->bshs [(0x137) >> 8]), ((0x137) & 0xFF))), |
3660 | scb->flags); |
3661 | } |
3662 | |
3663 | /* |
3664 | * Clear the MK_MESSAGE flag from the SCB so we aren't |
3665 | * asked to send this message again. |
3666 | */ |
3667 | ahd_outb(ahd, SCB_CONTROL,(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (ahd_inb_scbram (ahd, 0x192) & ~0x10))) |
3668 | ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE)(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (ahd_inb_scbram (ahd, 0x192) & ~0x10))); |
3669 | scb->hscb->control &= ~MK_MESSAGE0x10; |
3670 | ahd->msgout_index = 0; |
3671 | ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT; |
3672 | } |
3673 | |
3674 | /* |
3675 | * Build an appropriate transfer negotiation message for the |
3676 | * currently active target. |
3677 | */ |
3678 | void |
3679 | ahd_build_transfer_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) |
3680 | { |
3681 | /* |
3682 | * We need to initiate transfer negotiations. |
3683 | * If our current and goal settings are identical, |
3684 | * we want to renegotiate due to a check condition. |
3685 | */ |
3686 | struct ahd_initiator_tinfo *tinfo; |
3687 | struct ahd_tmode_tstate *tstate; |
3688 | int dowide; |
3689 | int dosync; |
3690 | int doppr; |
3691 | u_int period; |
3692 | u_int ppr_options; |
3693 | u_int offset; |
3694 | |
3695 | tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid, |
3696 | devinfo->target, &tstate); |
3697 | /* |
3698 | * Filter our period based on the current connection. |
3699 | * If we can't perform DT transfers on this segment (not in LVD |
3700 | * mode for instance), then our decision to issue a PPR message |
3701 | * may change. |
3702 | */ |
3703 | period = tinfo->goal.period; |
3704 | offset = tinfo->goal.offset; |
3705 | ppr_options = tinfo->goal.ppr_options; |
3706 | /* Target initiated PPR is not allowed in the SCSI spec */ |
3707 | if (devinfo->role == ROLE_TARGET) |
3708 | ppr_options = 0; |
3709 | ahd_devlimited_syncrate(ahd, tinfo, &period, |
3710 | &ppr_options, devinfo->role); |
3711 | dowide = tinfo->curr.width != tinfo->goal.width; |
3712 | dosync = tinfo->curr.offset != offset || tinfo->curr.period != period; |
3713 | /* |
3714 | * Only use PPR if we have options that need it, even if the device |
3715 | * claims to support it. There might be an expander in the way |
3716 | * that doesn't. |
3717 | */ |
3718 | doppr = ppr_options != 0; |
3719 | |
3720 | if (!dowide && !dosync && !doppr) { |
3721 | dowide = tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT0x00; |
3722 | dosync = tinfo->goal.offset != 0; |
3723 | } |
3724 | |
3725 | if (!dowide && !dosync && !doppr) { |
3726 | /* |
3727 | * Force async with a WDTR message if we have a wide bus, |
3728 | * or just issue an SDTR with a 0 offset. |
3729 | */ |
3730 | if ((ahd->features & AHD_WIDE) != 0) |
3731 | dowide = 1; |
3732 | else |
3733 | dosync = 1; |
3734 | |
3735 | if (bootverbose0) { |
3736 | ahd_print_devinfo(ahd, devinfo); |
3737 | printf("Ensuring async\n"); |
3738 | } |
3739 | } |
3740 | /* Target initiated PPR is not allowed in the SCSI spec */ |
3741 | if (devinfo->role == ROLE_TARGET) |
3742 | doppr = 0; |
3743 | |
3744 | /* |
3745 | * Both the PPR message and SDTR message require the |
3746 | * goal syncrate to be limited to what the target device |
3747 | * is capable of handling (based on whether an LVD->SE |
3748 | * expander is on the bus), so combine these two cases. |
3749 | * Regardless, guarantee that if we are using WDTR and SDTR |
3750 | * messages that WDTR comes first. |
3751 | */ |
3752 | if (doppr || (dosync && !dowide)) { |
3753 | |
3754 | offset = tinfo->goal.offset; |
3755 | ahd_validate_offset(ahd, tinfo, period, &offset, |
3756 | doppr ? tinfo->goal.width |
3757 | : tinfo->curr.width, |
3758 | devinfo->role); |
3759 | if (doppr) { |
3760 | ahd_construct_ppr(ahd, devinfo, period, offset, |
3761 | tinfo->goal.width, ppr_options); |
3762 | } else { |
3763 | ahd_construct_sdtr(ahd, devinfo, period, offset); |
3764 | } |
3765 | } else { |
3766 | ahd_construct_wdtr(ahd, devinfo, tinfo->goal.width); |
3767 | } |
3768 | } |
3769 | |
3770 | /* |
3771 | * Build a synchronous negotiation message in our message |
3772 | * buffer based on the input parameters. |
3773 | */ |
3774 | void |
3775 | ahd_construct_sdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, |
3776 | u_int period, u_int offset) |
3777 | { |
3778 | if (offset == 0) |
3779 | period = AHD_ASYNC_XFER_PERIOD0x44; |
3780 | ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED0x01; |
3781 | ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR_LEN0x03; |
3782 | ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR0x01; |
3783 | ahd->msgout_buf[ahd->msgout_index++] = period; |
3784 | ahd->msgout_buf[ahd->msgout_index++] = offset; |
3785 | ahd->msgout_len += 5; |
3786 | if (bootverbose0) { |
3787 | printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n", |
3788 | ahd_name(ahd), devinfo->channel, devinfo->target, |
3789 | devinfo->lun, period, offset); |
3790 | } |
3791 | } |
3792 | |
3793 | /* |
3794 | * Build a wide negotiation message in our message |
3795 | * buffer based on the input parameters. |
3796 | */ |
3797 | void |
3798 | ahd_construct_wdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, |
3799 | u_int bus_width) |
3800 | { |
3801 | ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED0x01; |
3802 | ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR_LEN0x02; |
3803 | ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR0x03; |
3804 | ahd->msgout_buf[ahd->msgout_index++] = bus_width; |
3805 | ahd->msgout_len += 4; |
3806 | if (bootverbose0) { |
3807 | printf("(%s:%c:%d:%d): Sending WDTR %x\n", |
3808 | ahd_name(ahd), devinfo->channel, devinfo->target, |
3809 | devinfo->lun, bus_width); |
3810 | } |
3811 | } |
3812 | |
3813 | /* |
3814 | * Build a parallel protocol request message in our message |
3815 | * buffer based on the input parameters. |
3816 | */ |
3817 | void |
3818 | ahd_construct_ppr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, |
3819 | u_int period, u_int offset, u_int bus_width, |
3820 | u_int ppr_options) |
3821 | { |
3822 | /* |
3823 | * Always request precompensation from |
3824 | * the other target if we are running |
3825 | * at paced syncrates. |
3826 | */ |
3827 | if (period <= AHD_SYNCRATE_PACED0x8) |
3828 | ppr_options |= MSG_EXT_PPR_PCOMP_EN0x80; |
3829 | if (offset == 0) |
3830 | period = AHD_ASYNC_XFER_PERIOD0x44; |
3831 | ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED0x01; |
3832 | ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR_LEN0x06; |
3833 | ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR0x04; |
3834 | ahd->msgout_buf[ahd->msgout_index++] = period; |
3835 | ahd->msgout_buf[ahd->msgout_index++] = 0; |
3836 | ahd->msgout_buf[ahd->msgout_index++] = offset; |
3837 | ahd->msgout_buf[ahd->msgout_index++] = bus_width; |
3838 | ahd->msgout_buf[ahd->msgout_index++] = ppr_options; |
3839 | ahd->msgout_len += 8; |
3840 | if (bootverbose0) { |
3841 | printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, " |
3842 | "offset %x, ppr_options %x\n", ahd_name(ahd), |
3843 | devinfo->channel, devinfo->target, devinfo->lun, |
3844 | bus_width, period, offset, ppr_options); |
3845 | } |
3846 | } |
3847 | |
3848 | /* |
3849 | * Clear any active message state. |
3850 | */ |
3851 | void |
3852 | ahd_clear_msg_state(struct ahd_softc *ahd) |
3853 | { |
3854 | ahd_mode_state saved_modes; |
3855 | |
3856 | saved_modes = ahd_save_modes(ahd); |
3857 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
3858 | ahd->send_msg_perror = 0; |
3859 | ahd->msg_flags = MSG_FLAG_NONE; |
3860 | ahd->msgout_len = 0; |
3861 | ahd->msgin_index = 0; |
3862 | ahd->msg_type = MSG_TYPE_NONE; |
3863 | if ((ahd_inb(ahd, SCSISIGO)(((ahd)->tags[(0x40) >> 8])->read_1(((ahd)->bshs [(0x40) >> 8]), ((0x40) & 0xFF))) & ATNO0x10) != 0) { |
3864 | /* |
3865 | * The target didn't care to respond to our |
3866 | * message request, so clear ATN. |
3867 | */ |
3868 | ahd_outb(ahd, CLRSINT1, CLRATNO)(((ahd)->tags[(0x4c) >> 8])->write_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF), (0x40))); |
3869 | } |
3870 | ahd_outb(ahd, MSG_OUT, MSG_NOOP)(((ahd)->tags[(0x137) >> 8])->write_1(((ahd)-> bshs[(0x137) >> 8]), ((0x137) & 0xFF), (0x08))); |
3871 | ahd_outb(ahd, SEQ_FLAGS2,(((ahd)->tags[(0x14d) >> 8])->write_1(((ahd)-> bshs[(0x14d) >> 8]), ((0x14d) & 0xFF), ((((ahd)-> tags[(0x14d) >> 8])->read_1(((ahd)->bshs[(0x14d) >> 8]), ((0x14d) & 0xFF))) & ~0x02))) |
3872 | ahd_inb(ahd, SEQ_FLAGS2) & ~TARGET_MSG_PENDING)(((ahd)->tags[(0x14d) >> 8])->write_1(((ahd)-> bshs[(0x14d) >> 8]), ((0x14d) & 0xFF), ((((ahd)-> tags[(0x14d) >> 8])->read_1(((ahd)->bshs[(0x14d) >> 8]), ((0x14d) & 0xFF))) & ~0x02))); |
3873 | ahd_restore_modes(ahd, saved_modes); |
3874 | } |
3875 | |
3876 | /* |
3877 | * Manual message loop handler. |
3878 | */ |
3879 | void |
3880 | ahd_handle_message_phase(struct ahd_softc *ahd) |
3881 | { |
3882 | struct ahd_devinfo devinfo; |
3883 | u_int bus_phase; |
3884 | int end_session; |
3885 | |
3886 | ahd_fetch_devinfo(ahd, &devinfo); |
3887 | end_session = FALSE0; |
3888 | bus_phase = ahd_inb(ahd, LASTPHASE)(((ahd)->tags[(0x13c) >> 8])->read_1(((ahd)->bshs [(0x13c) >> 8]), ((0x13c) & 0xFF))); |
3889 | |
3890 | if ((ahd_inb(ahd, LQISTAT2)(((ahd)->tags[(0x52) >> 8])->read_1(((ahd)->bshs [(0x52) >> 8]), ((0x52) & 0xFF))) & LQIPHASE_OUTPKT0x40) != 0) { |
3891 | printf("LQIRETRY for LQIPHASE_OUTPKT\n"); |
3892 | ahd_outb(ahd, LQCTL2, LQIRETRY)(((ahd)->tags[(0x39) >> 8])->write_1(((ahd)->bshs [(0x39) >> 8]), ((0x39) & 0xFF), (0x80))); |
3893 | } |
3894 | reswitch: |
3895 | switch (ahd->msg_type) { |
3896 | case MSG_TYPE_INITIATOR_MSGOUT: |
3897 | { |
3898 | int lastbyte; |
3899 | int phasemis; |
3900 | int msgdone; |
3901 | |
3902 | if (ahd->msgout_len == 0 && ahd->send_msg_perror == 0) |
3903 | panic("HOST_MSG_LOOP interrupt with no active message"); |
3904 | |
3905 | #ifdef AHD_DEBUG |
3906 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { |
3907 | ahd_print_devinfo(ahd, &devinfo); |
3908 | printf("INITIATOR_MSG_OUT"); |
3909 | } |
3910 | #endif |
3911 | phasemis = bus_phase != P_MESGOUT0xa0; |
3912 | if (phasemis) { |
3913 | #ifdef AHD_DEBUG |
3914 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { |
3915 | printf(" PHASEMIS %s\n", |
3916 | ahd_lookup_phase_entry(bus_phase) |
3917 | ->phasemsg); |
3918 | } |
3919 | #endif |
3920 | if (bus_phase == P_MESGIN0xe0) { |
3921 | /* |
3922 | * Change gears and see if |
3923 | * this messages is of interest to |
3924 | * us or should be passed back to |
3925 | * the sequencer. |
3926 | */ |
3927 | ahd_outb(ahd, CLRSINT1, CLRATNO)(((ahd)->tags[(0x4c) >> 8])->write_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF), (0x40))); |
3928 | ahd->send_msg_perror = 0; |
3929 | ahd->msg_type = MSG_TYPE_INITIATOR_MSGIN; |
3930 | ahd->msgin_index = 0; |
3931 | goto reswitch; |
3932 | } |
3933 | end_session = TRUE1; |
3934 | break; |
3935 | } |
3936 | |
3937 | if (ahd->send_msg_perror) { |
3938 | ahd_outb(ahd, CLRSINT1, CLRATNO)(((ahd)->tags[(0x4c) >> 8])->write_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF), (0x40))); |
3939 | ahd_outb(ahd, CLRSINT1, CLRREQINIT)(((ahd)->tags[(0x4c) >> 8])->write_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF), (0x01))); |
3940 | #ifdef AHD_DEBUG |
3941 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) |
3942 | printf(" byte 0x%x\n", ahd->send_msg_perror); |
3943 | #endif |
3944 | /* |
3945 | * If we are notifying the target of a CRC error |
3946 | * during packetized operations, the target is |
3947 | * within its rights to acknowledge our message |
3948 | * with a busfree. |
3949 | */ |
3950 | if ((ahd->msg_flags & MSG_FLAG_PACKETIZED) != 0 |
3951 | && ahd->send_msg_perror == MSG_INITIATOR_DET_ERR0x05) |
3952 | ahd->msg_flags |= MSG_FLAG_EXPECT_IDE_BUSFREE; |
3953 | |
3954 | ahd_outb(ahd, RETURN_2, ahd->send_msg_perror)(((ahd)->tags[(0x149) >> 8])->write_1(((ahd)-> bshs[(0x149) >> 8]), ((0x149) & 0xFF), (ahd->send_msg_perror ))); |
3955 | ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_WRITE)(((ahd)->tags[(0x148) >> 8])->write_1(((ahd)-> bshs[(0x148) >> 8]), ((0x148) & 0xFF), (0x04))); |
3956 | break; |
3957 | } |
3958 | |
3959 | msgdone = ahd->msgout_index == ahd->msgout_len; |
3960 | if (msgdone) { |
3961 | /* |
3962 | * The target has requested a retry. |
3963 | * Re-assert ATN, reset our message index to |
3964 | * 0, and try again. |
3965 | */ |
3966 | ahd->msgout_index = 0; |
3967 | ahd_assert_atn(ahd); |
3968 | } |
3969 | |
3970 | lastbyte = ahd->msgout_index == (ahd->msgout_len - 1); |
3971 | if (lastbyte) { |
3972 | /* Last byte is signified by dropping ATN */ |
3973 | ahd_outb(ahd, CLRSINT1, CLRATNO)(((ahd)->tags[(0x4c) >> 8])->write_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF), (0x40))); |
3974 | } |
3975 | |
3976 | /* |
3977 | * Clear our interrupt status and present |
3978 | * the next byte on the bus. |
3979 | */ |
3980 | ahd_outb(ahd, CLRSINT1, CLRREQINIT)(((ahd)->tags[(0x4c) >> 8])->write_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF), (0x01))); |
3981 | #ifdef AHD_DEBUG |
3982 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) |
3983 | printf(" byte 0x%x\n", |
3984 | ahd->msgout_buf[ahd->msgout_index]); |
3985 | #endif |
3986 | ahd_outb(ahd, RETURN_2, ahd->msgout_buf[ahd->msgout_index++])(((ahd)->tags[(0x149) >> 8])->write_1(((ahd)-> bshs[(0x149) >> 8]), ((0x149) & 0xFF), (ahd->msgout_buf [ahd->msgout_index++]))); |
3987 | ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_WRITE)(((ahd)->tags[(0x148) >> 8])->write_1(((ahd)-> bshs[(0x148) >> 8]), ((0x148) & 0xFF), (0x04))); |
3988 | break; |
3989 | } |
3990 | case MSG_TYPE_INITIATOR_MSGIN: |
3991 | { |
3992 | int phasemis; |
3993 | int message_done; |
3994 | |
3995 | #ifdef AHD_DEBUG |
3996 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { |
3997 | ahd_print_devinfo(ahd, &devinfo); |
3998 | printf("INITIATOR_MSG_IN"); |
3999 | } |
4000 | #endif |
4001 | phasemis = bus_phase != P_MESGIN0xe0; |
4002 | if (phasemis) { |
4003 | #ifdef AHD_DEBUG |
4004 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { |
4005 | printf(" PHASEMIS %s\n", |
4006 | ahd_lookup_phase_entry(bus_phase) |
4007 | ->phasemsg); |
4008 | } |
4009 | #endif |
4010 | ahd->msgin_index = 0; |
4011 | if (bus_phase == P_MESGOUT0xa0 |
4012 | && (ahd->send_msg_perror != 0 |
4013 | || (ahd->msgout_len != 0 |
4014 | && ahd->msgout_index == 0))) { |
4015 | ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT; |
4016 | goto reswitch; |
4017 | } |
4018 | end_session = TRUE1; |
4019 | break; |
4020 | } |
4021 | |
4022 | /* Pull the byte in without acking it */ |
4023 | ahd->msgin_buf[ahd->msgin_index] = ahd_inb(ahd, SCSIBUS)(((ahd)->tags[(0x46) >> 8])->read_1(((ahd)->bshs [(0x46) >> 8]), ((0x46) & 0xFF))); |
4024 | #ifdef AHD_DEBUG |
4025 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) |
4026 | printf(" byte 0x%x\n", |
4027 | ahd->msgin_buf[ahd->msgin_index]); |
4028 | #endif |
4029 | |
4030 | message_done = ahd_parse_msg(ahd, &devinfo); |
4031 | |
4032 | if (message_done) { |
4033 | /* |
4034 | * Clear our incoming message buffer in case there |
4035 | * is another message following this one. |
4036 | */ |
4037 | ahd->msgin_index = 0; |
4038 | |
4039 | /* |
4040 | * If this message illicited a response, |
4041 | * assert ATN so the target takes us to the |
4042 | * message out phase. |
4043 | */ |
4044 | if (ahd->msgout_len != 0) { |
4045 | #ifdef AHD_DEBUG |
4046 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { |
4047 | ahd_print_devinfo(ahd, &devinfo); |
4048 | printf("Asserting ATN for response\n"); |
4049 | } |
4050 | #endif |
4051 | ahd_assert_atn(ahd); |
4052 | } |
4053 | } else |
4054 | ahd->msgin_index++; |
4055 | |
4056 | if (message_done == MSGLOOP_TERMINATED) { |
4057 | end_session = TRUE1; |
4058 | } else { |
4059 | /* Ack the byte */ |
4060 | ahd_outb(ahd, CLRSINT1, CLRREQINIT)(((ahd)->tags[(0x4c) >> 8])->write_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF), (0x01))); |
4061 | ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_READ)(((ahd)->tags[(0x148) >> 8])->write_1(((ahd)-> bshs[(0x148) >> 8]), ((0x148) & 0xFF), (0x03))); |
4062 | } |
4063 | break; |
4064 | } |
4065 | case MSG_TYPE_TARGET_MSGIN: |
4066 | { |
4067 | int msgdone; |
4068 | int msgout_request; |
4069 | |
4070 | /* |
4071 | * By default, the message loop will continue. |
4072 | */ |
4073 | ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG)(((ahd)->tags[(0x148) >> 8])->write_1(((ahd)-> bshs[(0x148) >> 8]), ((0x148) & 0xFF), (0x02))); |
4074 | |
4075 | if (ahd->msgout_len == 0) |
4076 | panic("Target MSGIN with no active message"); |
4077 | |
4078 | /* |
4079 | * If we interrupted a mesgout session, the initiator |
4080 | * will not know this until our first REQ. So, we |
4081 | * only honor mesgout requests after we've sent our |
4082 | * first byte. |
4083 | */ |
4084 | if ((ahd_inb(ahd, SCSISIGI)(((ahd)->tags[(0x41) >> 8])->read_1(((ahd)->bshs [(0x41) >> 8]), ((0x41) & 0xFF))) & ATNI0x10) != 0 |
4085 | && ahd->msgout_index > 0) |
4086 | msgout_request = TRUE1; |
4087 | else |
4088 | msgout_request = FALSE0; |
4089 | |
4090 | if (msgout_request) { |
4091 | |
4092 | /* |
4093 | * Change gears and see if |
4094 | * this messages is of interest to |
4095 | * us or should be passed back to |
4096 | * the sequencer. |
4097 | */ |
4098 | ahd->msg_type = MSG_TYPE_TARGET_MSGOUT; |
4099 | ahd_outb(ahd, SCSISIGO, P_MESGOUT | BSYO)(((ahd)->tags[(0x40) >> 8])->write_1(((ahd)->bshs [(0x40) >> 8]), ((0x40) & 0xFF), (0xa0 | 0x04))); |
4100 | ahd->msgin_index = 0; |
4101 | /* Dummy read to REQ for first byte */ |
4102 | ahd_inb(ahd, SCSIDAT)(((ahd)->tags[(0x44) >> 8])->read_1(((ahd)->bshs [(0x44) >> 8]), ((0x44) & 0xFF))); |
4103 | ahd_outb(ahd, SXFRCTL0,(((ahd)->tags[(0x3c) >> 8])->write_1(((ahd)->bshs [(0x3c) >> 8]), ((0x3c) & 0xFF), ((((ahd)->tags[ (0x3c) >> 8])->read_1(((ahd)->bshs[(0x3c) >> 8]), ((0x3c) & 0xFF))) | 0x08))) |
4104 | ahd_inb(ahd, SXFRCTL0) | SPIOEN)(((ahd)->tags[(0x3c) >> 8])->write_1(((ahd)->bshs [(0x3c) >> 8]), ((0x3c) & 0xFF), ((((ahd)->tags[ (0x3c) >> 8])->read_1(((ahd)->bshs[(0x3c) >> 8]), ((0x3c) & 0xFF))) | 0x08))); |
4105 | break; |
4106 | } |
4107 | |
4108 | msgdone = ahd->msgout_index == ahd->msgout_len; |
4109 | if (msgdone) { |
4110 | ahd_outb(ahd, SXFRCTL0,(((ahd)->tags[(0x3c) >> 8])->write_1(((ahd)->bshs [(0x3c) >> 8]), ((0x3c) & 0xFF), ((((ahd)->tags[ (0x3c) >> 8])->read_1(((ahd)->bshs[(0x3c) >> 8]), ((0x3c) & 0xFF))) & ~0x08))) |
4111 | ahd_inb(ahd, SXFRCTL0) & ~SPIOEN)(((ahd)->tags[(0x3c) >> 8])->write_1(((ahd)->bshs [(0x3c) >> 8]), ((0x3c) & 0xFF), ((((ahd)->tags[ (0x3c) >> 8])->read_1(((ahd)->bshs[(0x3c) >> 8]), ((0x3c) & 0xFF))) & ~0x08))); |
4112 | end_session = TRUE1; |
4113 | break; |
4114 | } |
4115 | |
4116 | /* |
4117 | * Present the next byte on the bus. |
4118 | */ |
4119 | ahd_outb(ahd, SXFRCTL0, ahd_inb(ahd, SXFRCTL0) | SPIOEN)(((ahd)->tags[(0x3c) >> 8])->write_1(((ahd)->bshs [(0x3c) >> 8]), ((0x3c) & 0xFF), ((((ahd)->tags[ (0x3c) >> 8])->read_1(((ahd)->bshs[(0x3c) >> 8]), ((0x3c) & 0xFF))) | 0x08))); |
4120 | ahd_outb(ahd, SCSIDAT, ahd->msgout_buf[ahd->msgout_index++])(((ahd)->tags[(0x44) >> 8])->write_1(((ahd)->bshs [(0x44) >> 8]), ((0x44) & 0xFF), (ahd->msgout_buf [ahd->msgout_index++]))); |
4121 | break; |
4122 | } |
4123 | case MSG_TYPE_TARGET_MSGOUT: |
4124 | { |
4125 | int lastbyte; |
4126 | int msgdone; |
4127 | |
4128 | /* |
4129 | * By default, the message loop will continue. |
4130 | */ |
4131 | ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG)(((ahd)->tags[(0x148) >> 8])->write_1(((ahd)-> bshs[(0x148) >> 8]), ((0x148) & 0xFF), (0x02))); |
4132 | |
4133 | /* |
4134 | * The initiator signals that this is |
4135 | * the last byte by dropping ATN. |
4136 | */ |
4137 | lastbyte = (ahd_inb(ahd, SCSISIGI)(((ahd)->tags[(0x41) >> 8])->read_1(((ahd)->bshs [(0x41) >> 8]), ((0x41) & 0xFF))) & ATNI0x10) == 0; |
4138 | |
4139 | /* |
4140 | * Read the latched byte, but turn off SPIOEN first |
4141 | * so that we don't inadvertently cause a REQ for the |
4142 | * next byte. |
4143 | */ |
4144 | ahd_outb(ahd, SXFRCTL0, ahd_inb(ahd, SXFRCTL0) & ~SPIOEN)(((ahd)->tags[(0x3c) >> 8])->write_1(((ahd)->bshs [(0x3c) >> 8]), ((0x3c) & 0xFF), ((((ahd)->tags[ (0x3c) >> 8])->read_1(((ahd)->bshs[(0x3c) >> 8]), ((0x3c) & 0xFF))) & ~0x08))); |
4145 | ahd->msgin_buf[ahd->msgin_index] = ahd_inb(ahd, SCSIDAT)(((ahd)->tags[(0x44) >> 8])->read_1(((ahd)->bshs [(0x44) >> 8]), ((0x44) & 0xFF))); |
4146 | msgdone = ahd_parse_msg(ahd, &devinfo); |
4147 | if (msgdone == MSGLOOP_TERMINATED) { |
4148 | /* |
4149 | * The message is *really* done in that it caused |
4150 | * us to go to bus free. The sequencer has already |
4151 | * been reset at this point, so pull the ejection |
4152 | * handle. |
4153 | */ |
4154 | return; |
4155 | } |
4156 | |
4157 | ahd->msgin_index++; |
4158 | |
4159 | /* |
4160 | * XXX Read spec about initiator dropping ATN too soon |
4161 | * and use msgdone to detect it. |
4162 | */ |
4163 | if (msgdone == MSGLOOP_MSGCOMPLETE) { |
4164 | ahd->msgin_index = 0; |
4165 | |
4166 | /* |
4167 | * If this message illicited a response, transition |
4168 | * to the Message in phase and send it. |
4169 | */ |
4170 | if (ahd->msgout_len != 0) { |
4171 | ahd_outb(ahd, SCSISIGO, P_MESGIN | BSYO)(((ahd)->tags[(0x40) >> 8])->write_1(((ahd)->bshs [(0x40) >> 8]), ((0x40) & 0xFF), (0xe0 | 0x04))); |
4172 | ahd_outb(ahd, SXFRCTL0,(((ahd)->tags[(0x3c) >> 8])->write_1(((ahd)->bshs [(0x3c) >> 8]), ((0x3c) & 0xFF), ((((ahd)->tags[ (0x3c) >> 8])->read_1(((ahd)->bshs[(0x3c) >> 8]), ((0x3c) & 0xFF))) | 0x08))) |
4173 | ahd_inb(ahd, SXFRCTL0) | SPIOEN)(((ahd)->tags[(0x3c) >> 8])->write_1(((ahd)->bshs [(0x3c) >> 8]), ((0x3c) & 0xFF), ((((ahd)->tags[ (0x3c) >> 8])->read_1(((ahd)->bshs[(0x3c) >> 8]), ((0x3c) & 0xFF))) | 0x08))); |
4174 | ahd->msg_type = MSG_TYPE_TARGET_MSGIN; |
4175 | ahd->msgin_index = 0; |
4176 | break; |
4177 | } |
4178 | } |
4179 | |
4180 | if (lastbyte) |
4181 | end_session = TRUE1; |
4182 | else { |
4183 | /* Ask for the next byte. */ |
4184 | ahd_outb(ahd, SXFRCTL0,(((ahd)->tags[(0x3c) >> 8])->write_1(((ahd)->bshs [(0x3c) >> 8]), ((0x3c) & 0xFF), ((((ahd)->tags[ (0x3c) >> 8])->read_1(((ahd)->bshs[(0x3c) >> 8]), ((0x3c) & 0xFF))) | 0x08))) |
4185 | ahd_inb(ahd, SXFRCTL0) | SPIOEN)(((ahd)->tags[(0x3c) >> 8])->write_1(((ahd)->bshs [(0x3c) >> 8]), ((0x3c) & 0xFF), ((((ahd)->tags[ (0x3c) >> 8])->read_1(((ahd)->bshs[(0x3c) >> 8]), ((0x3c) & 0xFF))) | 0x08))); |
4186 | } |
4187 | |
4188 | break; |
4189 | } |
4190 | default: |
4191 | panic("Unknown REQINIT message type"); |
4192 | } |
4193 | |
4194 | if (end_session) { |
4195 | if ((ahd->msg_flags & MSG_FLAG_PACKETIZED) != 0) { |
4196 | printf("%s: Returning to Idle Loop\n", |
4197 | ahd_name(ahd)); |
4198 | ahd_clear_msg_state(ahd); |
4199 | |
4200 | /* |
4201 | * Perform the equivalent of a clear_target_state. |
4202 | */ |
4203 | ahd_outb(ahd, LASTPHASE, P_BUSFREE)(((ahd)->tags[(0x13c) >> 8])->write_1(((ahd)-> bshs[(0x13c) >> 8]), ((0x13c) & 0xFF), (0x01))); |
4204 | ahd_outb(ahd, SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT)(((ahd)->tags[(0x139) >> 8])->write_1(((ahd)-> bshs[(0x139) >> 8]), ((0x139) & 0xFF), (0x80|0x40)) ); |
4205 | ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET)(((ahd)->tags[(0xd6) >> 8])->write_1(((ahd)->bshs [(0xd6) >> 8]), ((0xd6) & 0xFF), (0x10|0x02))); |
4206 | } else { |
4207 | ahd_clear_msg_state(ahd); |
4208 | ahd_outb(ahd, RETURN_1, EXIT_MSG_LOOP)(((ahd)->tags[(0x148) >> 8])->write_1(((ahd)-> bshs[(0x148) >> 8]), ((0x148) & 0xFF), (0x08))); |
4209 | } |
4210 | } |
4211 | } |
4212 | |
4213 | /* |
4214 | * See if we sent a particular extended message to the target. |
4215 | * If "full" is true, return true only if the target saw the full |
4216 | * message. If "full" is false, return true if the target saw at |
4217 | * least the first byte of the message. |
4218 | */ |
4219 | int |
4220 | ahd_sent_msg(struct ahd_softc *ahd, ahd_msgtype type, u_int msgval, int full) |
4221 | { |
4222 | int found; |
4223 | u_int index; |
4224 | |
4225 | found = FALSE0; |
4226 | index = 0; |
4227 | |
4228 | while (index < ahd->msgout_len) { |
4229 | if (ahd->msgout_buf[index] == MSG_EXTENDED0x01) { |
4230 | u_int end_index; |
4231 | |
4232 | end_index = index + 1 + ahd->msgout_buf[index + 1]; |
4233 | if (ahd->msgout_buf[index+2] == msgval |
4234 | && type == AHDMSG_EXT) { |
4235 | |
4236 | if (full) { |
4237 | if (ahd->msgout_index > end_index) |
4238 | found = TRUE1; |
4239 | } else if (ahd->msgout_index > index) |
4240 | found = TRUE1; |
4241 | } |
4242 | index = end_index; |
4243 | } else if (ahd->msgout_buf[index] >= MSG_SIMPLE_TASK0x20 |
4244 | && ahd->msgout_buf[index] <= MSG_IGN_WIDE_RESIDUE0x23) { |
4245 | |
4246 | /* Skip tag type and tag id or residue param*/ |
4247 | index += 2; |
4248 | } else { |
4249 | /* Single byte message */ |
4250 | if (type == AHDMSG_1B |
4251 | && ahd->msgout_index > index |
4252 | && (ahd->msgout_buf[index] == msgval |
4253 | || ((ahd->msgout_buf[index] & MSG_IDENTIFYFLAG0x80) != 0 |
4254 | && msgval == MSG_IDENTIFYFLAG0x80))) |
4255 | found = TRUE1; |
4256 | index++; |
4257 | } |
4258 | |
4259 | if (found) |
4260 | break; |
4261 | } |
4262 | return (found); |
4263 | } |
4264 | |
4265 | /* |
4266 | * Wait for a complete incoming message, parse it, and respond accordingly. |
4267 | */ |
4268 | int |
4269 | ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) |
4270 | { |
4271 | struct ahd_initiator_tinfo *tinfo; |
4272 | struct ahd_tmode_tstate *tstate; |
4273 | int reject; |
4274 | int done; |
4275 | int response; |
4276 | |
4277 | done = MSGLOOP_IN_PROG; |
4278 | response = FALSE0; |
4279 | reject = FALSE0; |
4280 | tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid, |
4281 | devinfo->target, &tstate); |
4282 | |
4283 | /* |
4284 | * Parse as much of the message as is available, |
4285 | * rejecting it if we don't support it. When |
4286 | * the entire message is available and has been |
4287 | * handled, return MSGLOOP_MSGCOMPLETE, indicating |
4288 | * that we have parsed an entire message. |
4289 | * |
4290 | * In the case of extended messages, we accept the length |
4291 | * byte outright and perform more checking once we know the |
4292 | * extended message type. |
4293 | */ |
4294 | switch (ahd->msgin_buf[0]) { |
4295 | case MSG_DISCONNECT0x04: |
4296 | case MSG_SAVEDATAPOINTER0x02: |
4297 | case MSG_CMDCOMPLETE0x00: |
4298 | case MSG_RESTOREPOINTERS0x03: |
4299 | case MSG_IGN_WIDE_RESIDUE0x23: |
4300 | /* |
4301 | * End our message loop as these are messages |
4302 | * the sequencer handles on its own. |
4303 | */ |
4304 | done = MSGLOOP_TERMINATED; |
4305 | break; |
4306 | case MSG_MESSAGE_REJECT0x07: |
4307 | response = ahd_handle_msg_reject(ahd, devinfo); |
4308 | /* FALLTHROUGH */ |
4309 | case MSG_NOOP0x08: |
4310 | done = MSGLOOP_MSGCOMPLETE; |
4311 | break; |
4312 | case MSG_EXTENDED0x01: |
4313 | { |
4314 | /* Wait for enough of the message to begin validation */ |
4315 | if (ahd->msgin_index < 2) |
4316 | break; |
4317 | switch (ahd->msgin_buf[2]) { |
4318 | case MSG_EXT_SDTR0x01: |
4319 | { |
4320 | u_int period; |
4321 | u_int ppr_options; |
4322 | u_int offset; |
4323 | u_int saved_offset; |
4324 | |
4325 | if (ahd->msgin_buf[1] != MSG_EXT_SDTR_LEN0x03) { |
4326 | reject = TRUE1; |
4327 | break; |
4328 | } |
4329 | |
4330 | /* |
4331 | * Wait until we have both args before validating |
4332 | * and acting on this message. |
4333 | * |
4334 | * Add one to MSG_EXT_SDTR_LEN to account for |
4335 | * the extended message preamble. |
4336 | */ |
4337 | if (ahd->msgin_index < (MSG_EXT_SDTR_LEN0x03 + 1)) |
4338 | break; |
4339 | |
4340 | period = ahd->msgin_buf[3]; |
4341 | ppr_options = 0; |
4342 | saved_offset = offset = ahd->msgin_buf[4]; |
4343 | ahd_devlimited_syncrate(ahd, tinfo, &period, |
4344 | &ppr_options, devinfo->role); |
4345 | ahd_validate_offset(ahd, tinfo, period, &offset, |
4346 | tinfo->curr.width, devinfo->role); |
4347 | if (bootverbose0) { |
4348 | printf("(%s:%c:%d:%d): Received " |
4349 | "SDTR period %x, offset %x\n\t" |
4350 | "Filtered to period %x, offset %x\n", |
4351 | ahd_name(ahd), devinfo->channel, |
4352 | devinfo->target, devinfo->lun, |
4353 | ahd->msgin_buf[3], saved_offset, |
4354 | period, offset); |
4355 | } |
4356 | ahd_set_syncrate(ahd, devinfo, period, |
4357 | offset, ppr_options, |
4358 | AHD_TRANS_ACTIVE0x03|AHD_TRANS_GOAL0x04, |
4359 | /*paused*/TRUE1); |
4360 | |
4361 | /* |
4362 | * See if we initiated Sync Negotiation |
4363 | * and didn't have to fall down to async |
4364 | * transfers. |
4365 | */ |
4366 | if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR0x01, TRUE1)) { |
4367 | /* We started it */ |
4368 | if (saved_offset != offset) { |
4369 | /* Went too low - force async */ |
4370 | reject = TRUE1; |
4371 | } |
4372 | } else { |
4373 | /* |
4374 | * Send our own SDTR in reply |
4375 | */ |
4376 | if (bootverbose0 |
4377 | && devinfo->role == ROLE_INITIATOR) { |
4378 | printf("(%s:%c:%d:%d): Target " |
4379 | "Initiated SDTR\n", |
4380 | ahd_name(ahd), devinfo->channel, |
4381 | devinfo->target, devinfo->lun); |
4382 | } |
4383 | ahd->msgout_index = 0; |
4384 | ahd->msgout_len = 0; |
4385 | ahd_construct_sdtr(ahd, devinfo, |
4386 | period, offset); |
4387 | ahd->msgout_index = 0; |
4388 | response = TRUE1; |
4389 | } |
4390 | done = MSGLOOP_MSGCOMPLETE; |
4391 | break; |
4392 | } |
4393 | case MSG_EXT_WDTR0x03: |
4394 | { |
4395 | u_int bus_width; |
4396 | u_int saved_width; |
4397 | u_int sending_reply; |
4398 | |
4399 | sending_reply = FALSE0; |
4400 | if (ahd->msgin_buf[1] != MSG_EXT_WDTR_LEN0x02) { |
4401 | reject = TRUE1; |
4402 | break; |
4403 | } |
4404 | |
4405 | /* |
4406 | * Wait until we have our arg before validating |
4407 | * and acting on this message. |
4408 | * |
4409 | * Add one to MSG_EXT_WDTR_LEN to account for |
4410 | * the extended message preamble. |
4411 | */ |
4412 | if (ahd->msgin_index < (MSG_EXT_WDTR_LEN0x02 + 1)) |
4413 | break; |
4414 | |
4415 | bus_width = ahd->msgin_buf[3]; |
4416 | saved_width = bus_width; |
4417 | ahd_validate_width(ahd, tinfo, &bus_width, |
4418 | devinfo->role); |
4419 | if (bootverbose0) { |
4420 | printf("(%s:%c:%d:%d): Received WDTR " |
4421 | "%x filtered to %x\n", |
4422 | ahd_name(ahd), devinfo->channel, |
4423 | devinfo->target, devinfo->lun, |
4424 | saved_width, bus_width); |
4425 | } |
4426 | |
4427 | if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR0x03, TRUE1)) { |
4428 | /* |
4429 | * Don't send a WDTR back to the |
4430 | * target, since we asked first. |
4431 | * If the width went higher than our |
4432 | * request, reject it. |
4433 | */ |
4434 | if (saved_width > bus_width) { |
4435 | reject = TRUE1; |
4436 | printf("(%s:%c:%d:%d): requested %dBit " |
4437 | "transfers. Rejecting...\n", |
4438 | ahd_name(ahd), devinfo->channel, |
4439 | devinfo->target, devinfo->lun, |
4440 | 8 * (0x01 << bus_width)); |
4441 | bus_width = 0; |
4442 | } |
4443 | } else { |
4444 | /* |
4445 | * Send our own WDTR in reply |
4446 | */ |
4447 | if (bootverbose0 |
4448 | && devinfo->role == ROLE_INITIATOR) { |
4449 | printf("(%s:%c:%d:%d): Target " |
4450 | "Initiated WDTR\n", |
4451 | ahd_name(ahd), devinfo->channel, |
4452 | devinfo->target, devinfo->lun); |
4453 | } |
4454 | ahd->msgout_index = 0; |
4455 | ahd->msgout_len = 0; |
4456 | ahd_construct_wdtr(ahd, devinfo, bus_width); |
4457 | ahd->msgout_index = 0; |
4458 | response = TRUE1; |
4459 | sending_reply = TRUE1; |
4460 | } |
4461 | /* |
4462 | * After a wide message, we are async, but |
4463 | * some devices don't seem to honor this portion |
4464 | * of the spec. Force a renegotiation of the |
4465 | * sync component of our transfer agreement even |
4466 | * if our goal is async. By updating our width |
4467 | * after forcing the negotiation, we avoid |
4468 | * renegotiating for width. |
4469 | */ |
4470 | ahd_update_neg_request(ahd, devinfo, tstate, |
4471 | tinfo, AHD_NEG_ALWAYS); |
4472 | ahd_set_width(ahd, devinfo, bus_width, |
4473 | AHD_TRANS_ACTIVE0x03|AHD_TRANS_GOAL0x04, |
4474 | /*paused*/TRUE1); |
4475 | if (sending_reply == FALSE0 && reject == FALSE0) { |
4476 | |
4477 | /* |
4478 | * We will always have an SDTR to send. |
4479 | */ |
4480 | ahd->msgout_index = 0; |
4481 | ahd->msgout_len = 0; |
4482 | ahd_build_transfer_msg(ahd, devinfo); |
4483 | ahd->msgout_index = 0; |
4484 | response = TRUE1; |
4485 | } |
4486 | done = MSGLOOP_MSGCOMPLETE; |
4487 | break; |
4488 | } |
4489 | case MSG_EXT_PPR0x04: |
4490 | { |
4491 | u_int period; |
4492 | u_int offset; |
4493 | u_int bus_width; |
4494 | u_int ppr_options; |
4495 | u_int saved_width; |
4496 | u_int saved_offset; |
4497 | u_int saved_ppr_options; |
4498 | |
4499 | if (ahd->msgin_buf[1] != MSG_EXT_PPR_LEN0x06) { |
4500 | reject = TRUE1; |
4501 | break; |
4502 | } |
4503 | |
4504 | /* |
4505 | * Wait until we have all args before validating |
4506 | * and acting on this message. |
4507 | * |
4508 | * Add one to MSG_EXT_PPR_LEN to account for |
4509 | * the extended message preamble. |
4510 | */ |
4511 | if (ahd->msgin_index < (MSG_EXT_PPR_LEN0x06 + 1)) |
4512 | break; |
4513 | |
4514 | period = ahd->msgin_buf[3]; |
4515 | offset = ahd->msgin_buf[5]; |
4516 | bus_width = ahd->msgin_buf[6]; |
4517 | saved_width = bus_width; |
4518 | ppr_options = ahd->msgin_buf[7]; |
4519 | /* |
4520 | * According to the spec, a DT only |
4521 | * period factor with no DT option |
4522 | * set implies async. |
4523 | */ |
4524 | if ((ppr_options & MSG_EXT_PPR_DT_REQ0x02) == 0 |
4525 | && period <= 9) |
4526 | offset = 0; |
4527 | saved_ppr_options = ppr_options; |
4528 | saved_offset = offset; |
4529 | |
4530 | /* |
4531 | * Transfer options are only available if we |
4532 | * are negotiating wide. |
4533 | */ |
4534 | if (bus_width == 0) |
4535 | ppr_options &= MSG_EXT_PPR_QAS_REQ0x04; |
4536 | |
4537 | ahd_validate_width(ahd, tinfo, &bus_width, |
4538 | devinfo->role); |
4539 | ahd_devlimited_syncrate(ahd, tinfo, &period, |
4540 | &ppr_options, devinfo->role); |
4541 | ahd_validate_offset(ahd, tinfo, period, &offset, |
4542 | bus_width, devinfo->role); |
4543 | |
4544 | if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR0x04, TRUE1)) { |
4545 | /* |
4546 | * If we are unable to do any of the |
4547 | * requested options (we went too low), |
4548 | * then we'll have to reject the message. |
4549 | */ |
4550 | if (saved_width > bus_width |
4551 | || saved_offset != offset |
4552 | || saved_ppr_options != ppr_options) { |
4553 | reject = TRUE1; |
4554 | period = 0; |
4555 | offset = 0; |
4556 | bus_width = 0; |
4557 | ppr_options = 0; |
4558 | } |
4559 | } else { |
4560 | if (devinfo->role != ROLE_TARGET) |
4561 | printf("(%s:%c:%d:%d): Target " |
4562 | "Initiated PPR\n", |
4563 | ahd_name(ahd), devinfo->channel, |
4564 | devinfo->target, devinfo->lun); |
4565 | else |
4566 | printf("(%s:%c:%d:%d): Initiator " |
4567 | "Initiated PPR\n", |
4568 | ahd_name(ahd), devinfo->channel, |
4569 | devinfo->target, devinfo->lun); |
4570 | ahd->msgout_index = 0; |
4571 | ahd->msgout_len = 0; |
4572 | ahd_construct_ppr(ahd, devinfo, period, offset, |
4573 | bus_width, ppr_options); |
4574 | ahd->msgout_index = 0; |
4575 | response = TRUE1; |
4576 | } |
4577 | if (bootverbose0) { |
4578 | printf("(%s:%c:%d:%d): Received PPR width %x, " |
4579 | "period %x, offset %x,options %x\n" |
4580 | "\tFiltered to width %x, period %x, " |
4581 | "offset %x, options %x\n", |
4582 | ahd_name(ahd), devinfo->channel, |
4583 | devinfo->target, devinfo->lun, |
4584 | saved_width, ahd->msgin_buf[3], |
4585 | saved_offset, saved_ppr_options, |
4586 | bus_width, period, offset, ppr_options); |
4587 | } |
4588 | ahd_set_width(ahd, devinfo, bus_width, |
4589 | AHD_TRANS_ACTIVE0x03|AHD_TRANS_GOAL0x04, |
4590 | /*paused*/TRUE1); |
4591 | ahd_set_syncrate(ahd, devinfo, period, |
4592 | offset, ppr_options, |
4593 | AHD_TRANS_ACTIVE0x03|AHD_TRANS_GOAL0x04, |
4594 | /*paused*/TRUE1); |
4595 | |
4596 | done = MSGLOOP_MSGCOMPLETE; |
4597 | break; |
4598 | } |
4599 | default: |
4600 | /* Unknown extended message. Reject it. */ |
4601 | reject = TRUE1; |
4602 | break; |
4603 | } |
4604 | break; |
4605 | } |
4606 | #ifdef AHD_TARGET_MODE |
4607 | case MSG_BUS_DEV_RESET0x0c: |
4608 | ahd_handle_devreset(ahd, devinfo, CAM_LUN_WILDCARD-1, |
4609 | CAM_BDR_SENT, |
4610 | "Bus Device Reset Received", |
4611 | /*verbose_level*/0); |
4612 | ahd_restart(ahd); |
4613 | done = MSGLOOP_TERMINATED; |
4614 | break; |
4615 | case MSG_ABORT_TAG0x0d: |
4616 | case MSG_ABORT0x06: |
4617 | case MSG_CLEAR_QUEUE0x0e: |
4618 | { |
4619 | int tag; |
4620 | |
4621 | /* Target mode messages */ |
4622 | if (devinfo->role != ROLE_TARGET) { |
4623 | reject = TRUE1; |
4624 | break; |
4625 | } |
4626 | tag = SCB_LIST_NULL0xFF00; |
4627 | if (ahd->msgin_buf[0] == MSG_ABORT_TAG0x0d) |
4628 | tag = ahd_inb(ahd, INITIATOR_TAG)(((ahd)->tags[(0x14c) >> 8])->read_1(((ahd)->bshs [(0x14c) >> 8]), ((0x14c) & 0xFF))); |
4629 | ahd_abort_scbs(ahd, devinfo->target, devinfo->channel, |
4630 | devinfo->lun, tag, ROLE_TARGET, |
4631 | CAM_REQ_ABORTED); |
4632 | |
4633 | tstate = ahd->enabled_targets[devinfo->our_scsiid]; |
4634 | if (tstate != NULL((void *)0)) { |
4635 | struct ahd_tmode_lstate* lstate; |
4636 | |
4637 | lstate = tstate->enabled_luns[devinfo->lun]; |
4638 | if (lstate != NULL((void *)0)) { |
4639 | ahd_queue_lstate_event(ahd, lstate, |
4640 | devinfo->our_scsiid, |
4641 | ahd->msgin_buf[0], |
4642 | /*arg*/tag); |
4643 | ahd_send_lstate_events(ahd, lstate); |
4644 | } |
4645 | } |
4646 | ahd_restart(ahd); |
4647 | done = MSGLOOP_TERMINATED; |
4648 | break; |
4649 | } |
4650 | #endif |
4651 | case MSG_QAS_REQUEST0x55: |
4652 | #ifdef AHD_DEBUG |
4653 | if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) |
4654 | printf("%s: QAS request. SCSISIGI == 0x%x\n", |
4655 | ahd_name(ahd), ahd_inb(ahd, SCSISIGI)(((ahd)->tags[(0x41) >> 8])->read_1(((ahd)->bshs [(0x41) >> 8]), ((0x41) & 0xFF)))); |
4656 | #endif |
4657 | ahd->msg_flags |= MSG_FLAG_EXPECT_QASREJ_BUSFREE; |
4658 | /* FALLTHROUGH */ |
4659 | case MSG_TERM_IO_PROC0x11: |
4660 | default: |
4661 | reject = TRUE1; |
4662 | break; |
4663 | } |
4664 | |
4665 | if (reject) { |
4666 | /* |
4667 | * Setup to reject the message. |
4668 | */ |
4669 | ahd->msgout_index = 0; |
4670 | ahd->msgout_len = 1; |
4671 | ahd->msgout_buf[0] = MSG_MESSAGE_REJECT0x07; |
4672 | done = MSGLOOP_MSGCOMPLETE; |
4673 | response = TRUE1; |
4674 | } |
4675 | |
4676 | if (done != MSGLOOP_IN_PROG && !response) |
4677 | /* Clear the outgoing message buffer */ |
4678 | ahd->msgout_len = 0; |
4679 | |
4680 | return (done); |
4681 | } |
4682 | |
4683 | /* |
4684 | * Process a message reject message. |
4685 | */ |
4686 | int |
4687 | ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) |
4688 | { |
4689 | /* |
4690 | * What we care about here is if we had an |
4691 | * outstanding SDTR or WDTR message for this |
4692 | * target. If we did, this is a signal that |
4693 | * the target is refusing negotiation. |
4694 | */ |
4695 | struct scb *scb; |
4696 | struct ahd_initiator_tinfo *tinfo; |
4697 | struct ahd_tmode_tstate *tstate; |
4698 | u_int scb_index; |
4699 | u_int last_msg; |
4700 | int response = 0; |
4701 | |
4702 | scb_index = ahd_get_scbptr(ahd); |
4703 | scb = ahd_lookup_scb(ahd, scb_index); |
4704 | tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, |
4705 | devinfo->our_scsiid, |
4706 | devinfo->target, &tstate); |
4707 | /* Might be necessary */ |
4708 | last_msg = ahd_inb(ahd, LAST_MSG)(((ahd)->tags[(0x14a) >> 8])->read_1(((ahd)->bshs [(0x14a) >> 8]), ((0x14a) & 0xFF))); |
4709 | |
4710 | if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR0x04, /*full*/FALSE0)) { |
4711 | if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR0x04, /*full*/TRUE1) |
4712 | && tinfo->goal.period <= AHD_SYNCRATE_PACED0x8) { |
4713 | /* |
4714 | * Target may not like our SPI-4 PPR Options. |
4715 | * Attempt to negotiate 80MHz which will turn |
4716 | * off these options. |
4717 | */ |
4718 | if (bootverbose0) { |
4719 | printf("(%s:%c:%d:%d): PPR Rejected. " |
4720 | "Trying simple U160 PPR\n", |
4721 | ahd_name(ahd), devinfo->channel, |
4722 | devinfo->target, devinfo->lun); |
4723 | } |
4724 | tinfo->goal.period = AHD_SYNCRATE_DT0x9; |
4725 | tinfo->goal.ppr_options &= MSG_EXT_PPR_IU_REQ0x01 |
4726 | | MSG_EXT_PPR_QAS_REQ0x04 |
4727 | | MSG_EXT_PPR_DT_REQ0x02; |
4728 | } else { |
4729 | /* |
4730 | * Target does not support the PPR message. |
4731 | * Attempt to negotiate SPI-2 style. |
4732 | */ |
4733 | if (bootverbose0) { |
4734 | printf("(%s:%c:%d:%d): PPR Rejected. " |
4735 | "Trying WDTR/SDTR\n", |
4736 | ahd_name(ahd), devinfo->channel, |
4737 | devinfo->target, devinfo->lun); |
4738 | } |
4739 | tinfo->goal.ppr_options = 0; |
4740 | tinfo->curr.transport_version = 2; |
4741 | tinfo->goal.transport_version = 2; |
4742 | } |
4743 | ahd->msgout_index = 0; |
4744 | ahd->msgout_len = 0; |
4745 | ahd_build_transfer_msg(ahd, devinfo); |
4746 | ahd->msgout_index = 0; |
4747 | response = 1; |
4748 | } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR0x03, /*full*/FALSE0)) { |
4749 | |
4750 | /* note 8bit xfers */ |
4751 | printf("(%s:%c:%d:%d): refuses WIDE negotiation. Using " |
4752 | "8bit transfers\n", ahd_name(ahd), |
4753 | devinfo->channel, devinfo->target, devinfo->lun); |
4754 | ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT0x00, |
4755 | AHD_TRANS_ACTIVE0x03|AHD_TRANS_GOAL0x04, |
4756 | /*paused*/TRUE1); |
4757 | /* |
4758 | * No need to clear the sync rate. If the target |
4759 | * did not accept the command, our syncrate is |
4760 | * unaffected. If the target started the negotiation, |
4761 | * but rejected our response, we already cleared the |
4762 | * sync rate before sending our WDTR. |
4763 | */ |
4764 | if (tinfo->goal.offset != tinfo->curr.offset) { |
4765 | |
4766 | /* Start the sync negotiation */ |
4767 | ahd->msgout_index = 0; |
4768 | ahd->msgout_len = 0; |
4769 | ahd_build_transfer_msg(ahd, devinfo); |
4770 | ahd->msgout_index = 0; |
4771 | response = 1; |
4772 | } |
4773 | } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR0x01, /*full*/FALSE0)) { |
4774 | /* note asynch xfers and clear flag */ |
4775 | ahd_set_syncrate(ahd, devinfo, /*period*/0, |
4776 | /*offset*/0, /*ppr_options*/0, |
4777 | AHD_TRANS_ACTIVE0x03|AHD_TRANS_GOAL0x04, |
4778 | /*paused*/TRUE1); |
4779 | printf("(%s:%c:%d:%d): refuses synchronous negotiation. " |
4780 | "Using asynchronous transfers\n", |
4781 | ahd_name(ahd), devinfo->channel, |
4782 | devinfo->target, devinfo->lun); |
4783 | } else if ((scb->hscb->control & MSG_SIMPLE_TASK0x20) != 0) { |
4784 | int tag_type; |
4785 | int mask; |
4786 | |
4787 | tag_type = (scb->hscb->control & MSG_SIMPLE_TASK0x20); |
4788 | |
4789 | if (tag_type == MSG_SIMPLE_TASK0x20) { |
4790 | printf("(%s:%c:%d:%d): refuses tagged commands. " |
4791 | "Performing non-tagged I/O\n", ahd_name(ahd), |
4792 | devinfo->channel, devinfo->target, devinfo->lun); |
4793 | ahd_set_tags(ahd, devinfo, AHD_QUEUE_NONE); |
4794 | mask = ~0x23; |
4795 | } else { |
4796 | printf("(%s:%c:%d:%d): refuses %s tagged commands. " |
4797 | "Performing simple queue tagged I/O only\n", |
4798 | ahd_name(ahd), devinfo->channel, devinfo->target, |
4799 | devinfo->lun, tag_type == MSG_ORDERED_TASK0x22 |
4800 | ? "ordered" : "head of queue"); |
4801 | ahd_set_tags(ahd, devinfo, AHD_QUEUE_BASIC); |
4802 | mask = ~0x03; |
4803 | } |
4804 | |
4805 | /* |
4806 | * Resend the identify for this CCB as the target |
4807 | * may believe that the selection is invalid otherwise. |
4808 | */ |
4809 | ahd_outb(ahd, SCB_CONTROL,(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (ahd_inb_scbram (ahd, 0x192) & mask))) |
4810 | ahd_inb_scbram(ahd, SCB_CONTROL) & mask)(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (ahd_inb_scbram (ahd, 0x192) & mask))); |
4811 | scb->hscb->control &= mask; |
4812 | aic_set_transaction_tag(scb, /*enabled*/FALSE, |
4813 | /*type*/MSG_SIMPLE_TASK); |
4814 | ahd_outb(ahd, MSG_OUT, MSG_IDENTIFYFLAG)(((ahd)->tags[(0x137) >> 8])->write_1(((ahd)-> bshs[(0x137) >> 8]), ((0x137) & 0xFF), (0x80))); |
4815 | ahd_assert_atn(ahd); |
4816 | ahd_busy_tcl(ahd, BUILD_TCL(scb->hscb->scsiid, devinfo->lun)((devinfo->lun) | (((scb->hscb->scsiid) & 0xf0) << 4)), |
4817 | SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag))); |
4818 | |
4819 | /* |
4820 | * Requeue all tagged commands for this target |
4821 | * currently in our possession so they can be |
4822 | * converted to untagged commands. |
4823 | */ |
4824 | ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb)((((scb)->hscb->scsiid) & 0xf0) >> 0x04), |
4825 | SCB_GET_CHANNEL(ahd, scb)('A'), |
4826 | SCB_GET_LUN(scb)((scb)->hscb->lun), /*tag*/SCB_LIST_NULL0xFF00, |
4827 | ROLE_INITIATOR, CAM_REQUEUE_REQ, |
4828 | SEARCH_COMPLETE); |
4829 | } else if (ahd_sent_msg(ahd, AHDMSG_1B, MSG_IDENTIFYFLAG0x80, TRUE1)) { |
4830 | /* |
4831 | * Most likely the device believes that we had |
4832 | * previously negotiated packetized. |
4833 | */ |
4834 | ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE |
4835 | | MSG_FLAG_IU_REQ_CHANGED; |
4836 | |
4837 | ahd_force_renegotiation(ahd, devinfo); |
4838 | ahd->msgout_index = 0; |
4839 | ahd->msgout_len = 0; |
4840 | ahd_build_transfer_msg(ahd, devinfo); |
4841 | ahd->msgout_index = 0; |
4842 | response = 1; |
4843 | } else { |
4844 | /* |
4845 | * Otherwise, we ignore it. |
4846 | */ |
4847 | printf("%s:%c:%d: Message reject for %x -- ignored\n", |
4848 | ahd_name(ahd), devinfo->channel, devinfo->target, |
4849 | last_msg); |
4850 | } |
4851 | return (response); |
4852 | } |
4853 | |
4854 | /* |
4855 | * Process an ignore wide residue message. |
4856 | */ |
4857 | void |
4858 | ahd_handle_ign_wide_residue(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) |
4859 | { |
4860 | u_int scb_index; |
4861 | struct scb *scb; |
4862 | |
4863 | scb_index = ahd_get_scbptr(ahd); |
4864 | scb = ahd_lookup_scb(ahd, scb_index); |
4865 | /* |
4866 | * XXX Actually check data direction in the sequencer? |
4867 | * Perhaps add datadir to some spare bits in the hscb? |
4868 | */ |
4869 | if ((ahd_inb(ahd, SEQ_FLAGS)(((ahd)->tags[(0x139) >> 8])->read_1(((ahd)->bshs [(0x139) >> 8]), ((0x139) & 0xFF))) & DPHASE0x20) == 0 |
4870 | || aic_get_transfer_dir(scb)((scb)->xs->flags & (0x00800 | 0x01000)) != CAM_DIR_IN) { |
4871 | /* |
4872 | * Ignore the message if we haven't |
4873 | * seen an appropriate data phase yet. |
4874 | */ |
4875 | } else { |
4876 | /* |
4877 | * If the residual occurred on the last |
4878 | * transfer and the transfer request was |
4879 | * expected to end on an odd count, do |
4880 | * nothing. Otherwise, subtract a byte |
4881 | * and update the residual count accordingly. |
4882 | */ |
4883 | uint32_t sgptr; |
4884 | |
4885 | sgptr = ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR0x184); |
4886 | if ((sgptr & SG_LIST_NULL0x01) != 0 |
4887 | && (ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE0x195) |
4888 | & SCB_XFERLEN_ODD0x01) != 0) { |
4889 | /* |
4890 | * If the residual occurred on the last |
4891 | * transfer and the transfer request was |
4892 | * expected to end on an odd count, do |
4893 | * nothing. |
4894 | */ |
4895 | } else { |
4896 | uint32_t data_cnt; |
4897 | uint64_t data_addr; |
4898 | uint32_t sglen; |
4899 | |
4900 | /* Pull in the rest of the sgptr */ |
4901 | sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR0x184); |
4902 | data_cnt = ahd_inl_scbram(ahd, SCB_RESIDUAL_DATACNT0x180); |
4903 | if ((sgptr & SG_LIST_NULL0x01) != 0) { |
4904 | /* |
4905 | * The residual data count is not updated |
4906 | * for the command run to completion case. |
4907 | * Explicitly zero the count. |
4908 | */ |
4909 | data_cnt &= ~AHD_SG_LEN_MASK0x00FFFFFF; |
4910 | } |
4911 | data_addr = ahd_inq(ahd, SHADDR0x60); |
4912 | data_cnt += 1; |
4913 | data_addr -= 1; |
4914 | sgptr &= SG_PTR_MASK0xFFFFFFF8; |
4915 | if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) { |
4916 | struct ahd_dma64_seg *sg; |
4917 | |
4918 | sg = ahd_sg_bus_to_virt(ahd, scb, sgptr); |
4919 | |
4920 | /* |
4921 | * The residual sg ptr points to the next S/G |
4922 | * to load so we must go back one. |
4923 | */ |
4924 | sg--; |
4925 | sglen = aic_le32toh(sg->len)((__uint32_t)(sg->len)) & AHD_SG_LEN_MASK0x00FFFFFF; |
4926 | if (sg != scb->sg_list |
4927 | && sglen < (data_cnt & AHD_SG_LEN_MASK0x00FFFFFF)) { |
4928 | |
4929 | sg--; |
4930 | sglen = aic_le32toh(sg->len)((__uint32_t)(sg->len)); |
4931 | /* |
4932 | * Preserve High Address and SG_LIST |
4933 | * bits while setting the count to 1. |
4934 | */ |
4935 | data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK0x00FFFFFF)); |
4936 | data_addr = aic_le64toh(sg->addr)((__uint64_t)(sg->addr)) |
4937 | + (sglen & AHD_SG_LEN_MASK0x00FFFFFF) |
4938 | - 1; |
4939 | |
4940 | /* |
4941 | * Increment sg so it points to the |
4942 | * "next" sg. |
4943 | */ |
4944 | sg++; |
4945 | sgptr = ahd_sg_virt_to_bus(ahd, scb, |
4946 | sg); |
4947 | } |
4948 | } else { |
4949 | struct ahd_dma_seg *sg; |
4950 | |
4951 | sg = ahd_sg_bus_to_virt(ahd, scb, sgptr); |
4952 | |
4953 | /* |
4954 | * The residual sg ptr points to the next S/G |
4955 | * to load so we must go back one. |
4956 | */ |
4957 | sg--; |
4958 | sglen = aic_le32toh(sg->len)((__uint32_t)(sg->len)) & AHD_SG_LEN_MASK0x00FFFFFF; |
4959 | if (sg != scb->sg_list |
4960 | && sglen < (data_cnt & AHD_SG_LEN_MASK0x00FFFFFF)) { |
4961 | |
4962 | sg--; |
4963 | sglen = aic_le32toh(sg->len)((__uint32_t)(sg->len)); |
4964 | /* |
4965 | * Preserve High Address and SG_LIST |
4966 | * bits while setting the count to 1. |
4967 | */ |
4968 | data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK0x00FFFFFF)); |
4969 | data_addr = aic_le32toh(sg->addr)((__uint32_t)(sg->addr)) |
4970 | + (sglen & AHD_SG_LEN_MASK0x00FFFFFF) |
4971 | - 1; |
4972 | |
4973 | /* |
4974 | * Increment sg so it points to the |
4975 | * "next" sg. |
4976 | */ |
4977 | sg++; |
4978 | sgptr = ahd_sg_virt_to_bus(ahd, scb, |
4979 | sg); |
4980 | } |
4981 | } |
4982 | /* |
4983 | * Toggle the "oddness" of the transfer length |
4984 | * to handle this mid-transfer ignore wide |
4985 | * residue. This ensures that the oddness is |
4986 | * correct for subsequent data transfers. |
4987 | */ |
4988 | ahd_outb(ahd, SCB_TASK_ATTRIBUTE,(((ahd)->tags[(0x195) >> 8])->write_1(((ahd)-> bshs[(0x195) >> 8]), ((0x195) & 0xFF), (ahd_inb_scbram (ahd, 0x195) ^ 0x01))) |
4989 | ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE)(((ahd)->tags[(0x195) >> 8])->write_1(((ahd)-> bshs[(0x195) >> 8]), ((0x195) & 0xFF), (ahd_inb_scbram (ahd, 0x195) ^ 0x01))) |
4990 | ^ SCB_XFERLEN_ODD)(((ahd)->tags[(0x195) >> 8])->write_1(((ahd)-> bshs[(0x195) >> 8]), ((0x195) & 0xFF), (ahd_inb_scbram (ahd, 0x195) ^ 0x01))); |
4991 | |
4992 | ahd_outl(ahd, SCB_RESIDUAL_SGPTR0x184, sgptr); |
4993 | ahd_outl(ahd, SCB_RESIDUAL_DATACNT0x180, data_cnt); |
4994 | /* |
4995 | * The FIFO's pointers will be updated if/when the |
4996 | * sequencer re-enters a data phase. |
4997 | */ |
4998 | } |
4999 | } |
5000 | } |
5001 | |
5002 | |
5003 | /* |
5004 | * Reinitialize the data pointers for the active transfer |
5005 | * based on its current residual. |
5006 | */ |
5007 | void |
5008 | ahd_reinitialize_dataptrs(struct ahd_softc *ahd) |
5009 | { |
5010 | struct scb *scb; |
5011 | ahd_mode_state saved_modes; |
5012 | u_int scb_index; |
5013 | u_int wait; |
5014 | uint32_t sgptr; |
5015 | uint32_t resid; |
5016 | uint64_t dataptr; |
5017 | |
5018 | AHD_ASSERT_MODES(ahd, AHD_MODE_DFF0_MSK|AHD_MODE_DFF1_MSK,ahd_assert_modes(ahd, (0x01 << (AHD_MODE_DFF0))|(0x01 << (AHD_MODE_DFF1)), (0x01 << (AHD_MODE_DFF0))|(0x01 << (AHD_MODE_DFF1)), "/usr/src/sys/dev/ic/aic79xx.c", 5019); |
5019 | AHD_MODE_DFF0_MSK|AHD_MODE_DFF1_MSK)ahd_assert_modes(ahd, (0x01 << (AHD_MODE_DFF0))|(0x01 << (AHD_MODE_DFF1)), (0x01 << (AHD_MODE_DFF0))|(0x01 << (AHD_MODE_DFF1)), "/usr/src/sys/dev/ic/aic79xx.c", 5019);; |
5020 | |
5021 | scb_index = ahd_get_scbptr(ahd); |
5022 | scb = ahd_lookup_scb(ahd, scb_index); |
5023 | |
5024 | /* |
5025 | * Release and reacquire the FIFO so we |
5026 | * have a clean slate. |
5027 | */ |
5028 | ahd_outb(ahd, DFFSXFRCTL, CLRCHN)(((ahd)->tags[(0x5a) >> 8])->write_1(((ahd)->bshs [(0x5a) >> 8]), ((0x5a) & 0xFF), (0x02))); |
5029 | wait = 1000; |
5030 | while (--wait && !(ahd_inb(ahd, MDFFSTAT)(((ahd)->tags[(0x5d) >> 8])->read_1(((ahd)->bshs [(0x5d) >> 8]), ((0x5d) & 0xFF))) & FIFOFREE0x01)) |
5031 | aic_delay(100)(*delay_func)(100); |
5032 | if (wait == 0) { |
5033 | ahd_print_path(ahd, scb); |
5034 | printf("ahd_reinitialize_dataptrs: Forcing FIFO free.\n"); |
5035 | ahd_outb(ahd, DFFSXFRCTL, RSTCHN|CLRSHCNT)(((ahd)->tags[(0x5a) >> 8])->write_1(((ahd)->bshs [(0x5a) >> 8]), ((0x5a) & 0xFF), (0x01|0x04))); |
5036 | } |
5037 | saved_modes = ahd_save_modes(ahd); |
5038 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
5039 | ahd_outb(ahd, DFFSTAT,(((ahd)->tags[(0x3f) >> 8])->write_1(((ahd)->bshs [(0x3f) >> 8]), ((0x3f) & 0xFF), ((((ahd)->tags[ (0x3f) >> 8])->read_1(((ahd)->bshs[(0x3f) >> 8]), ((0x3f) & 0xFF))) | (saved_modes == 0x11 ? 0x01 : 0x00 )))) |
5040 | ahd_inb(ahd, DFFSTAT)(((ahd)->tags[(0x3f) >> 8])->write_1(((ahd)->bshs [(0x3f) >> 8]), ((0x3f) & 0xFF), ((((ahd)->tags[ (0x3f) >> 8])->read_1(((ahd)->bshs[(0x3f) >> 8]), ((0x3f) & 0xFF))) | (saved_modes == 0x11 ? 0x01 : 0x00 )))) |
5041 | | (saved_modes == 0x11 ? CURRFIFO_1 : CURRFIFO_0))(((ahd)->tags[(0x3f) >> 8])->write_1(((ahd)->bshs [(0x3f) >> 8]), ((0x3f) & 0xFF), ((((ahd)->tags[ (0x3f) >> 8])->read_1(((ahd)->bshs[(0x3f) >> 8]), ((0x3f) & 0xFF))) | (saved_modes == 0x11 ? 0x01 : 0x00 )))); |
5042 | |
5043 | /* |
5044 | * Determine initial values for data_addr and data_cnt |
5045 | * for resuming the data phase. |
5046 | */ |
5047 | sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR0x184); |
5048 | sgptr &= SG_PTR_MASK0xFFFFFFF8; |
5049 | |
5050 | resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT0x180 + 2) << 16) |
5051 | | (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT0x180 + 1) << 8) |
5052 | | ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT0x180); |
5053 | |
5054 | if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) { |
5055 | struct ahd_dma64_seg *sg; |
5056 | |
5057 | sg = ahd_sg_bus_to_virt(ahd, scb, sgptr); |
5058 | |
5059 | /* The residual sg_ptr always points to the next sg */ |
5060 | sg--; |
5061 | |
5062 | dataptr = aic_le64toh(sg->addr)((__uint64_t)(sg->addr)) |
5063 | + (aic_le32toh(sg->len)((__uint32_t)(sg->len)) & AHD_SG_LEN_MASK0x00FFFFFF) |
5064 | - resid; |
5065 | ahd_outl(ahd, HADDR0x70 + 4, dataptr >> 32); |
5066 | } else { |
5067 | struct ahd_dma_seg *sg; |
5068 | |
5069 | sg = ahd_sg_bus_to_virt(ahd, scb, sgptr); |
5070 | |
5071 | /* The residual sg_ptr always points to the next sg */ |
5072 | sg--; |
5073 | |
5074 | dataptr = aic_le32toh(sg->addr)((__uint32_t)(sg->addr)) |
5075 | + (aic_le32toh(sg->len)((__uint32_t)(sg->len)) & AHD_SG_LEN_MASK0x00FFFFFF) |
5076 | - resid; |
5077 | ahd_outb(ahd, HADDR + 4,(((ahd)->tags[(0x70 + 4) >> 8])->write_1(((ahd)-> bshs[(0x70 + 4) >> 8]), ((0x70 + 4) & 0xFF), ((((__uint32_t )(sg->len)) & ~0x00FFFFFF) >> 24))) |
5078 | (aic_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24)(((ahd)->tags[(0x70 + 4) >> 8])->write_1(((ahd)-> bshs[(0x70 + 4) >> 8]), ((0x70 + 4) & 0xFF), ((((__uint32_t )(sg->len)) & ~0x00FFFFFF) >> 24))); |
5079 | } |
5080 | ahd_outl(ahd, HADDR0x70, dataptr); |
5081 | ahd_outb(ahd, HCNT + 2, resid >> 16)(((ahd)->tags[(0x78 + 2) >> 8])->write_1(((ahd)-> bshs[(0x78 + 2) >> 8]), ((0x78 + 2) & 0xFF), (resid >> 16))); |
5082 | ahd_outb(ahd, HCNT + 1, resid >> 8)(((ahd)->tags[(0x78 + 1) >> 8])->write_1(((ahd)-> bshs[(0x78 + 1) >> 8]), ((0x78 + 1) & 0xFF), (resid >> 8))); |
5083 | ahd_outb(ahd, HCNT, resid)(((ahd)->tags[(0x78) >> 8])->write_1(((ahd)->bshs [(0x78) >> 8]), ((0x78) & 0xFF), (resid))); |
5084 | } |
5085 | |
5086 | /* |
5087 | * Handle the effects of issuing a bus device reset message. |
5088 | */ |
5089 | void |
5090 | ahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, |
5091 | u_int lun, cam_status status, char *message, |
5092 | int verbose_level) |
5093 | { |
5094 | #ifdef AHD_TARGET_MODE |
5095 | struct ahd_tmode_tstate* tstate; |
5096 | #endif |
5097 | int found; |
5098 | |
5099 | found = ahd_abort_scbs(ahd, devinfo->target, devinfo->channel, |
5100 | lun, SCB_LIST_NULL0xFF00, devinfo->role, |
5101 | status); |
5102 | |
5103 | #ifdef AHD_TARGET_MODE |
5104 | /* |
5105 | * Send an immediate notify ccb to all target mord peripheral |
5106 | * drivers affected by this action. |
5107 | */ |
5108 | tstate = ahd->enabled_targets[devinfo->our_scsiid]; |
5109 | if (tstate != NULL((void *)0)) { |
5110 | u_int cur_lun; |
5111 | u_int max_lun; |
5112 | |
5113 | if (lun != CAM_LUN_WILDCARD-1) { |
5114 | cur_lun = 0; |
5115 | max_lun = AHD_NUM_LUNS256 - 1; |
5116 | } else { |
5117 | cur_lun = lun; |
5118 | max_lun = lun; |
5119 | } |
5120 | for (cur_lun <= max_lun; cur_lun++) { |
5121 | struct ahd_tmode_lstate* lstate; |
5122 | |
5123 | lstate = tstate->enabled_luns[cur_lun]; |
5124 | if (lstate == NULL((void *)0)) |
5125 | continue; |
5126 | |
5127 | ahd_queue_lstate_event(ahd, lstate, devinfo->our_scsiid, |
5128 | MSG_BUS_DEV_RESET0x0c, /*arg*/0); |
5129 | ahd_send_lstate_events(ahd, lstate); |
5130 | } |
5131 | } |
5132 | #endif |
5133 | |
5134 | /* |
5135 | * Go back to async/narrow transfers and renegotiate. |
5136 | */ |
5137 | ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT0x00, |
5138 | AHD_TRANS_CUR0x01, /*paused*/TRUE1); |
5139 | ahd_set_syncrate(ahd, devinfo, /*period*/0, /*offset*/0, |
5140 | /*ppr_options*/0, AHD_TRANS_CUR0x01, |
5141 | /*paused*/TRUE1); |
5142 | |
5143 | #if 0 |
5144 | if (status != CAM_SEL_TIMEOUT) |
5145 | ahd_send_async(ahd, devinfo->channel, devinfo->target, |
5146 | lun, AC_SENT_BDR, NULL((void *)0)); |
5147 | #endif |
5148 | |
5149 | if (message != NULL((void *)0) |
5150 | && (verbose_level <= bootverbose0)) |
5151 | printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd), |
5152 | message, devinfo->channel, devinfo->target, found); |
5153 | } |
5154 | |
5155 | #ifdef AHD_TARGET_MODE |
5156 | void |
5157 | ahd_setup_target_msgin(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, |
5158 | struct scb *scb) |
5159 | { |
5160 | |
5161 | /* |
5162 | * To facilitate adding multiple messages together, |
5163 | * each routine should increment the index and len |
5164 | * variables instead of setting them explicitly. |
5165 | */ |
5166 | ahd->msgout_index = 0; |
5167 | ahd->msgout_len = 0; |
5168 | |
5169 | if (scb != NULL((void *)0) && (scb->flags & SCB_AUTO_NEGOTIATE) != 0) |
5170 | ahd_build_transfer_msg(ahd, devinfo); |
5171 | else |
5172 | panic("ahd_intr: AWAITING target message with no message"); |
5173 | |
5174 | ahd->msgout_index = 0; |
5175 | ahd->msg_type = MSG_TYPE_TARGET_MSGIN; |
5176 | } |
5177 | #endif |
5178 | /**************************** Initialization **********************************/ |
5179 | u_int |
5180 | ahd_sglist_size(struct ahd_softc *ahd) |
5181 | { |
5182 | bus_size_t list_size; |
5183 | |
5184 | list_size = sizeof(struct ahd_dma_seg) * AHD_NSEG((((((((64 * 1024)) >> 12) + 1)+((16)-1))/(16))*(16))); |
5185 | if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) |
5186 | list_size = sizeof(struct ahd_dma64_seg) * AHD_NSEG((((((((64 * 1024)) >> 12) + 1)+((16)-1))/(16))*(16))); |
5187 | return (list_size); |
5188 | } |
5189 | |
5190 | /* |
5191 | * Calculate the optimum S/G List allocation size. S/G elements used |
5192 | * for a given transaction must be physically contiguous. Assume the |
5193 | * OS will allocate full pages to us, so it doesn't make sense to request |
5194 | * less than a page. |
5195 | */ |
5196 | u_int |
5197 | ahd_sglist_allocsize(struct ahd_softc *ahd) |
5198 | { |
5199 | bus_size_t sg_list_increment; |
5200 | bus_size_t sg_list_size; |
5201 | bus_size_t max_list_size; |
5202 | bus_size_t best_list_size; |
5203 | |
5204 | /* Start out with the minimum required for AHD_NSEG. */ |
5205 | sg_list_increment = ahd_sglist_size(ahd); |
5206 | sg_list_size = sg_list_increment; |
5207 | |
5208 | /* Get us as close as possible to a page in size. */ |
5209 | while ((sg_list_size + sg_list_increment) <= PAGE_SIZE(1 << 12)) |
5210 | sg_list_size += sg_list_increment; |
5211 | |
5212 | /* |
5213 | * Try to reduce the amount of wastage by allocating |
5214 | * multiple pages. |
5215 | */ |
5216 | best_list_size = sg_list_size; |
5217 | max_list_size = roundup(sg_list_increment, PAGE_SIZE)((((sg_list_increment)+(((1 << 12))-1))/((1 << 12 )))*((1 << 12))); |
5218 | if (max_list_size < 4 * PAGE_SIZE(1 << 12)) |
5219 | max_list_size = 4 * PAGE_SIZE(1 << 12); |
5220 | if (max_list_size > (AHD_SCB_MAX_ALLOC512 * sg_list_increment)) |
5221 | max_list_size = (AHD_SCB_MAX_ALLOC512 * sg_list_increment); |
5222 | while ((sg_list_size + sg_list_increment) <= max_list_size |
5223 | && (sg_list_size % PAGE_SIZE(1 << 12)) != 0) { |
5224 | bus_size_t new_mod; |
5225 | bus_size_t best_mod; |
5226 | |
5227 | sg_list_size += sg_list_increment; |
5228 | new_mod = sg_list_size % PAGE_SIZE(1 << 12); |
5229 | best_mod = best_list_size % PAGE_SIZE(1 << 12); |
5230 | if (new_mod > best_mod || new_mod == 0) { |
5231 | best_list_size = sg_list_size; |
5232 | } |
5233 | } |
5234 | return (best_list_size); |
5235 | } |
5236 | |
5237 | /* |
5238 | * Perform initial initialization for a controller structure. |
5239 | */ |
5240 | struct ahd_softc * |
5241 | ahd_alloc(void *platform_arg, char *name) |
5242 | { |
5243 | struct ahd_softc *ahd = (struct ahd_softc *)platform_arg; |
5244 | |
5245 | ahd->seep_config = malloc(sizeof(*ahd->seep_config), |
5246 | M_DEVBUF2, M_NOWAIT0x0002); |
5247 | if (ahd->seep_config == NULL((void *)0)) |
5248 | return (NULL((void *)0)); |
5249 | |
5250 | TAILQ_INIT(&ahd->pending_scbs)do { (&ahd->pending_scbs)->tqh_first = ((void *)0); (&ahd->pending_scbs)->tqh_last = &(&ahd-> pending_scbs)->tqh_first; } while (0); |
5251 | LIST_INIT(&ahd->timedout_scbs)do { ((&ahd->timedout_scbs)->lh_first) = ((void *)0 ); } while (0); |
5252 | |
5253 | /* We don't know our unit number until the OSM sets it */ |
5254 | ahd->name = name; |
5255 | ahd->unit = -1; |
5256 | ahd->bus_description = NULL((void *)0); |
5257 | ahd->channel = 'A'; |
5258 | ahd->chip = AHD_NONE; |
5259 | ahd->features = AHD_FENONE; |
5260 | ahd->bugs = AHD_BUGNONE; |
5261 | ahd->flags = AHD_SPCHK_ENB_A|AHD_RESET_BUS_A|AHD_TERM_ENB_A |
5262 | | AHD_EXTENDED_TRANS_A|AHD_STPWLEVEL_A; |
5263 | ahd->int_coalescing_timer = AHD_INT_COALESCING_TIMER_DEFAULT250; |
5264 | ahd->int_coalescing_maxcmds = AHD_INT_COALESCING_MAXCMDS_DEFAULT10; |
5265 | ahd->int_coalescing_mincmds = AHD_INT_COALESCING_MINCMDS_DEFAULT5; |
5266 | ahd->int_coalescing_threshold = AHD_INT_COALESCING_THRESHOLD_DEFAULT2000; |
5267 | ahd->int_coalescing_stop_threshold = |
5268 | AHD_INT_COALESCING_STOP_THRESHOLD_DEFAULT1000; |
5269 | |
5270 | #ifdef AHD_DEBUG |
5271 | if ((ahd_debug & AHD_SHOW_MEMORY) != 0) { |
5272 | printf("%s: scb size = 0x%x, hscb size = 0x%x\n", |
5273 | ahd_name(ahd), (u_int)sizeof(struct scb), |
5274 | (u_int)sizeof(struct hardware_scb)); |
5275 | } |
5276 | #endif |
5277 | return (ahd); |
5278 | } |
5279 | |
5280 | int |
5281 | ahd_softc_init(struct ahd_softc *ahd) |
5282 | { |
5283 | |
5284 | ahd->unpause = 0; |
5285 | ahd->pause = PAUSE0x04; |
5286 | return (0); |
5287 | } |
5288 | |
5289 | void |
5290 | ahd_softc_insert(struct ahd_softc *ahd) |
5291 | { |
5292 | struct ahd_softc *list_ahd; |
5293 | |
5294 | #if AHD_PCI_CONFIG > 0 |
5295 | /* |
5296 | * Second Function PCI devices need to inherit some |
5297 | * settings from function 0. |
5298 | */ |
5299 | if ((ahd->features & AHD_MULTI_FUNC) != 0) { |
5300 | TAILQ_FOREACH(list_ahd, &ahd_tailq, links)for((list_ahd) = ((&ahd_tailq)->tqh_first); (list_ahd) != ((void *)0); (list_ahd) = ((list_ahd)->links.tqe_next) ) { |
5301 | aic_dev_softc_t list_pci; |
5302 | aic_dev_softc_t pci; |
5303 | |
5304 | list_pci = list_ahd->dev_softc; |
5305 | pci = ahd->dev_softc; |
5306 | if (aic_get_pci_slot(list_pci)((list_pci)->pa_device) == aic_get_pci_slot(pci)((pci)->pa_device) |
5307 | && aic_get_pci_bus(list_pci)((list_pci)->pa_bus) == aic_get_pci_bus(pci)((pci)->pa_bus)) { |
5308 | struct ahd_softc *master; |
5309 | struct ahd_softc *slave; |
5310 | |
5311 | if (aic_get_pci_function(list_pci)((list_pci)->pa_function) == 0) { |
5312 | master = list_ahd; |
5313 | slave = ahd; |
5314 | } else { |
5315 | master = ahd; |
5316 | slave = list_ahd; |
5317 | } |
5318 | slave->flags &= ~AHD_BIOS_ENABLED; |
5319 | slave->flags |= |
5320 | master->flags & AHD_BIOS_ENABLED; |
5321 | break; |
5322 | } |
5323 | } |
5324 | } |
5325 | #endif |
5326 | |
5327 | /* |
5328 | * Insertion sort into our list of softcs. |
5329 | */ |
5330 | list_ahd = TAILQ_FIRST(&ahd_tailq)((&ahd_tailq)->tqh_first); |
5331 | while (list_ahd != NULL((void *)0) |
5332 | && ahd_softc_comp(ahd, list_ahd) <= 0) |
5333 | list_ahd = TAILQ_NEXT(list_ahd, links)((list_ahd)->links.tqe_next); |
5334 | if (list_ahd != NULL((void *)0)) |
5335 | TAILQ_INSERT_BEFORE(list_ahd, ahd, links)do { (ahd)->links.tqe_prev = (list_ahd)->links.tqe_prev ; (ahd)->links.tqe_next = (list_ahd); *(list_ahd)->links .tqe_prev = (ahd); (list_ahd)->links.tqe_prev = &(ahd) ->links.tqe_next; } while (0); |
5336 | else |
5337 | TAILQ_INSERT_TAIL(&ahd_tailq, ahd, links)do { (ahd)->links.tqe_next = ((void *)0); (ahd)->links. tqe_prev = (&ahd_tailq)->tqh_last; *(&ahd_tailq)-> tqh_last = (ahd); (&ahd_tailq)->tqh_last = &(ahd)-> links.tqe_next; } while (0); |
5338 | ahd->init_level++; |
5339 | } |
5340 | |
5341 | /* |
5342 | * Verify that the passed in softc pointer is for a |
5343 | * controller that is still configured. |
5344 | */ |
5345 | struct ahd_softc * |
5346 | ahd_find_softc(struct ahd_softc *ahd) |
5347 | { |
5348 | struct ahd_softc *list_ahd; |
5349 | |
5350 | TAILQ_FOREACH(list_ahd, &ahd_tailq, links)for((list_ahd) = ((&ahd_tailq)->tqh_first); (list_ahd) != ((void *)0); (list_ahd) = ((list_ahd)->links.tqe_next) ) { |
5351 | if (list_ahd == ahd) |
5352 | return (ahd); |
5353 | } |
5354 | return (NULL((void *)0)); |
5355 | } |
5356 | |
5357 | void |
5358 | ahd_set_unit(struct ahd_softc *ahd, int unit) |
5359 | { |
5360 | ahd->unit = unit; |
5361 | } |
5362 | |
5363 | void |
5364 | ahd_set_name(struct ahd_softc *ahd, char *name) |
5365 | { |
5366 | if (ahd->name != NULL((void *)0)) |
5367 | free(ahd->name, M_DEVBUF2, 0); |
5368 | ahd->name = name; |
5369 | } |
5370 | |
5371 | void |
5372 | ahd_free(struct ahd_softc *ahd) |
5373 | { |
5374 | int i; |
5375 | |
5376 | switch (ahd->init_level) { |
5377 | default: |
5378 | case 2: |
5379 | ahd_shutdown(ahd); |
5380 | TAILQ_REMOVE(&ahd_tailq, ahd, links)do { if (((ahd)->links.tqe_next) != ((void *)0)) (ahd)-> links.tqe_next->links.tqe_prev = (ahd)->links.tqe_prev; else (&ahd_tailq)->tqh_last = (ahd)->links.tqe_prev ; *(ahd)->links.tqe_prev = (ahd)->links.tqe_next; ((ahd )->links.tqe_prev) = ((void *)-1); ((ahd)->links.tqe_next ) = ((void *)-1); } while (0); |
5381 | /* FALLTHROUGH */ |
5382 | case 1: |
5383 | ahd_freedmamem(ahd, &ahd->shared_data_map); |
5384 | break; |
5385 | case 0: |
5386 | break; |
5387 | } |
5388 | |
5389 | ahd_fini_scbdata(ahd); |
5390 | for (i = 0; i < AHD_NUM_TARGETS16; i++) { |
5391 | struct ahd_tmode_tstate *tstate; |
5392 | |
5393 | tstate = ahd->enabled_targets[i]; |
5394 | if (tstate != NULL((void *)0)) { |
5395 | #if AHD_TARGET_MODE |
5396 | int j; |
5397 | |
5398 | for (j = 0; j < AHD_NUM_LUNS256; j++) { |
5399 | struct ahd_tmode_lstate *lstate; |
5400 | |
5401 | lstate = tstate->enabled_luns[j]; |
5402 | if (lstate != NULL((void *)0)) { |
5403 | xpt_free_path(lstate->path); |
5404 | free(lstate, M_DEVBUF2, 0); |
5405 | } |
5406 | } |
5407 | #endif |
5408 | free(tstate, M_DEVBUF2, 0); |
5409 | } |
5410 | } |
5411 | #if AHD_TARGET_MODE |
5412 | if (ahd->black_hole != NULL((void *)0)) { |
5413 | xpt_free_path(ahd->black_hole->path); |
5414 | free(ahd->black_hole, M_DEVBUF2, 0); |
5415 | } |
5416 | #endif |
5417 | if (ahd->seep_config != NULL((void *)0)) |
5418 | free(ahd->seep_config, M_DEVBUF2, 0); |
5419 | if (ahd->saved_stack != NULL((void *)0)) |
5420 | free(ahd->saved_stack, M_DEVBUF2, 0); |
5421 | return; |
5422 | } |
5423 | |
5424 | void |
5425 | ahd_shutdown(void *arg) |
5426 | { |
5427 | struct ahd_softc *ahd; |
5428 | |
5429 | ahd = (struct ahd_softc *)arg; |
5430 | |
5431 | /* |
5432 | * Stop periodic timer callbacks. |
5433 | */ |
5434 | aic_timer_stoptimeout_del(&ahd->reset_timer); |
5435 | aic_timer_stoptimeout_del(&ahd->stat_timer); |
5436 | |
5437 | /* This will reset most registers to 0, but not all */ |
5438 | ahd_reset(ahd, /*reinit*/FALSE0); |
5439 | } |
5440 | |
5441 | /* |
5442 | * Reset the controller and record some information about it |
5443 | * that is only available just after a reset. If "reinit" is |
5444 | * non-zero, this reset occurred after initial configuration |
5445 | * and the caller requests that the chip be fully reinitialized |
5446 | * to a runable state. Chip interrupts are *not* enabled after |
5447 | * a reinitialization. The caller must enable interrupts via |
5448 | * ahd_intr_enable(). |
5449 | */ |
5450 | int |
5451 | ahd_reset(struct ahd_softc *ahd, int reinit) |
5452 | { |
5453 | const pci_chipset_tag_t pc = ahd->dev_softc->pa_pc; |
5454 | const pcitag_t tag = ahd->dev_softc->pa_tag; |
5455 | u_int sxfrctl1; |
5456 | int wait; |
5457 | pcireg_t cmd; |
5458 | |
5459 | /* |
5460 | * Preserve the value of the SXFRCTL1 register for all channels. |
5461 | * It contains settings that affect termination and we don't want |
5462 | * to disturb the integrity of the bus. |
5463 | */ |
5464 | ahd_pause(ahd); |
5465 | ahd_update_modes(ahd); |
5466 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
5467 | sxfrctl1 = ahd_inb(ahd, SXFRCTL1)(((ahd)->tags[(0x3d) >> 8])->read_1(((ahd)->bshs [(0x3d) >> 8]), ((0x3d) & 0xFF))); |
5468 | |
5469 | cmd = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG0x04); |
5470 | |
5471 | if ((ahd->bugs & AHD_PCIX_CHIPRST_BUG) != 0) { |
5472 | pcireg_t mod_cmd; |
5473 | |
5474 | /* |
5475 | * A4 Razor #632 |
5476 | * During the assertion of CHIPRST, the chip |
5477 | * does not disable its parity logic prior to |
5478 | * the start of the reset. This may cause a |
5479 | * parity error to be detected and thus a |
5480 | * spurious SERR or PERR assertion. Disable |
5481 | * PERR and SERR responses during the CHIPRST. |
5482 | */ |
5483 | mod_cmd = cmd & ~(PCI_COMMAND_PARITY_ENABLE0x00000040|PCI_COMMAND_SERR_ENABLE0x00000100); |
5484 | pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG0x04, mod_cmd); |
5485 | } |
5486 | ahd_outb(ahd, HCNTRL, CHIPRST | ahd->pause)(((ahd)->tags[(0x05) >> 8])->write_1(((ahd)->bshs [(0x05) >> 8]), ((0x05) & 0xFF), (0x01 | ahd->pause ))); |
5487 | |
5488 | /* |
5489 | * Ensure that the reset has finished. We delay 1000us |
5490 | * prior to reading the register to make sure the chip |
5491 | * has sufficiently completed its reset to handle register |
5492 | * accesses. |
5493 | */ |
5494 | wait = 1000; |
5495 | do { |
5496 | aic_delay(1000)(*delay_func)(1000); |
5497 | } while (--wait && !(ahd_inb(ahd, HCNTRL)(((ahd)->tags[(0x05) >> 8])->read_1(((ahd)->bshs [(0x05) >> 8]), ((0x05) & 0xFF))) & CHIPRSTACK0x01)); |
5498 | |
5499 | if (wait == 0) { |
5500 | printf("%s: WARNING - Failed chip reset! " |
5501 | "Trying to initialize anyway.\n", ahd_name(ahd)); |
5502 | } |
5503 | ahd_outb(ahd, HCNTRL, ahd->pause)(((ahd)->tags[(0x05) >> 8])->write_1(((ahd)->bshs [(0x05) >> 8]), ((0x05) & 0xFF), (ahd->pause))); |
5504 | |
5505 | if ((ahd->bugs & AHD_PCIX_CHIPRST_BUG) != 0) { |
5506 | /* |
5507 | * Clear any latched PCI error status and restore |
5508 | * previous SERR and PERR response enables. |
5509 | */ |
5510 | pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG0x04, cmd | |
5511 | (PCI_STATUS_PARITY_ERROR0x01000000 | PCI_STATUS_TARGET_TARGET_ABORT0x08000000 | |
5512 | PCI_STATUS_MASTER_TARGET_ABORT0x10000000 | PCI_STATUS_MASTER_ABORT0x20000000 | |
5513 | PCI_STATUS_SPECIAL_ERROR0x40000000)); |
5514 | |
5515 | } |
5516 | |
5517 | /* |
5518 | * Mode should be SCSI after a chip reset, but lets |
5519 | * set it just to be safe. We touch the MODE_PTR |
5520 | * register directly so as to bypass the lazy update |
5521 | * code in ahd_set_modes(). |
5522 | */ |
5523 | ahd_known_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
5524 | ahd_outb(ahd, MODE_PTR,(((ahd)->tags[(0x00) >> 8])->write_1(((ahd)->bshs [(0x00) >> 8]), ((0x00) & 0xFF), (ahd_build_mode_state (ahd, AHD_MODE_SCSI, AHD_MODE_SCSI)))) |
5525 | ahd_build_mode_state(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI))(((ahd)->tags[(0x00) >> 8])->write_1(((ahd)->bshs [(0x00) >> 8]), ((0x00) & 0xFF), (ahd_build_mode_state (ahd, AHD_MODE_SCSI, AHD_MODE_SCSI)))); |
5526 | |
5527 | /* |
5528 | * Restore SXFRCTL1. |
5529 | * |
5530 | * We must always initialize STPWEN to 1 before we |
5531 | * restore the saved values. STPWEN is initialized |
5532 | * to a tri-state condition which can only be cleared |
5533 | * by turning it on. |
5534 | */ |
5535 | ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN)(((ahd)->tags[(0x3d) >> 8])->write_1(((ahd)->bshs [(0x3d) >> 8]), ((0x3d) & 0xFF), (sxfrctl1|0x01))); |
5536 | ahd_outb(ahd, SXFRCTL1, sxfrctl1)(((ahd)->tags[(0x3d) >> 8])->write_1(((ahd)->bshs [(0x3d) >> 8]), ((0x3d) & 0xFF), (sxfrctl1))); |
5537 | |
5538 | /* Determine chip configuration */ |
5539 | ahd->features &= ~AHD_WIDE; |
5540 | if ((ahd_inb(ahd, SBLKCTL)(((ahd)->tags[(0x4a) >> 8])->read_1(((ahd)->bshs [(0x4a) >> 8]), ((0x4a) & 0xFF))) & SELWIDE0x02) != 0) |
5541 | ahd->features |= AHD_WIDE; |
5542 | |
5543 | /* |
5544 | * If a recovery action has forced a chip reset, |
5545 | * re-initialize the chip to our liking. |
5546 | */ |
5547 | if (reinit != 0) |
5548 | ahd_chip_init(ahd); |
5549 | |
5550 | return (0); |
5551 | } |
5552 | |
5553 | /* |
5554 | * Determine the number of SCBs available on the controller |
5555 | */ |
5556 | int |
5557 | ahd_probe_scbs(struct ahd_softc *ahd) { |
5558 | int i; |
5559 | |
5560 | AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),ahd_assert_modes(ahd, ~((0x01 << (AHD_MODE_UNKNOWN))|(0x01 << (AHD_MODE_CFG))), ~((0x01 << (AHD_MODE_UNKNOWN ))|(0x01 << (AHD_MODE_CFG))), "/usr/src/sys/dev/ic/aic79xx.c" , 5561); |
5561 | ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK))ahd_assert_modes(ahd, ~((0x01 << (AHD_MODE_UNKNOWN))|(0x01 << (AHD_MODE_CFG))), ~((0x01 << (AHD_MODE_UNKNOWN ))|(0x01 << (AHD_MODE_CFG))), "/usr/src/sys/dev/ic/aic79xx.c" , 5561);; |
5562 | for (i = 0; i < AHD_SCB_MAX512; i++) { |
5563 | int j; |
5564 | |
5565 | ahd_set_scbptr(ahd, i); |
5566 | ahd_outw(ahd, SCB_BASE0x180, i); |
5567 | for (j = 2; j < 64; j++) |
5568 | ahd_outb(ahd, SCB_BASE+j, 0)(((ahd)->tags[(0x180 +j) >> 8])->write_1(((ahd)-> bshs[(0x180 +j) >> 8]), ((0x180 +j) & 0xFF), (0))); |
5569 | /* Start out life as unallocated (needing an abort) */ |
5570 | ahd_outb(ahd, SCB_CONTROL, MK_MESSAGE)(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (0x10))); |
5571 | if (ahd_inw_scbram(ahd, SCB_BASE0x180) != i) |
5572 | break; |
5573 | ahd_set_scbptr(ahd, 0); |
5574 | if (ahd_inw_scbram(ahd, SCB_BASE0x180) != 0) |
5575 | break; |
5576 | } |
5577 | return (i); |
5578 | } |
5579 | |
5580 | void |
5581 | ahd_initialize_hscbs(struct ahd_softc *ahd) |
5582 | { |
5583 | int i; |
5584 | |
5585 | for (i = 0; i < ahd->scb_data.maxhscbs; i++) { |
5586 | ahd_set_scbptr(ahd, i); |
5587 | |
5588 | /* Clear the control byte. */ |
5589 | ahd_outb(ahd, SCB_CONTROL, 0)(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (0))); |
5590 | |
5591 | /* Set the next pointer */ |
5592 | ahd_outw(ahd, SCB_NEXT0x1ac, SCB_LIST_NULL0xFF00); |
5593 | } |
5594 | } |
5595 | |
5596 | int |
5597 | ahd_init_scbdata(struct ahd_softc *ahd) |
5598 | { |
5599 | struct scb_data *scb_data; |
5600 | int i; |
5601 | |
5602 | scb_data = &ahd->scb_data; |
5603 | TAILQ_INIT(&scb_data->free_scbs)do { (&scb_data->free_scbs)->tqh_first = ((void *)0 ); (&scb_data->free_scbs)->tqh_last = &(&scb_data ->free_scbs)->tqh_first; } while (0); |
5604 | SLIST_INIT(&scb_data->hscb_maps){ ((&scb_data->hscb_maps)->slh_first) = ((void *)0) ; }; |
5605 | SLIST_INIT(&scb_data->sg_maps){ ((&scb_data->sg_maps)->slh_first) = ((void *)0); }; |
5606 | SLIST_INIT(&scb_data->sense_maps){ ((&scb_data->sense_maps)->slh_first) = ((void *)0 ); }; |
5607 | mtx_init(&ahd->sc_scb_mtx, IPL_BIO)do { (void)(((void *)0)); (void)(0); __mtx_init((&ahd-> sc_scb_mtx), ((((0x3)) > 0x0 && ((0x3)) < 0x9) ? 0x9 : ((0x3)))); } while (0); |
5608 | scsi_iopool_init(&ahd->sc_iopool, ahd, ahd_scb_alloc, ahd_scb_free); |
5609 | |
5610 | /* Determine the number of hardware SCBs and initialize them */ |
5611 | scb_data->maxhscbs = ahd_probe_scbs(ahd); |
5612 | if (scb_data->maxhscbs == 0) { |
5613 | printf("%s: No SCB space found\n", ahd_name(ahd)); |
5614 | return (ENXIO6); |
5615 | } |
5616 | |
5617 | ahd_initialize_hscbs(ahd); |
5618 | |
5619 | /* |
5620 | * Create our DMA tags. These tags define the kinds of device |
5621 | * accessible memory allocations and memory mappings we will |
5622 | * need to perform during normal operation. |
5623 | * |
5624 | * Unless we need to further restrict the allocation, we rely |
5625 | * on the restrictions of the parent dmat, hence the common |
5626 | * use of MAXADDR and MAXSIZE. |
5627 | */ |
5628 | |
5629 | /* Perform initial CCB allocation */ |
5630 | do { |
5631 | i = scb_data->numscbs; |
5632 | ahd_alloc_scbs(ahd); |
5633 | } while ((i != scb_data->numscbs) && |
5634 | (scb_data->numscbs < AHD_SCB_MAX_ALLOC512)); |
5635 | |
5636 | if (scb_data->numscbs != AHD_SCB_MAX_ALLOC512) { |
5637 | printf("%s: ahd_init_scbdata - " |
5638 | "Unable to allocate initial scbs\n", |
5639 | ahd_name(ahd)); |
5640 | goto error_exit; |
5641 | } |
5642 | |
5643 | /* |
5644 | * Note that we were successful |
5645 | */ |
5646 | return (0); |
5647 | |
5648 | error_exit: |
5649 | |
5650 | return (ENOMEM12); |
5651 | } |
5652 | |
5653 | struct scb * |
5654 | ahd_find_scb_by_tag(struct ahd_softc *ahd, u_int tag) |
5655 | { |
5656 | struct scb *scb; |
5657 | |
5658 | /* |
5659 | * Look on the pending list. |
5660 | */ |
5661 | TAILQ_FOREACH(scb, &ahd->pending_scbs, next)for((scb) = ((&ahd->pending_scbs)->tqh_first); (scb ) != ((void *)0); (scb) = ((scb)->next.tqe_next)) { |
5662 | if (SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)) == tag) |
5663 | return (scb); |
5664 | } |
5665 | |
5666 | /* |
5667 | * And finally on the generic free list. |
5668 | */ |
5669 | TAILQ_FOREACH(scb, &ahd->scb_data.free_scbs, next)for((scb) = ((&ahd->scb_data.free_scbs)->tqh_first) ; (scb) != ((void *)0); (scb) = ((scb)->next.tqe_next)) { |
5670 | if (SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)) == tag) |
5671 | return (scb); |
5672 | } |
5673 | |
5674 | return (NULL((void *)0)); |
5675 | } |
5676 | |
5677 | void |
5678 | ahd_fini_scbdata(struct ahd_softc *ahd) |
5679 | { |
5680 | struct scb_data *scb_data; |
5681 | |
5682 | scb_data = &ahd->scb_data; |
5683 | if (scb_data == NULL((void *)0)) |
5684 | return; |
5685 | |
5686 | switch (scb_data->init_level) { |
5687 | default: |
5688 | case 3: |
5689 | { |
5690 | struct map_node *sns_map; |
5691 | |
5692 | while ((sns_map = SLIST_FIRST(&scb_data->sense_maps)((&scb_data->sense_maps)->slh_first)) != NULL((void *)0)) { |
5693 | SLIST_REMOVE_HEAD(&scb_data->sense_maps, links)do { (&scb_data->sense_maps)->slh_first = (&scb_data ->sense_maps)->slh_first->links.sle_next; } while (0 ); |
5694 | ahd_freedmamem(ahd, sns_map); |
5695 | free(sns_map, M_DEVBUF2, 0); |
5696 | } |
5697 | /* FALLTHROUGH */ |
5698 | } |
5699 | case 2: |
5700 | { |
5701 | struct map_node *sg_map; |
5702 | |
5703 | while ((sg_map = SLIST_FIRST(&scb_data->sg_maps)((&scb_data->sg_maps)->slh_first)) != NULL((void *)0)) { |
5704 | SLIST_REMOVE_HEAD(&scb_data->sg_maps, links)do { (&scb_data->sg_maps)->slh_first = (&scb_data ->sg_maps)->slh_first->links.sle_next; } while (0); |
5705 | ahd_freedmamem(ahd, sg_map); |
5706 | free(sg_map, M_DEVBUF2, 0); |
5707 | } |
5708 | /* FALLTHROUGH */ |
5709 | } |
5710 | case 1: |
5711 | { |
5712 | struct map_node *hscb_map; |
5713 | |
5714 | while ((hscb_map = SLIST_FIRST(&scb_data->hscb_maps)((&scb_data->hscb_maps)->slh_first)) != NULL((void *)0)) { |
5715 | SLIST_REMOVE_HEAD(&scb_data->hscb_maps, links)do { (&scb_data->hscb_maps)->slh_first = (&scb_data ->hscb_maps)->slh_first->links.sle_next; } while (0); |
5716 | ahd_freedmamem(ahd, hscb_map); |
5717 | free(hscb_map, M_DEVBUF2, 0); |
5718 | } |
5719 | /* FALLTHROUGH */ |
5720 | } |
5721 | case 0: |
5722 | break; |
5723 | } |
5724 | } |
5725 | |
5726 | /* |
5727 | * DSP filter Bypass must be enabled until the first selection |
5728 | * after a change in bus mode (Razor #491 and #493). |
5729 | */ |
5730 | void |
5731 | ahd_setup_iocell_workaround(struct ahd_softc *ahd) |
5732 | { |
5733 | ahd_mode_state saved_modes; |
5734 | |
5735 | saved_modes = ahd_save_modes(ahd); |
5736 | ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); |
5737 | ahd_outb(ahd, DSPDATACTL, ahd_inb(ahd, DSPDATACTL)(((ahd)->tags[(0xc1) >> 8])->write_1(((ahd)->bshs [(0xc1) >> 8]), ((0xc1) & 0xFF), ((((ahd)->tags[ (0xc1) >> 8])->read_1(((ahd)->bshs[(0xc1) >> 8]), ((0xc1) & 0xFF))) | 0x80 | 0x04 | 0x02))) |
5738 | | BYPASSENAB | RCVROFFSTDIS | XMITOFFSTDIS)(((ahd)->tags[(0xc1) >> 8])->write_1(((ahd)->bshs [(0xc1) >> 8]), ((0xc1) & 0xFF), ((((ahd)->tags[ (0xc1) >> 8])->read_1(((ahd)->bshs[(0xc1) >> 8]), ((0xc1) & 0xFF))) | 0x80 | 0x04 | 0x02))); |
5739 | ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) | (ENSELDO|ENSELDI))(((ahd)->tags[(0x4b) >> 8])->write_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF), ((((ahd)->tags[ (0x4b) >> 8])->read_1(((ahd)->bshs[(0x4b) >> 8]), ((0x4b) & 0xFF))) | (0x40|0x20)))); |
5740 | #ifdef AHD_DEBUG |
5741 | if ((ahd_debug & AHD_SHOW_MISC) != 0) |
5742 | printf("%s: Setting up iocell workaround\n", ahd_name(ahd)); |
5743 | #endif |
5744 | ahd_restore_modes(ahd, saved_modes); |
5745 | ahd->flags &= ~AHD_HAD_FIRST_SEL; |
5746 | } |
5747 | |
5748 | void |
5749 | ahd_iocell_first_selection(struct ahd_softc *ahd) |
5750 | { |
5751 | ahd_mode_state saved_modes; |
5752 | u_int sblkctl; |
5753 | |
5754 | if ((ahd->flags & AHD_HAD_FIRST_SEL) != 0) |
5755 | return; |
5756 | saved_modes = ahd_save_modes(ahd); |
5757 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
5758 | sblkctl = ahd_inb(ahd, SBLKCTL)(((ahd)->tags[(0x4a) >> 8])->read_1(((ahd)->bshs [(0x4a) >> 8]), ((0x4a) & 0xFF))); |
5759 | ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); |
5760 | #ifdef AHD_DEBUG |
5761 | if ((ahd_debug & AHD_SHOW_MISC) != 0) |
5762 | printf("%s: iocell first selection\n", ahd_name(ahd)); |
5763 | #endif |
5764 | if ((sblkctl & ENAB400x08) != 0) { |
5765 | ahd_outb(ahd, DSPDATACTL,(((ahd)->tags[(0xc1) >> 8])->write_1(((ahd)->bshs [(0xc1) >> 8]), ((0xc1) & 0xFF), ((((ahd)->tags[ (0xc1) >> 8])->read_1(((ahd)->bshs[(0xc1) >> 8]), ((0xc1) & 0xFF))) & ~0x80))) |
5766 | ahd_inb(ahd, DSPDATACTL) & ~BYPASSENAB)(((ahd)->tags[(0xc1) >> 8])->write_1(((ahd)->bshs [(0xc1) >> 8]), ((0xc1) & 0xFF), ((((ahd)->tags[ (0xc1) >> 8])->read_1(((ahd)->bshs[(0xc1) >> 8]), ((0xc1) & 0xFF))) & ~0x80))); |
5767 | #ifdef AHD_DEBUG |
5768 | if ((ahd_debug & AHD_SHOW_MISC) != 0) |
5769 | printf("%s: BYPASS now disabled\n", ahd_name(ahd)); |
5770 | #endif |
5771 | } |
5772 | ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) & ~(ENSELDO|ENSELDI))(((ahd)->tags[(0x4b) >> 8])->write_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF), ((((ahd)->tags[ (0x4b) >> 8])->read_1(((ahd)->bshs[(0x4b) >> 8]), ((0x4b) & 0xFF))) & ~(0x40|0x20)))); |
5773 | ahd_outb(ahd, CLRINT, CLRSCSIINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x08))); |
5774 | ahd_restore_modes(ahd, saved_modes); |
5775 | ahd->flags |= AHD_HAD_FIRST_SEL; |
5776 | } |
5777 | |
5778 | /* |
5779 | * Get a free scb. If there are none, see if we can allocate a new SCB. |
5780 | */ |
5781 | void * |
5782 | ahd_scb_alloc(void *xahd) |
5783 | { |
5784 | struct ahd_softc *ahd = xahd; |
5785 | struct scb *scb; |
5786 | |
5787 | mtx_enter(&ahd->sc_scb_mtx); |
5788 | scb = TAILQ_FIRST(&ahd->scb_data.free_scbs)((&ahd->scb_data.free_scbs)->tqh_first); |
5789 | if (scb) { |
5790 | TAILQ_REMOVE(&ahd->scb_data.free_scbs, scb, next)do { if (((scb)->next.tqe_next) != ((void *)0)) (scb)-> next.tqe_next->next.tqe_p |