File: | dev/ic/aic79xx.c |
Warning: | line 1558, column 2 Value stored to 'busfreetime' 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; |
Value stored to 'busfreetime' is never read | |
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)); |
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_prev = (scb)->next.tqe_prev; else (&ahd->scb_data.free_scbs)->tqh_last = (scb)->next .tqe_prev; *(scb)->next.tqe_prev = (scb)->next.tqe_next ; ((scb)->next.tqe_prev) = ((void *)-1); ((scb)->next.tqe_next ) = ((void *)-1); } while (0); |
5791 | scb->flags |= SCB_ACTIVE; |
5792 | } |
5793 | mtx_leave(&ahd->sc_scb_mtx); |
5794 | |
5795 | return (scb); |
5796 | } |
5797 | |
5798 | /* |
5799 | * Return an SCB resource to the free list. |
5800 | */ |
5801 | void |
5802 | ahd_scb_free(void *xahd, void *xscb) |
5803 | { |
5804 | struct ahd_softc *ahd = xahd; |
5805 | struct scb *scb = xscb; |
5806 | |
5807 | /* Clean up for the next user */ |
5808 | scb->flags = SCB_FLAG_NONE; |
5809 | scb->hscb->control = 0; |
5810 | ahd->scb_data.scbindex[SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag))] = NULL((void *)0); |
5811 | |
5812 | mtx_enter(&ahd->sc_scb_mtx); |
5813 | TAILQ_INSERT_HEAD(&ahd->scb_data.free_scbs, scb, next)do { if (((scb)->next.tqe_next = (&ahd->scb_data.free_scbs )->tqh_first) != ((void *)0)) (&ahd->scb_data.free_scbs )->tqh_first->next.tqe_prev = &(scb)->next.tqe_next ; else (&ahd->scb_data.free_scbs)->tqh_last = & (scb)->next.tqe_next; (&ahd->scb_data.free_scbs)-> tqh_first = (scb); (scb)->next.tqe_prev = &(&ahd-> scb_data.free_scbs)->tqh_first; } while (0); |
5814 | aic_platform_scb_free(ahd, scb); |
5815 | mtx_leave(&ahd->sc_scb_mtx); |
5816 | } |
5817 | |
5818 | void |
5819 | ahd_alloc_scbs(struct ahd_softc *ahd) |
5820 | { |
5821 | struct scb_data *scb_data; |
5822 | struct scb *next_scb; |
5823 | struct hardware_scb *hscb; |
5824 | struct map_node *hscb_map; |
5825 | struct map_node *sg_map; |
5826 | struct map_node *sense_map; |
5827 | uint8_t *segs; |
5828 | uint8_t *sense_data; |
5829 | bus_addr_t hscb_busaddr; |
5830 | bus_addr_t sg_busaddr; |
5831 | bus_addr_t sense_busaddr; |
5832 | int newcount; |
5833 | int i; |
5834 | |
5835 | scb_data = &ahd->scb_data; |
5836 | if (scb_data->numscbs >= AHD_SCB_MAX_ALLOC512) |
5837 | /* Can't allocate any more */ |
5838 | return; |
5839 | |
5840 | KASSERT(scb_data->scbs_left >= 0)((scb_data->scbs_left >= 0) ? (void)0 : __assert("diagnostic " , "/usr/src/sys/dev/ic/aic79xx.c", 5840, "scb_data->scbs_left >= 0" )); |
5841 | if (scb_data->scbs_left != 0) { |
5842 | int offset; |
5843 | |
5844 | offset = (PAGE_SIZE(1 << 12) / sizeof(*hscb)) - scb_data->scbs_left; |
5845 | hscb_map = SLIST_FIRST(&scb_data->hscb_maps)((&scb_data->hscb_maps)->slh_first); |
5846 | hscb = &((struct hardware_scb *)hscb_map->vaddr)[offset]; |
5847 | hscb_busaddr = hscb_map->busaddr + (offset * sizeof(*hscb)); |
5848 | } else { |
5849 | hscb_map = malloc(sizeof(*hscb_map), M_DEVBUF2, M_NOWAIT0x0002); |
5850 | |
5851 | if (hscb_map == NULL((void *)0)) |
5852 | return; |
5853 | |
5854 | /* Allocate the next batch of hardware SCBs */ |
5855 | if (ahd_createdmamem(ahd, PAGE_SIZE(1 << 12), hscb_map, |
5856 | "hardware SCB structures") < 0) { |
5857 | free(hscb_map, M_DEVBUF2, 0); |
5858 | return; |
5859 | } |
5860 | |
5861 | SLIST_INSERT_HEAD(&scb_data->hscb_maps, hscb_map, links)do { (hscb_map)->links.sle_next = (&scb_data->hscb_maps )->slh_first; (&scb_data->hscb_maps)->slh_first = (hscb_map); } while (0); |
5862 | |
5863 | hscb = (struct hardware_scb *)hscb_map->vaddr; |
5864 | hscb_busaddr = hscb_map->busaddr; |
5865 | scb_data->scbs_left = PAGE_SIZE(1 << 12) / sizeof(*hscb); |
5866 | } |
5867 | |
5868 | scb_data->init_level++; |
5869 | |
5870 | if (scb_data->sgs_left != 0) { |
5871 | int offset; |
5872 | |
5873 | offset = ((ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd)) |
5874 | - scb_data->sgs_left) * ahd_sglist_size(ahd); |
5875 | sg_map = SLIST_FIRST(&scb_data->sg_maps)((&scb_data->sg_maps)->slh_first); |
5876 | segs = sg_map->vaddr + offset; |
5877 | sg_busaddr = sg_map->busaddr + offset; |
5878 | } else { |
5879 | sg_map = malloc(sizeof(*sg_map), M_DEVBUF2, M_NOWAIT0x0002); |
5880 | |
5881 | if (sg_map == NULL((void *)0)) |
5882 | return; |
5883 | |
5884 | /* Allocate the next batch of S/G lists */ |
5885 | if (ahd_createdmamem(ahd, ahd_sglist_allocsize(ahd), sg_map, |
5886 | "SG data structures") < 0) { |
5887 | free(sg_map, M_DEVBUF2, 0); |
5888 | return; |
5889 | } |
5890 | |
5891 | SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links)do { (sg_map)->links.sle_next = (&scb_data->sg_maps )->slh_first; (&scb_data->sg_maps)->slh_first = ( sg_map); } while (0); |
5892 | |
5893 | segs = sg_map->vaddr; |
5894 | sg_busaddr = sg_map->busaddr; |
5895 | scb_data->sgs_left = |
5896 | ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd); |
5897 | #ifdef AHD_DEBUG |
5898 | if (ahd_debug & AHD_SHOW_MEMORY) |
5899 | printf("%s: ahd_alloc_scbs - Mapped SG data\n", ahd_name(ahd)); |
5900 | #endif |
5901 | } |
5902 | |
5903 | scb_data->init_level++; |
5904 | |
5905 | if (scb_data->sense_left != 0) { |
5906 | int offset; |
5907 | |
5908 | offset = PAGE_SIZE(1 << 12) - (AHD_SENSE_BUFSIZE0x100 * scb_data->sense_left); |
5909 | sense_map = SLIST_FIRST(&scb_data->sense_maps)((&scb_data->sense_maps)->slh_first); |
5910 | sense_data = sense_map->vaddr + offset; |
5911 | sense_busaddr = sense_map->busaddr + offset; |
5912 | } else { |
5913 | sense_map = malloc(sizeof(*sense_map), M_DEVBUF2, M_NOWAIT0x0002); |
5914 | |
5915 | if (sense_map == NULL((void *)0)) |
5916 | return; |
5917 | |
5918 | /* Allocate the next batch of sense buffers */ |
5919 | if (ahd_createdmamem(ahd, PAGE_SIZE(1 << 12), sense_map, |
5920 | "Sense Data structures") < 0) { |
5921 | free(sense_map, M_DEVBUF2, 0); |
5922 | return; |
5923 | } |
5924 | |
5925 | SLIST_INSERT_HEAD(&scb_data->sense_maps, sense_map, links)do { (sense_map)->links.sle_next = (&scb_data->sense_maps )->slh_first; (&scb_data->sense_maps)->slh_first = (sense_map); } while (0); |
5926 | |
5927 | sense_data = sense_map->vaddr; |
5928 | sense_busaddr = sense_map->busaddr; |
5929 | scb_data->sense_left = PAGE_SIZE(1 << 12) / AHD_SENSE_BUFSIZE0x100; |
5930 | #ifdef AHD_DEBUG |
5931 | if (ahd_debug & AHD_SHOW_MEMORY) |
5932 | printf("%s: ahd_alloc_scbs - Mapped sense data\n", ahd_name(ahd)); |
5933 | #endif |
5934 | } |
5935 | |
5936 | scb_data->init_level++; |
5937 | |
5938 | newcount = MIN(scb_data->sense_left, scb_data->scbs_left)(((scb_data->sense_left)<(scb_data->scbs_left))?(scb_data ->sense_left):(scb_data->scbs_left)); |
5939 | newcount = MIN(newcount, scb_data->sgs_left)(((newcount)<(scb_data->sgs_left))?(newcount):(scb_data ->sgs_left)); |
5940 | newcount = MIN(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs))(((newcount)<((512 - scb_data->numscbs)))?(newcount):(( 512 - scb_data->numscbs))); |
5941 | scb_data->sense_left -= newcount; |
5942 | scb_data->scbs_left -= newcount; |
5943 | scb_data->sgs_left -= newcount; |
5944 | for (i = 0; i < newcount; i++) { |
5945 | int error; |
5946 | |
5947 | next_scb = (struct scb *)malloc(sizeof(*next_scb), |
5948 | M_DEVBUF2, M_NOWAIT0x0002); |
5949 | if (next_scb == NULL((void *)0)) |
5950 | break; |
5951 | |
5952 | next_scb->hscb_map = hscb_map; |
5953 | next_scb->sg_map = sg_map; |
5954 | next_scb->sense_map = sense_map; |
5955 | next_scb->sg_list = segs; |
5956 | next_scb->sense_data = sense_data; |
5957 | next_scb->sense_busaddr = sense_busaddr; |
5958 | memset(hscb, 0, sizeof(*hscb))__builtin_memset((hscb), (0), (sizeof(*hscb))); |
5959 | next_scb->hscb = hscb; |
5960 | KASSERT((vaddr_t)hscb >= (vaddr_t)hscb_map->vaddr &&(((vaddr_t)hscb >= (vaddr_t)hscb_map->vaddr && ( vaddr_t)hscb < (vaddr_t)hscb_map->vaddr + (1 << 12 )) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/aic79xx.c" , 5961, "(vaddr_t)hscb >= (vaddr_t)hscb_map->vaddr && (vaddr_t)hscb < (vaddr_t)hscb_map->vaddr + PAGE_SIZE" )) |
5961 | (vaddr_t)hscb < (vaddr_t)hscb_map->vaddr + PAGE_SIZE)(((vaddr_t)hscb >= (vaddr_t)hscb_map->vaddr && ( vaddr_t)hscb < (vaddr_t)hscb_map->vaddr + (1 << 12 )) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/aic79xx.c" , 5961, "(vaddr_t)hscb >= (vaddr_t)hscb_map->vaddr && (vaddr_t)hscb < (vaddr_t)hscb_map->vaddr + PAGE_SIZE" )); |
5962 | hscb->hscb_busaddr = aic_htole32(hscb_busaddr)((__uint32_t)(hscb_busaddr)); |
5963 | |
5964 | /* |
5965 | * The sequencer always starts with the second entry. |
5966 | * The first entry is embedded in the scb. |
5967 | */ |
5968 | next_scb->sg_list_busaddr = sg_busaddr; |
5969 | if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) |
5970 | next_scb->sg_list_busaddr |
5971 | += sizeof(struct ahd_dma64_seg); |
5972 | else |
5973 | next_scb->sg_list_busaddr += sizeof(struct ahd_dma_seg); |
5974 | next_scb->ahd_softc = ahd; |
5975 | next_scb->flags = SCB_FLAG_NONE; |
5976 | |
5977 | error = bus_dmamap_create(ahd->parent_dmat,(*(ahd->parent_dmat)->_dmamap_create)((ahd->parent_dmat ), (0x00ffffff), (((((((((64 * 1024)) >> 12) + 1)+((16) -1))/(16))*(16)))), ((64 * 1024)), (0), (0x0001|0x0002), (& next_scb->dmamap)) |
5978 | AHD_MAXTRANSFER_SIZE, AHD_NSEG, MAXBSIZE, 0,(*(ahd->parent_dmat)->_dmamap_create)((ahd->parent_dmat ), (0x00ffffff), (((((((((64 * 1024)) >> 12) + 1)+((16) -1))/(16))*(16)))), ((64 * 1024)), (0), (0x0001|0x0002), (& next_scb->dmamap)) |
5979 | BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &next_scb->dmamap)(*(ahd->parent_dmat)->_dmamap_create)((ahd->parent_dmat ), (0x00ffffff), (((((((((64 * 1024)) >> 12) + 1)+((16) -1))/(16))*(16)))), ((64 * 1024)), (0), (0x0001|0x0002), (& next_scb->dmamap)); |
5980 | |
5981 | if (error != 0) { |
5982 | free(next_scb, M_DEVBUF2, 0); |
5983 | break; |
5984 | } |
5985 | next_scb->hscb->tag = aic_htole16(scb_data->numscbs)((__uint16_t)(scb_data->numscbs)); |
5986 | ahd_scb_free(ahd, next_scb); |
5987 | hscb++; |
5988 | hscb_busaddr += sizeof(*hscb); |
5989 | segs += ahd_sglist_size(ahd); |
5990 | sg_busaddr += ahd_sglist_size(ahd); |
5991 | sense_data += AHD_SENSE_BUFSIZE0x100; |
5992 | sense_busaddr += AHD_SENSE_BUFSIZE0x100; |
5993 | scb_data->numscbs++; |
5994 | } |
5995 | } |
5996 | |
5997 | void |
5998 | ahd_controller_info(struct ahd_softc *ahd, char *buf, size_t bufsz) |
5999 | { |
6000 | snprintf(buf, bufsz, "%s: %s, U320 %s Channel %c, %s, %d SCBs", |
6001 | ahd_name(ahd), ahd_chip_names[ahd->chip & AHD_CHIPID_MASK], |
6002 | ((ahd->features & AHD_WIDE) != 0) ? "Wide" : "Single", |
6003 | ahd->channel, ahd->bus_description, ahd->scb_data.maxhscbs); |
6004 | } |
6005 | |
6006 | static const char *channel_strings[] = { |
6007 | "Primary Low", |
6008 | "Primary High", |
6009 | "Secondary Low", |
6010 | "Secondary High" |
6011 | }; |
6012 | |
6013 | static const char *termstat_strings[] = { |
6014 | "Terminated Correctly", |
6015 | "Over Terminated", |
6016 | "Under Terminated", |
6017 | "Not Configured" |
6018 | }; |
6019 | |
6020 | /* |
6021 | * Start the board, ready for normal operation |
6022 | */ |
6023 | int |
6024 | ahd_init(struct ahd_softc *ahd) |
6025 | { |
6026 | uint8_t *next_vaddr; |
6027 | bus_addr_t next_baddr; |
6028 | size_t driver_data_size; |
6029 | int i; |
6030 | int error; |
6031 | u_int warn_user; |
6032 | uint8_t current_sensing; |
6033 | uint8_t fstat; |
6034 | |
6035 | 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", 6035);; |
6036 | |
6037 | ahd->stack_size = ahd_probe_stack_size(ahd); |
6038 | ahd->saved_stack = mallocarray(ahd->stack_size, sizeof(uint16_t), |
6039 | M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008); |
6040 | if (ahd->saved_stack == NULL((void *)0)) |
6041 | return (ENOMEM12); |
6042 | |
6043 | /* |
6044 | * Verify that the compiler hasn't over-aggressively |
6045 | * padded important structures. |
6046 | */ |
6047 | if (sizeof(struct hardware_scb) != 64) |
6048 | panic("Hardware SCB size is incorrect"); |
6049 | |
6050 | #ifdef AHD_DEBUG |
6051 | if ((ahd_debug & AHD_DEBUG_SEQUENCER) != 0) |
6052 | ahd->flags |= AHD_SEQUENCER_DEBUG; |
6053 | #endif |
6054 | |
6055 | /* |
6056 | * Default to allowing initiator operations. |
6057 | */ |
6058 | ahd->flags |= AHD_INITIATORROLE; |
6059 | |
6060 | /* |
6061 | * Only allow target mode features if this unit has them enabled. |
6062 | */ |
6063 | if ((AHD_TMODE_ENABLE0 & (0x1 << ahd->unit)) == 0) |
6064 | ahd->features &= ~AHD_TARGETMODE; |
6065 | |
6066 | /* |
6067 | * DMA tag for our command fifos and other data in system memory |
6068 | * the card's sequencer must be able to access. For initiator |
6069 | * roles, we need to allocate space for the qoutfifo. When providing |
6070 | * for the target mode role, we must additionally provide space for |
6071 | * the incoming target command fifo. |
6072 | */ |
6073 | driver_data_size = AHD_SCB_MAX512 * sizeof(*ahd->qoutfifo) |
6074 | + sizeof(struct hardware_scb); |
6075 | if ((ahd->features & AHD_TARGETMODE) != 0) |
6076 | driver_data_size += AHD_TMODE_CMDS256 * sizeof(struct target_cmd); |
6077 | if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) |
6078 | driver_data_size += PKT_OVERRUN_BUFSIZE0x200; |
6079 | if (ahd_createdmamem(ahd, driver_data_size, &ahd->shared_data_map, |
6080 | "shared data") < 0) |
6081 | return (ENOMEM12); |
6082 | |
6083 | ahd->qoutfifo = (struct ahd_completion *)ahd->shared_data_map.vaddr; |
6084 | |
6085 | ahd->init_level++; |
6086 | |
6087 | next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE512]; |
6088 | next_baddr = ahd->shared_data_map.busaddr |
6089 | + AHD_QOUT_SIZE512*sizeof(struct ahd_completion); |
6090 | if ((ahd->features & AHD_TARGETMODE) != 0) { |
6091 | ahd->targetcmds = (struct target_cmd *)next_vaddr; |
6092 | next_vaddr += AHD_TMODE_CMDS256 * sizeof(struct target_cmd); |
6093 | next_baddr += AHD_TMODE_CMDS256 * sizeof(struct target_cmd); |
6094 | } |
6095 | |
6096 | if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) { |
6097 | ahd->overrun_buf = next_vaddr; |
6098 | next_vaddr += PKT_OVERRUN_BUFSIZE0x200; |
6099 | next_baddr += PKT_OVERRUN_BUFSIZE0x200; |
6100 | } |
6101 | |
6102 | /* |
6103 | * We need one SCB to serve as the "next SCB". Since the |
6104 | * tag identifier in this SCB will never be used, there is |
6105 | * no point in using a valid HSCB tag from an SCB pulled from |
6106 | * the standard free pool. So, we allocate this "sentinel" |
6107 | * specially from the DMA safe memory chunk used for the QOUTFIFO. |
6108 | */ |
6109 | ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr; |
6110 | ahd->next_queued_hscb_map = &ahd->shared_data_map; |
6111 | ahd->next_queued_hscb->hscb_busaddr = aic_htole32(next_baddr)((__uint32_t)(next_baddr)); |
6112 | |
6113 | /* Allocate SCB data now that buffer_dmat is initialized */ |
6114 | if (ahd_init_scbdata(ahd) != 0) |
6115 | return (ENOMEM12); |
6116 | |
6117 | if ((ahd->flags & AHD_INITIATORROLE) == 0) |
6118 | ahd->flags &= ~AHD_RESET_BUS_A; |
6119 | |
6120 | /* Bring up the chip. */ |
6121 | ahd_chip_init(ahd); |
6122 | |
6123 | 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", 6123);; |
6124 | |
6125 | if ((ahd->flags & AHD_CURRENT_SENSING) == 0) |
6126 | goto init_done; |
6127 | |
6128 | /* |
6129 | * Verify termination based on current draw and |
6130 | * warn user if the bus is over/under terminated. |
6131 | */ |
6132 | error = ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL0x1, |
6133 | CURSENSE_ENB0x1); |
6134 | if (error != 0) { |
6135 | printf("%s: current sensing timeout 1\n", ahd_name(ahd)); |
6136 | goto init_done; |
6137 | } |
6138 | for (i = 20, fstat = FLX_FSTAT_BUSY0x1; |
6139 | (fstat & FLX_FSTAT_BUSY0x1) != 0 && i; i--) { |
6140 | error = ahd_read_flexport(ahd, FLXADDR_FLEXSTAT0x2, &fstat); |
6141 | if (error != 0) { |
6142 | printf("%s: current sensing timeout 2\n", |
6143 | ahd_name(ahd)); |
6144 | goto init_done; |
6145 | } |
6146 | } |
6147 | if (i == 0) { |
6148 | printf("%s: Timeout during current-sensing test\n", |
6149 | ahd_name(ahd)); |
6150 | goto init_done; |
6151 | } |
6152 | |
6153 | /* Latch Current Sensing status. */ |
6154 | error = ahd_read_flexport(ahd, FLXADDR_CURRENT_STAT0x4, ¤t_sensing); |
6155 | if (error != 0) { |
6156 | printf("%s: current sensing timeout 3\n", ahd_name(ahd)); |
6157 | goto init_done; |
6158 | } |
6159 | |
6160 | /* Disable current sensing. */ |
6161 | ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL0x1, 0); |
6162 | |
6163 | #ifdef AHD_DEBUG |
6164 | if ((ahd_debug & AHD_SHOW_TERMCTL) != 0) { |
6165 | printf("%s: current_sensing == 0x%x\n", |
6166 | ahd_name(ahd), current_sensing); |
6167 | } |
6168 | #endif |
6169 | warn_user = 0; |
6170 | for (i = 0; i < 4; i++, current_sensing >>= FLX_CSTAT_SHIFT2) { |
6171 | u_int term_stat; |
6172 | |
6173 | term_stat = (current_sensing & FLX_CSTAT_MASK0x03); |
6174 | switch (term_stat) { |
6175 | case FLX_CSTAT_OVER0x1: |
6176 | case FLX_CSTAT_UNDER0x2: |
6177 | warn_user++; |
6178 | case FLX_CSTAT_INVALID0x3: |
6179 | case FLX_CSTAT_OKAY0x0: |
6180 | if (warn_user == 0 && bootverbose0 == 0) |
6181 | break; |
6182 | printf("%s: %s Channel %s\n", ahd_name(ahd), |
6183 | channel_strings[i], termstat_strings[term_stat]); |
6184 | break; |
6185 | } |
6186 | } |
6187 | if (warn_user) { |
6188 | printf("%s: WARNING. Termination is not configured correctly.\n" |
6189 | "%s: WARNING. SCSI bus operations may FAIL.\n", |
6190 | ahd_name(ahd), ahd_name(ahd)); |
6191 | } |
6192 | init_done: |
6193 | ahd_reset_current_bus(ahd); |
6194 | ahd_restart(ahd); |
6195 | aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_MS250, |
6196 | ahd_stat_timer, ahd); |
6197 | return (0); |
6198 | } |
6199 | |
6200 | /* |
6201 | * (Re)initialize chip state after a chip reset. |
6202 | */ |
6203 | void |
6204 | ahd_chip_init(struct ahd_softc *ahd) |
6205 | { |
6206 | uint32_t busaddr; |
6207 | u_int sxfrctl1; |
6208 | u_int scsiseq_template; |
6209 | u_int wait; |
6210 | u_int i; |
6211 | u_int target; |
6212 | |
6213 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
6214 | /* |
6215 | * Take the LED out of diagnostic mode |
6216 | */ |
6217 | ahd_outb(ahd, SBLKCTL, ahd_inb(ahd, SBLKCTL) & ~(DIAGLEDEN|DIAGLEDON))(((ahd)->tags[(0x4a) >> 8])->write_1(((ahd)->bshs [(0x4a) >> 8]), ((0x4a) & 0xFF), ((((ahd)->tags[ (0x4a) >> 8])->read_1(((ahd)->bshs[(0x4a) >> 8]), ((0x4a) & 0xFF))) & ~(0x80|0x40)))); |
6218 | |
6219 | /* |
6220 | * Return HS_MAILBOX to its default value. |
6221 | */ |
6222 | ahd->hs_mailbox = 0; |
6223 | ahd_outb(ahd, HS_MAILBOX, 0)(((ahd)->tags[(0x0b) >> 8])->write_1(((ahd)->bshs [(0x0b) >> 8]), ((0x0b) & 0xFF), (0))); |
6224 | |
6225 | /* Set the SCSI Id, SXFRCTL0, SXFRCTL1, and SIMODE1. */ |
6226 | ahd_outb(ahd, IOWNID, ahd->our_id)(((ahd)->tags[(0x67) >> 8])->write_1(((ahd)->bshs [(0x67) >> 8]), ((0x67) & 0xFF), (ahd->our_id))); |
6227 | ahd_outb(ahd, TOWNID, ahd->our_id)(((ahd)->tags[(0x69) >> 8])->write_1(((ahd)->bshs [(0x69) >> 8]), ((0x69) & 0xFF), (ahd->our_id))); |
6228 | sxfrctl1 = (ahd->flags & AHD_TERM_ENB_A) != 0 ? STPWEN0x01 : 0; |
6229 | sxfrctl1 |= (ahd->flags & AHD_SPCHK_ENB_A) != 0 ? ENSPCHK0x20 : 0; |
6230 | if ((ahd->bugs & AHD_LONG_SETIMO_BUG) |
6231 | && (ahd->seltime != STIMESEL_MIN0x18)) { |
6232 | /* |
6233 | * The selection timer duration is twice as long |
6234 | * as it should be. Halve it by adding "1" to |
6235 | * the user specified setting. |
6236 | */ |
6237 | sxfrctl1 |= ahd->seltime + STIMESEL_BUG_ADJ0x08; |
6238 | } else { |
6239 | sxfrctl1 |= ahd->seltime; |
6240 | } |
6241 | |
6242 | ahd_outb(ahd, SXFRCTL0, DFON)(((ahd)->tags[(0x3c) >> 8])->write_1(((ahd)->bshs [(0x3c) >> 8]), ((0x3c) & 0xFF), (0x80))); |
6243 | ahd_outb(ahd, SXFRCTL1, sxfrctl1|ahd->seltime|ENSTIMER|ACTNEGEN)(((ahd)->tags[(0x3d) >> 8])->write_1(((ahd)->bshs [(0x3d) >> 8]), ((0x3d) & 0xFF), (sxfrctl1|ahd-> seltime|0x04|0x02))); |
6244 | ahd_outb(ahd, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR)(((ahd)->tags[(0x57) >> 8])->write_1(((ahd)->bshs [(0x57) >> 8]), ((0x57) & 0xFF), (0x80|0x20|0x04))); |
6245 | |
6246 | /* |
6247 | * Now that termination is set, wait for up |
6248 | * to 500ms for our transceivers to settle. If |
6249 | * the adapter does not have a cable attached, |
6250 | * the transceivers may never settle, so don't |
6251 | * complain if we fail here. |
6252 | */ |
6253 | for (wait = 10000; |
6254 | (ahd_inb(ahd, SBLKCTL)(((ahd)->tags[(0x4a) >> 8])->read_1(((ahd)->bshs [(0x4a) >> 8]), ((0x4a) & 0xFF))) & (ENAB400x08|ENAB200x04)) == 0 && wait; |
6255 | wait--) |
6256 | aic_delay(100)(*delay_func)(100); |
6257 | |
6258 | /* Clear any false bus resets due to the transceivers settling */ |
6259 | ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI)(((ahd)->tags[(0x4c) >> 8])->write_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF), (0x20))); |
6260 | ahd_outb(ahd, CLRINT, CLRSCSIINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x08))); |
6261 | |
6262 | /* Initialize mode specific S/G state. */ |
6263 | for (i = 0; i < 2; i++) { |
6264 | ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i); |
6265 | ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR)(((ahd)->tags[(0xf8 + 1) >> 8])->write_1(((ahd)-> bshs[(0xf8 + 1) >> 8]), ((0xf8 + 1) & 0xFF), (0x80) )); |
6266 | ahd_outb(ahd, SG_STATE, 0)(((ahd)->tags[(0xa6) >> 8])->write_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF), (0))); |
6267 | ahd_outb(ahd, CLRSEQINTSRC, 0xFF)(((ahd)->tags[(0x5b) >> 8])->write_1(((ahd)->bshs [(0x5b) >> 8]), ((0x5b) & 0xFF), (0xFF))); |
6268 | ahd_outb(ahd, SEQIMODE,(((ahd)->tags[(0x5c) >> 8])->write_1(((ahd)->bshs [(0x5c) >> 8]), ((0x5c) & 0xFF), (0x20|0x10|0x08 |0x04 |0x02|0x01))) |
6269 | ENSAVEPTRS|ENCFG4DATA|ENCFG4ISTAT(((ahd)->tags[(0x5c) >> 8])->write_1(((ahd)->bshs [(0x5c) >> 8]), ((0x5c) & 0xFF), (0x20|0x10|0x08 |0x04 |0x02|0x01))) |
6270 | |ENCFG4TSTAT|ENCFG4ICMD|ENCFG4TCMD)(((ahd)->tags[(0x5c) >> 8])->write_1(((ahd)->bshs [(0x5c) >> 8]), ((0x5c) & 0xFF), (0x20|0x10|0x08 |0x04 |0x02|0x01))); |
6271 | } |
6272 | |
6273 | ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); |
6274 | ahd_outb(ahd, DSCOMMAND0, ahd_inb(ahd, DSCOMMAND0)|MPARCKEN|CACHETHEN)(((ahd)->tags[(0x19) >> 8])->write_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF), ((((ahd)->tags[ (0x19) >> 8])->read_1(((ahd)->bshs[(0x19) >> 8]), ((0x19) & 0xFF)))|0x20|0x80))); |
6275 | ahd_outb(ahd, DFF_THRSH, RD_DFTHRSH_75|WR_DFTHRSH_75)(((ahd)->tags[(0x88) >> 8])->write_1(((ahd)->bshs [(0x88) >> 8]), ((0x88) & 0xFF), (0x04|0x40))); |
6276 | ahd_outb(ahd, SIMODE0, ENIOERR|ENOVERRUN)(((ahd)->tags[(0x4b) >> 8])->write_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF), (0x08|0x04))); |
6277 | ahd_outb(ahd, SIMODE3, ENNTRAMPERR|ENOSRAMPERR)(((ahd)->tags[(0x53) >> 8])->write_1(((ahd)->bshs [(0x53) >> 8]), ((0x53) & 0xFF), (0x02|0x01))); |
6278 | if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) { |
6279 | ahd_outb(ahd, OPTIONMODE, AUTOACKEN|AUTO_MSGOUT_DE)(((ahd)->tags[(0x4a) >> 8])->write_1(((ahd)->bshs [(0x4a) >> 8]), ((0x4a) & 0xFF), (0x40|0x02))); |
6280 | } else { |
6281 | ahd_outb(ahd, OPTIONMODE, AUTOACKEN|BUSFREEREV|AUTO_MSGOUT_DE)(((ahd)->tags[(0x4a) >> 8])->write_1(((ahd)->bshs [(0x4a) >> 8]), ((0x4a) & 0xFF), (0x40|0x10|0x02))); |
6282 | } |
6283 | ahd_outb(ahd, SCSCHKN, CURRFIFODEF|WIDERESEN|SHVALIDSTDIS)(((ahd)->tags[(0x66) >> 8])->write_1(((ahd)->bshs [(0x66) >> 8]), ((0x66) & 0xFF), (0x20|0x10|0x02))); |
6284 | if ((ahd->chip & AHD_BUS_MASK) == AHD_PCIX) |
6285 | /* |
6286 | * Do not issue a target abort when a split completion |
6287 | * error occurs. Let our PCIX interrupt handler deal |
6288 | * with it instead. H2A4 Razor #625 |
6289 | */ |
6290 | ahd_outb(ahd, PCIXCTL, ahd_inb(ahd, PCIXCTL) | SPLTSTADIS)(((ahd)->tags[(0x93) >> 8])->write_1(((ahd)->bshs [(0x93) >> 8]), ((0x93) & 0xFF), ((((ahd)->tags[ (0x93) >> 8])->read_1(((ahd)->bshs[(0x93) >> 8]), ((0x93) & 0xFF))) | 0x08))); |
6291 | |
6292 | if ((ahd->bugs & AHD_LQOOVERRUN_BUG) != 0) |
6293 | ahd_outb(ahd, LQOSCSCTL, LQONOCHKOVER)(((ahd)->tags[(0x5a) >> 8])->write_1(((ahd)->bshs [(0x5a) >> 8]), ((0x5a) & 0xFF), (0x01))); |
6294 | |
6295 | /* |
6296 | * Tweak IOCELL settings. |
6297 | */ |
6298 | if ((ahd->flags & AHD_HP_BOARD) != 0) { |
6299 | for (i = 0; i < NUMDSPS0x14; i++) { |
6300 | ahd_outb(ahd, DSPSELECT, i)(((ahd)->tags[(0xc4) >> 8])->write_1(((ahd)->bshs [(0xc4) >> 8]), ((0xc4) & 0xFF), (i))); |
6301 | ahd_outb(ahd, WRTBIASCTL, WRTBIASCTL_HP_DEFAULT)(((ahd)->tags[(0xc5) >> 8])->write_1(((ahd)->bshs [(0xc5) >> 8]), ((0xc5) & 0xFF), (0x00))); |
6302 | } |
6303 | #ifdef AHD_DEBUG |
6304 | if ((ahd_debug & AHD_SHOW_MISC) != 0) |
6305 | printf("%s: WRTBIASCTL now 0x%x\n", ahd_name(ahd), |
6306 | WRTBIASCTL_HP_DEFAULT0x00); |
6307 | #endif |
6308 | } |
6309 | ahd_setup_iocell_workaround(ahd); |
6310 | |
6311 | /* |
6312 | * Enable LQI Manager interrupts. |
6313 | */ |
6314 | ahd_outb(ahd, LQIMODE1, ENLQIPHASE_LQ|ENLQIPHASE_NLQ|ENLIQABORT(((ahd)->tags[(0x51) >> 8])->write_1(((ahd)->bshs [(0x51) >> 8]), ((0x51) & 0xFF), (0x80|0x40|0x20 | 0x10 |0x08|0x04 | 0x02|0x01))) |
6315 | | ENLQICRCI_LQ|ENLQICRCI_NLQ|ENLQIBADLQI(((ahd)->tags[(0x51) >> 8])->write_1(((ahd)->bshs [(0x51) >> 8]), ((0x51) & 0xFF), (0x80|0x40|0x20 | 0x10 |0x08|0x04 | 0x02|0x01))) |
6316 | | ENLQIOVERI_LQ|ENLQIOVERI_NLQ)(((ahd)->tags[(0x51) >> 8])->write_1(((ahd)->bshs [(0x51) >> 8]), ((0x51) & 0xFF), (0x80|0x40|0x20 | 0x10 |0x08|0x04 | 0x02|0x01))); |
6317 | ahd_outb(ahd, LQOMODE0, ENLQOATNLQ|ENLQOATNPKT|ENLQOTCRC)(((ahd)->tags[(0x54) >> 8])->write_1(((ahd)->bshs [(0x54) >> 8]), ((0x54) & 0xFF), (0x04|0x02|0x01))); |
6318 | /* |
6319 | * We choose to have the sequencer catch LQOPHCHGINPKT errors |
6320 | * manually for the command phase at the start of a packetized |
6321 | * selection case. ENLQOBUSFREE should be made redundant by |
6322 | * the BUSFREE interrupt, but it seems that some LQOBUSFREE |
6323 | * events fail to assert the BUSFREE interrupt so we must |
6324 | * also enable LQOBUSFREE interrupts. |
6325 | */ |
6326 | ahd_outb(ahd, LQOMODE1, ENLQOBUSFREE)(((ahd)->tags[(0x55) >> 8])->write_1(((ahd)->bshs [(0x55) >> 8]), ((0x55) & 0xFF), (0x02))); |
6327 | |
6328 | /* |
6329 | * Setup sequencer interrupt handlers. |
6330 | */ |
6331 | ahd_outw(ahd, INTVEC1_ADDR0xf4, ahd_resolve_seqaddr(ahd, LABEL_seq_isr0x28f)); |
6332 | ahd_outw(ahd, INTVEC2_ADDR0xf6, ahd_resolve_seqaddr(ahd, LABEL_timer_isr0x28b)); |
6333 | |
6334 | /* |
6335 | * Setup SCB Offset registers. |
6336 | */ |
6337 | if ((ahd->bugs & AHD_PKT_LUN_BUG) != 0) { |
6338 | ahd_outb(ahd, LUNPTR, offsetof(struct hardware_scb,(((ahd)->tags[(0x22) >> 8])->write_1(((ahd)->bshs [(0x22) >> 8]), ((0x22) & 0xFF), (__builtin_offsetof (struct hardware_scb, pkt_long_lun)))) |
6339 | pkt_long_lun))(((ahd)->tags[(0x22) >> 8])->write_1(((ahd)->bshs [(0x22) >> 8]), ((0x22) & 0xFF), (__builtin_offsetof (struct hardware_scb, pkt_long_lun)))); |
6340 | } else { |
6341 | ahd_outb(ahd, LUNPTR, offsetof(struct hardware_scb, lun))(((ahd)->tags[(0x22) >> 8])->write_1(((ahd)->bshs [(0x22) >> 8]), ((0x22) & 0xFF), (__builtin_offsetof (struct hardware_scb, lun)))); |
6342 | } |
6343 | ahd_outb(ahd, CMDLENPTR, offsetof(struct hardware_scb, cdb_len))(((ahd)->tags[(0x25) >> 8])->write_1(((ahd)->bshs [(0x25) >> 8]), ((0x25) & 0xFF), (__builtin_offsetof (struct hardware_scb, cdb_len)))); |
6344 | ahd_outb(ahd, ATTRPTR, offsetof(struct hardware_scb, task_attribute))(((ahd)->tags[(0x26) >> 8])->write_1(((ahd)->bshs [(0x26) >> 8]), ((0x26) & 0xFF), (__builtin_offsetof (struct hardware_scb, task_attribute)))); |
6345 | ahd_outb(ahd, FLAGPTR, offsetof(struct hardware_scb, task_management))(((ahd)->tags[(0x27) >> 8])->write_1(((ahd)->bshs [(0x27) >> 8]), ((0x27) & 0xFF), (__builtin_offsetof (struct hardware_scb, task_management)))); |
6346 | ahd_outb(ahd, CMDPTR, offsetof(struct hardware_scb,(((ahd)->tags[(0x28) >> 8])->write_1(((ahd)->bshs [(0x28) >> 8]), ((0x28) & 0xFF), (__builtin_offsetof (struct hardware_scb, shared_data.idata.cdb)))) |
6347 | shared_data.idata.cdb))(((ahd)->tags[(0x28) >> 8])->write_1(((ahd)->bshs [(0x28) >> 8]), ((0x28) & 0xFF), (__builtin_offsetof (struct hardware_scb, shared_data.idata.cdb)))); |
6348 | ahd_outb(ahd, QNEXTPTR,(((ahd)->tags[(0x29) >> 8])->write_1(((ahd)->bshs [(0x29) >> 8]), ((0x29) & 0xFF), (__builtin_offsetof (struct hardware_scb, next_hscb_busaddr)))) |
6349 | offsetof(struct hardware_scb, next_hscb_busaddr))(((ahd)->tags[(0x29) >> 8])->write_1(((ahd)->bshs [(0x29) >> 8]), ((0x29) & 0xFF), (__builtin_offsetof (struct hardware_scb, next_hscb_busaddr)))); |
6350 | ahd_outb(ahd, ABRTBITPTR, MK_MESSAGE_BIT_OFFSET)(((ahd)->tags[(0x2c) >> 8])->write_1(((ahd)->bshs [(0x2c) >> 8]), ((0x2c) & 0xFF), (0x04))); |
6351 | ahd_outb(ahd, ABRTBYTEPTR, offsetof(struct hardware_scb, control))(((ahd)->tags[(0x2b) >> 8])->write_1(((ahd)->bshs [(0x2b) >> 8]), ((0x2b) & 0xFF), (__builtin_offsetof (struct hardware_scb, control)))); |
6352 | if ((ahd->bugs & AHD_PKT_LUN_BUG) != 0) { |
6353 | ahd_outb(ahd, LUNLEN,(((ahd)->tags[(0x30) >> 8])->write_1(((ahd)->bshs [(0x30) >> 8]), ((0x30) & 0xFF), (sizeof(ahd->next_queued_hscb ->pkt_long_lun) - 1))) |
6354 | sizeof(ahd->next_queued_hscb->pkt_long_lun) - 1)(((ahd)->tags[(0x30) >> 8])->write_1(((ahd)->bshs [(0x30) >> 8]), ((0x30) & 0xFF), (sizeof(ahd->next_queued_hscb ->pkt_long_lun) - 1))); |
6355 | } else { |
6356 | ahd_outb(ahd, LUNLEN, LUNLEN_SINGLE_LEVEL_LUN)(((ahd)->tags[(0x30) >> 8])->write_1(((ahd)->bshs [(0x30) >> 8]), ((0x30) & 0xFF), (0x0f))); |
6357 | } |
6358 | ahd_outb(ahd, CDBLIMIT, SCB_CDB_LEN_PTR - 1)(((ahd)->tags[(0x31) >> 8])->write_1(((ahd)->bshs [(0x31) >> 8]), ((0x31) & 0xFF), (0x80 - 1))); |
6359 | ahd_outb(ahd, MAXCMD, 0xFF)(((ahd)->tags[(0x32) >> 8])->write_1(((ahd)->bshs [(0x32) >> 8]), ((0x32) & 0xFF), (0xFF))); |
6360 | ahd_outb(ahd, SCBAUTOPTR,(((ahd)->tags[(0xab) >> 8])->write_1(((ahd)->bshs [(0xab) >> 8]), ((0xab) & 0xFF), (0x80 | __builtin_offsetof (struct hardware_scb, tag)))) |
6361 | AUSCBPTR_EN | offsetof(struct hardware_scb, tag))(((ahd)->tags[(0xab) >> 8])->write_1(((ahd)->bshs [(0xab) >> 8]), ((0xab) & 0xFF), (0x80 | __builtin_offsetof (struct hardware_scb, tag)))); |
6362 | |
6363 | /* We haven't been enabled for target mode yet. */ |
6364 | ahd_outb(ahd, MULTARGID, 0)(((ahd)->tags[(0x40) >> 8])->write_1(((ahd)->bshs [(0x40) >> 8]), ((0x40) & 0xFF), (0))); |
6365 | ahd_outb(ahd, MULTARGID + 1, 0)(((ahd)->tags[(0x40 + 1) >> 8])->write_1(((ahd)-> bshs[(0x40 + 1) >> 8]), ((0x40 + 1) & 0xFF), (0))); |
6366 | |
6367 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
6368 | /* Initialize the negotiation table. */ |
6369 | if ((ahd->features & AHD_NEW_IOCELL_OPTS) == 0) { |
6370 | /* |
6371 | * Clear the spare bytes in the neg table to avoid |
6372 | * spurious parity errors. |
6373 | */ |
6374 | for (target = 0; target < AHD_NUM_TARGETS16; target++) { |
6375 | ahd_outb(ahd, NEGOADDR, target)(((ahd)->tags[(0x60) >> 8])->write_1(((ahd)->bshs [(0x60) >> 8]), ((0x60) & 0xFF), (target))); |
6376 | ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PER_DEV0)(((ahd)->tags[(0x65) >> 8])->write_1(((ahd)->bshs [(0x65) >> 8]), ((0x65) & 0xFF), (0x04))); |
6377 | for (i = 0; i < AHD_NUM_PER_DEV_ANNEXCOLS0x04; i++) |
6378 | ahd_outb(ahd, ANNEXDAT, 0)(((ahd)->tags[(0x66) >> 8])->write_1(((ahd)->bshs [(0x66) >> 8]), ((0x66) & 0xFF), (0))); |
6379 | } |
6380 | } |
6381 | for (target = 0; target < AHD_NUM_TARGETS16; target++) { |
6382 | struct ahd_devinfo devinfo; |
6383 | struct ahd_initiator_tinfo *tinfo; |
6384 | struct ahd_tmode_tstate *tstate; |
6385 | |
6386 | tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, |
6387 | target, &tstate); |
6388 | ahd_compile_devinfo(&devinfo, ahd->our_id, |
6389 | target, CAM_LUN_WILDCARD-1, |
6390 | 'A', ROLE_INITIATOR); |
6391 | ahd_update_neg_table(ahd, &devinfo, &tinfo->curr); |
6392 | } |
6393 | |
6394 | ahd_outb(ahd, CLRSINT3, NTRAMPERR|OSRAMPERR)(((ahd)->tags[(0x53) >> 8])->write_1(((ahd)->bshs [(0x53) >> 8]), ((0x53) & 0xFF), (0x02|0x01))); |
6395 | ahd_outb(ahd, CLRINT, CLRSCSIINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x08))); |
6396 | |
6397 | #if NEEDS_MORE_TESTING |
6398 | /* |
6399 | * Always enable abort on incoming L_Qs if this feature is |
6400 | * supported. We use this to catch invalid SCB references. |
6401 | */ |
6402 | if ((ahd->bugs & AHD_ABORT_LQI_BUG) == 0) |
6403 | ahd_outb(ahd, LQCTL1, ABORTPENDING)(((ahd)->tags[(0x38) >> 8])->write_1(((ahd)->bshs [(0x38) >> 8]), ((0x38) & 0xFF), (0x01))); |
6404 | else |
6405 | #endif |
6406 | ahd_outb(ahd, LQCTL1, 0)(((ahd)->tags[(0x38) >> 8])->write_1(((ahd)->bshs [(0x38) >> 8]), ((0x38) & 0xFF), (0))); |
6407 | |
6408 | /* All of our queues are empty */ |
6409 | ahd->qoutfifonext = 0; |
6410 | ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID0x80; |
6411 | ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID)(((ahd)->tags[(0x13d) >> 8])->write_1(((ahd)-> bshs[(0x13d) >> 8]), ((0x13d) & 0xFF), (0x80))); |
6412 | for (i = 0; i < AHD_QOUT_SIZE512; i++) |
6413 | ahd->qoutfifo[i].valid_tag = 0; |
6414 | ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD0x01); |
6415 | |
6416 | ahd->qinfifonext = 0; |
6417 | for (i = 0; i < AHD_QIN_SIZE512; i++) |
6418 | ahd->qinfifo[i] = SCB_LIST_NULL0xFF00; |
6419 | |
6420 | if ((ahd->features & AHD_TARGETMODE) != 0) { |
6421 | /* All target command blocks start out invalid. */ |
6422 | for (i = 0; i < AHD_TMODE_CMDS256; i++) |
6423 | ahd->targetcmds[i].cmd_valid = 0; |
6424 | ahd_sync_tqinfifo(ahd, BUS_DMASYNC_PREREAD0x01); |
6425 | ahd->tqinfifonext = 1; |
6426 | ahd_outb(ahd, KERNEL_TQINPOS, ahd->tqinfifonext - 1)(((ahd)->tags[(0x13e) >> 8])->write_1(((ahd)-> bshs[(0x13e) >> 8]), ((0x13e) & 0xFF), (ahd->tqinfifonext - 1))); |
6427 | ahd_outb(ahd, TQINPOS, ahd->tqinfifonext)(((ahd)->tags[(0x13f) >> 8])->write_1(((ahd)-> bshs[(0x13f) >> 8]), ((0x13f) & 0xFF), (ahd->tqinfifonext ))); |
6428 | } |
6429 | |
6430 | /* Initialize Scratch Ram. */ |
6431 | ahd_outb(ahd, SEQ_FLAGS, 0)(((ahd)->tags[(0x139) >> 8])->write_1(((ahd)-> bshs[(0x139) >> 8]), ((0x139) & 0xFF), (0))); |
6432 | ahd_outb(ahd, SEQ_FLAGS2, 0)(((ahd)->tags[(0x14d) >> 8])->write_1(((ahd)-> bshs[(0x14d) >> 8]), ((0x14d) & 0xFF), (0))); |
6433 | |
6434 | /* We don't have any waiting selections */ |
6435 | ahd_outw(ahd, WAITING_TID_HEAD0x120, SCB_LIST_NULL0xFF00); |
6436 | ahd_outw(ahd, WAITING_TID_TAIL0x122, SCB_LIST_NULL0xFF00); |
6437 | ahd_outw(ahd, MK_MESSAGE_SCB0x160, SCB_LIST_NULL0xFF00); |
6438 | ahd_outw(ahd, MK_MESSAGE_SCSIID0x162, 0xFF); |
6439 | for (i = 0; i < AHD_NUM_TARGETS16; i++) |
6440 | ahd_outw(ahd, WAITING_SCB_TAILS0x100 + (2 * i), SCB_LIST_NULL0xFF00); |
6441 | |
6442 | /* |
6443 | * Nobody is waiting to be DMAed into the QOUTFIFO. |
6444 | */ |
6445 | ahd_outw(ahd, COMPLETE_SCB_HEAD0x128, SCB_LIST_NULL0xFF00); |
6446 | ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD0x12a, SCB_LIST_NULL0xFF00); |
6447 | ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD0x12c, SCB_LIST_NULL0xFF00); |
6448 | ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL0x12e, SCB_LIST_NULL0xFF00); |
6449 | ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD0x130, SCB_LIST_NULL0xFF00); |
6450 | |
6451 | /* |
6452 | * The Freeze Count is 0. |
6453 | */ |
6454 | ahd->qfreeze_cnt = 0; |
6455 | ahd_outw(ahd, QFREEZE_COUNT0x132, 0); |
6456 | ahd_outw(ahd, KERNEL_QFREEZE_COUNT0x134, 0); |
6457 | |
6458 | /* |
6459 | * Tell the sequencer where it can find our arrays in memory. |
6460 | */ |
6461 | busaddr = ahd->shared_data_map.busaddr; |
6462 | ahd_outl(ahd, SHARED_DATA_ADDR0x140, busaddr); |
6463 | ahd_outl(ahd, QOUTFIFO_NEXT_ADDR0x144, busaddr); |
6464 | |
6465 | /* |
6466 | * Setup the allowed SCSI Sequences based on operational mode. |
6467 | * If we are a target, we'll enable select in operations once |
6468 | * we've had a lun enabled. |
6469 | */ |
6470 | scsiseq_template = ENAUTOATNP0x02; |
6471 | if ((ahd->flags & AHD_INITIATORROLE) != 0) |
6472 | scsiseq_template |= ENRSELI0x10; |
6473 | ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq_template)(((ahd)->tags[(0x14b) >> 8])->write_1(((ahd)-> bshs[(0x14b) >> 8]), ((0x14b) & 0xFF), (scsiseq_template ))); |
6474 | |
6475 | /* There are no busy SCBs yet. */ |
6476 | for (target = 0; target < AHD_NUM_TARGETS16; target++) { |
6477 | int lun; |
6478 | |
6479 | for (lun = 0; lun < AHD_NUM_LUNS_NONPKT64; lun++) |
6480 | ahd_unbusy_tcl(ahd, BUILD_TCL_RAW(target, 'A', lun)((lun) | ((target) << 8))); |
6481 | } |
6482 | |
6483 | /* |
6484 | * Initialize the group code to command length table. |
6485 | * Vendor Unique codes are set to 0 so we only capture |
6486 | * the first byte of the cdb. These can be overridden |
6487 | * when target mode is enabled. |
6488 | */ |
6489 | ahd_outb(ahd, CMDSIZE_TABLE, 5)(((ahd)->tags[(0x158) >> 8])->write_1(((ahd)-> bshs[(0x158) >> 8]), ((0x158) & 0xFF), (5))); |
6490 | ahd_outb(ahd, CMDSIZE_TABLE + 1, 9)(((ahd)->tags[(0x158 + 1) >> 8])->write_1(((ahd)-> bshs[(0x158 + 1) >> 8]), ((0x158 + 1) & 0xFF), (9)) ); |
6491 | ahd_outb(ahd, CMDSIZE_TABLE + 2, 9)(((ahd)->tags[(0x158 + 2) >> 8])->write_1(((ahd)-> bshs[(0x158 + 2) >> 8]), ((0x158 + 2) & 0xFF), (9)) ); |
6492 | ahd_outb(ahd, CMDSIZE_TABLE + 3, 0)(((ahd)->tags[(0x158 + 3) >> 8])->write_1(((ahd)-> bshs[(0x158 + 3) >> 8]), ((0x158 + 3) & 0xFF), (0)) ); |
6493 | ahd_outb(ahd, CMDSIZE_TABLE + 4, 15)(((ahd)->tags[(0x158 + 4) >> 8])->write_1(((ahd)-> bshs[(0x158 + 4) >> 8]), ((0x158 + 4) & 0xFF), (15) )); |
6494 | ahd_outb(ahd, CMDSIZE_TABLE + 5, 11)(((ahd)->tags[(0x158 + 5) >> 8])->write_1(((ahd)-> bshs[(0x158 + 5) >> 8]), ((0x158 + 5) & 0xFF), (11) )); |
6495 | ahd_outb(ahd, CMDSIZE_TABLE + 6, 0)(((ahd)->tags[(0x158 + 6) >> 8])->write_1(((ahd)-> bshs[(0x158 + 6) >> 8]), ((0x158 + 6) & 0xFF), (0)) ); |
6496 | ahd_outb(ahd, CMDSIZE_TABLE + 7, 0)(((ahd)->tags[(0x158 + 7) >> 8])->write_1(((ahd)-> bshs[(0x158 + 7) >> 8]), ((0x158 + 7) & 0xFF), (0)) ); |
6497 | |
6498 | /* Tell the sequencer of our initial queue positions */ |
6499 | ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); |
6500 | ahd_outb(ahd, QOFF_CTLSTA, SCB_QSIZE_512)(((ahd)->tags[(0x16) >> 8])->write_1(((ahd)->bshs [(0x16) >> 8]), ((0x16) & 0xFF), (0x07))); |
6501 | ahd->qinfifonext = 0; |
6502 | ahd_set_hnscb_qoff(ahd, ahd->qinfifonext); |
6503 | ahd_set_hescb_qoff(ahd, 0); |
6504 | ahd_set_snscb_qoff(ahd, 0); |
6505 | ahd_set_sescb_qoff(ahd, 0); |
6506 | ahd_set_sdscb_qoff(ahd, 0); |
6507 | |
6508 | /* |
6509 | * Tell the sequencer which SCB will be the next one it receives. |
6510 | */ |
6511 | busaddr = aic_le32toh(ahd->next_queued_hscb->hscb_busaddr)((__uint32_t)(ahd->next_queued_hscb->hscb_busaddr)); |
6512 | ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR0x124, busaddr); |
6513 | |
6514 | /* |
6515 | * Default to coalescing disabled. |
6516 | */ |
6517 | ahd_outw(ahd, INT_COALESCING_CMDCOUNT0x156, 0); |
6518 | ahd_outw(ahd, CMDS_PENDING0x154, 0); |
6519 | ahd_update_coalescing_values(ahd, ahd->int_coalescing_timer, |
6520 | ahd->int_coalescing_maxcmds, |
6521 | ahd->int_coalescing_mincmds); |
6522 | ahd_enable_coalescing(ahd, FALSE0); |
6523 | |
6524 | ahd_loadseq(ahd); |
6525 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
6526 | } |
6527 | |
6528 | /* |
6529 | * Setup default device and controller settings. |
6530 | * This should only be called if our probe has |
6531 | * determined that no configuration data is available. |
6532 | */ |
6533 | int |
6534 | ahd_default_config(struct ahd_softc *ahd) |
6535 | { |
6536 | int targ; |
6537 | |
6538 | ahd->our_id = 7; |
6539 | |
6540 | /* |
6541 | * Allocate a tstate to house information for our |
6542 | * initiator presence on the bus as well as the user |
6543 | * data for any target mode initiator. |
6544 | */ |
6545 | if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL((void *)0)) { |
6546 | printf("%s: unable to allocate ahd_tmode_tstate. " |
6547 | "Failing attach\n", ahd_name(ahd)); |
6548 | return (ENOMEM12); |
6549 | } |
6550 | |
6551 | for (targ = 0; targ < AHD_NUM_TARGETS16; targ++) { |
6552 | struct ahd_devinfo devinfo; |
6553 | struct ahd_initiator_tinfo *tinfo; |
6554 | struct ahd_tmode_tstate *tstate; |
6555 | uint16_t target_mask; |
6556 | |
6557 | tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, |
6558 | targ, &tstate); |
6559 | /* |
6560 | * We support SPC2 and SPI4. |
6561 | */ |
6562 | tinfo->user.protocol_version = 4; |
6563 | tinfo->user.transport_version = 4; |
6564 | |
6565 | target_mask = 0x01 << targ; |
6566 | ahd->user_discenable |= target_mask; |
6567 | tstate->discenable |= target_mask; |
6568 | ahd->user_tagenable |= target_mask; |
6569 | #ifdef AHD_FORCE_160 |
6570 | tinfo->user.period = AHD_SYNCRATE_DT0x9; |
6571 | #else |
6572 | tinfo->user.period = AHD_SYNCRATE_1600x8; |
6573 | #endif |
6574 | tinfo->user.offset = MAX_OFFSET0xfe; |
6575 | tinfo->user.ppr_options = MSG_EXT_PPR_RD_STRM0x20 |
6576 | | MSG_EXT_PPR_WR_FLOW0x10 |
6577 | | MSG_EXT_PPR_HOLD_MCS0x08 |
6578 | | MSG_EXT_PPR_IU_REQ0x01 |
6579 | | MSG_EXT_PPR_QAS_REQ0x04 |
6580 | | MSG_EXT_PPR_DT_REQ0x02; |
6581 | if ((ahd->features & AHD_RTI) != 0) |
6582 | tinfo->user.ppr_options |= MSG_EXT_PPR_RTI0x40; |
6583 | |
6584 | tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT0x01; |
6585 | |
6586 | /* |
6587 | * Start out Async/Narrow/Untagged and with |
6588 | * conservative protocol support. |
6589 | */ |
6590 | tinfo->goal.protocol_version = 2; |
6591 | tinfo->goal.transport_version = 2; |
6592 | tinfo->curr.protocol_version = 2; |
6593 | tinfo->curr.transport_version = 2; |
6594 | ahd_compile_devinfo(&devinfo, ahd->our_id, |
6595 | targ, CAM_LUN_WILDCARD-1, |
6596 | 'A', ROLE_INITIATOR); |
6597 | tstate->tagenable &= ~target_mask; |
6598 | ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT0x00, |
6599 | AHD_TRANS_CUR0x01|AHD_TRANS_GOAL0x04, /*paused*/TRUE1); |
6600 | ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0, |
6601 | /*ppr_options*/0, AHD_TRANS_CUR0x01|AHD_TRANS_GOAL0x04, |
6602 | /*paused*/TRUE1); |
6603 | } |
6604 | return (0); |
6605 | } |
6606 | |
6607 | /* |
6608 | * Parse device configuration information. |
6609 | */ |
6610 | int |
6611 | ahd_parse_cfgdata(struct ahd_softc *ahd, struct seeprom_config *sc) |
6612 | { |
6613 | int targ; |
6614 | int max_targ; |
6615 | |
6616 | max_targ = sc->max_targets & CFMAXTARG0x00ff; |
6617 | ahd->our_id = sc->brtime_id & CFSCSIID0x000f; |
6618 | |
6619 | /* |
6620 | * Allocate a tstate to house information for our |
6621 | * initiator presence on the bus as well as the user |
6622 | * data for any target mode initiator. |
6623 | */ |
6624 | if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL((void *)0)) { |
6625 | printf("%s: unable to allocate ahd_tmode_tstate. " |
6626 | "Failing attach\n", ahd_name(ahd)); |
6627 | return (ENOMEM12); |
6628 | } |
6629 | |
6630 | for (targ = 0; targ < max_targ; targ++) { |
6631 | struct ahd_devinfo devinfo; |
6632 | struct ahd_initiator_tinfo *tinfo; |
6633 | struct ahd_transinfo *user_tinfo; |
6634 | struct ahd_tmode_tstate *tstate; |
6635 | uint16_t target_mask; |
6636 | |
6637 | tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id, |
6638 | targ, &tstate); |
6639 | user_tinfo = &tinfo->user; |
6640 | |
6641 | /* |
6642 | * We support SPC2 and SPI4. |
6643 | */ |
6644 | tinfo->user.protocol_version = 4; |
6645 | tinfo->user.transport_version = 4; |
6646 | |
6647 | target_mask = 0x01 << targ; |
6648 | ahd->user_discenable &= ~target_mask; |
6649 | tstate->discenable &= ~target_mask; |
6650 | ahd->user_tagenable &= ~target_mask; |
6651 | if (sc->device_flags[targ] & CFDISC0x0400) { |
6652 | tstate->discenable |= target_mask; |
6653 | ahd->user_discenable |= target_mask; |
6654 | ahd->user_tagenable |= target_mask; |
6655 | } else { |
6656 | /* |
6657 | * Cannot be packetized without disconnection. |
6658 | */ |
6659 | sc->device_flags[targ] &= ~CFPACKETIZED0x0080; |
6660 | } |
6661 | |
6662 | user_tinfo->ppr_options = 0; |
6663 | user_tinfo->period = (sc->device_flags[targ] & CFXFER0x003F); |
6664 | if (user_tinfo->period < CFXFER_ASYNC0x3F) { |
6665 | if (user_tinfo->period <= AHD_PERIOD_10MHz0x19) |
6666 | user_tinfo->ppr_options |= MSG_EXT_PPR_DT_REQ0x02; |
6667 | user_tinfo->offset = MAX_OFFSET0xfe; |
6668 | } else { |
6669 | user_tinfo->offset = 0; |
6670 | user_tinfo->period = AHD_ASYNC_XFER_PERIOD0x44; |
6671 | } |
6672 | #ifdef AHD_FORCE_160 |
6673 | if (user_tinfo->period <= AHD_SYNCRATE_1600x8) |
6674 | user_tinfo->period = AHD_SYNCRATE_DT0x9; |
6675 | #endif |
6676 | |
6677 | if ((sc->device_flags[targ] & CFPACKETIZED0x0080) != 0) { |
6678 | user_tinfo->ppr_options |= MSG_EXT_PPR_RD_STRM0x20 |
6679 | | MSG_EXT_PPR_WR_FLOW0x10 |
6680 | | MSG_EXT_PPR_HOLD_MCS0x08 |
6681 | | MSG_EXT_PPR_IU_REQ0x01; |
6682 | if ((ahd->features & AHD_RTI) != 0) |
6683 | user_tinfo->ppr_options |= MSG_EXT_PPR_RTI0x40; |
6684 | } |
6685 | |
6686 | if ((sc->device_flags[targ] & CFQAS0x0040) != 0) |
6687 | user_tinfo->ppr_options |= MSG_EXT_PPR_QAS_REQ0x04; |
6688 | |
6689 | if ((sc->device_flags[targ] & CFWIDEB0x1000) != 0) |
6690 | user_tinfo->width = MSG_EXT_WDTR_BUS_16_BIT0x01; |
6691 | else |
6692 | user_tinfo->width = MSG_EXT_WDTR_BUS_8_BIT0x00; |
6693 | #ifdef AHD_DEBUG |
6694 | if ((ahd_debug & AHD_SHOW_MISC) != 0) |
6695 | printf("(%d): %x:%x:%x:%x\n", targ, user_tinfo->width, |
6696 | user_tinfo->period, user_tinfo->offset, |
6697 | user_tinfo->ppr_options); |
6698 | #endif |
6699 | /* |
6700 | * Start out Async/Narrow/Untagged and with |
6701 | * conservative protocol support. |
6702 | */ |
6703 | tstate->tagenable &= ~target_mask; |
6704 | tinfo->goal.protocol_version = 2; |
6705 | tinfo->goal.transport_version = 2; |
6706 | tinfo->curr.protocol_version = 2; |
6707 | tinfo->curr.transport_version = 2; |
6708 | ahd_compile_devinfo(&devinfo, ahd->our_id, |
6709 | targ, CAM_LUN_WILDCARD-1, |
6710 | 'A', ROLE_INITIATOR); |
6711 | ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT0x00, |
6712 | AHD_TRANS_CUR0x01|AHD_TRANS_GOAL0x04, /*paused*/TRUE1); |
6713 | ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0, |
6714 | /*ppr_options*/0, AHD_TRANS_CUR0x01|AHD_TRANS_GOAL0x04, |
6715 | /*paused*/TRUE1); |
6716 | } |
6717 | |
6718 | ahd->flags &= ~AHD_SPCHK_ENB_A; |
6719 | if (sc->bios_control & CFSPARITY0x0040) |
6720 | ahd->flags |= AHD_SPCHK_ENB_A; |
6721 | |
6722 | ahd->flags &= ~AHD_RESET_BUS_A; |
6723 | if (sc->bios_control & CFRESETB0x0800) |
6724 | ahd->flags |= AHD_RESET_BUS_A; |
6725 | |
6726 | ahd->flags &= ~AHD_EXTENDED_TRANS_A; |
6727 | if (sc->bios_control & CFEXTEND0x0080) |
6728 | ahd->flags |= AHD_EXTENDED_TRANS_A; |
6729 | |
6730 | ahd->flags &= ~AHD_BIOS_ENABLED; |
6731 | if ((sc->bios_control & CFBIOSSTATE0x000C) == CFBS_ENABLED0x04) |
6732 | ahd->flags |= AHD_BIOS_ENABLED; |
6733 | |
6734 | ahd->flags &= ~AHD_STPWLEVEL_A; |
6735 | if ((sc->adapter_control & CFSTPWLEVEL0x0040) != 0) |
6736 | ahd->flags |= AHD_STPWLEVEL_A; |
6737 | |
6738 | return (0); |
6739 | } |
6740 | |
6741 | /* |
6742 | * Parse device configuration information. |
6743 | */ |
6744 | int |
6745 | ahd_parse_vpddata(struct ahd_softc *ahd, struct vpd_config *vpd) |
6746 | { |
6747 | int error; |
6748 | |
6749 | error = ahd_verify_vpd_cksum(vpd); |
6750 | if (error == 0) |
6751 | return (EINVAL22); |
6752 | if ((vpd->bios_flags & VPDBOOTHOST0x0002) != 0) |
6753 | ahd->flags |= AHD_BOOT_CHANNEL; |
6754 | return (0); |
6755 | } |
6756 | |
6757 | void |
6758 | ahd_intr_enable(struct ahd_softc *ahd, int enable) |
6759 | { |
6760 | u_int hcntrl; |
6761 | |
6762 | hcntrl = ahd_inb(ahd, HCNTRL)(((ahd)->tags[(0x05) >> 8])->read_1(((ahd)->bshs [(0x05) >> 8]), ((0x05) & 0xFF))); |
6763 | hcntrl &= ~INTEN0x02; |
6764 | ahd->pause &= ~INTEN0x02; |
6765 | ahd->unpause &= ~INTEN0x02; |
6766 | if (enable) { |
6767 | hcntrl |= INTEN0x02; |
6768 | ahd->pause |= INTEN0x02; |
6769 | ahd->unpause |= INTEN0x02; |
6770 | } |
6771 | ahd_outb(ahd, HCNTRL, hcntrl)(((ahd)->tags[(0x05) >> 8])->write_1(((ahd)->bshs [(0x05) >> 8]), ((0x05) & 0xFF), (hcntrl))); |
6772 | } |
6773 | |
6774 | void |
6775 | ahd_update_coalescing_values(struct ahd_softc *ahd, u_int timer, u_int maxcmds, |
6776 | u_int mincmds) |
6777 | { |
6778 | if (timer > AHD_TIMER_MAX_US0x18ffe7) |
6779 | timer = AHD_TIMER_MAX_US0x18ffe7; |
6780 | ahd->int_coalescing_timer = timer; |
6781 | |
6782 | if (maxcmds > AHD_INT_COALESCING_MAXCMDS_MAX127) |
6783 | maxcmds = AHD_INT_COALESCING_MAXCMDS_MAX127; |
6784 | if (mincmds > AHD_INT_COALESCING_MINCMDS_MAX127) |
6785 | mincmds = AHD_INT_COALESCING_MINCMDS_MAX127; |
6786 | ahd->int_coalescing_maxcmds = maxcmds; |
6787 | ahd_outw(ahd, INT_COALESCING_TIMER0x150, timer / AHD_TIMER_US_PER_TICK0x19); |
6788 | ahd_outb(ahd, INT_COALESCING_MAXCMDS, -maxcmds)(((ahd)->tags[(0x152) >> 8])->write_1(((ahd)-> bshs[(0x152) >> 8]), ((0x152) & 0xFF), (-maxcmds))); |
6789 | ahd_outb(ahd, INT_COALESCING_MINCMDS, -mincmds)(((ahd)->tags[(0x153) >> 8])->write_1(((ahd)-> bshs[(0x153) >> 8]), ((0x153) & 0xFF), (-mincmds))); |
6790 | } |
6791 | |
6792 | void |
6793 | ahd_enable_coalescing(struct ahd_softc *ahd, int enable) |
6794 | { |
6795 | |
6796 | ahd->hs_mailbox &= ~ENINT_COALESCE0x40; |
6797 | if (enable) |
6798 | ahd->hs_mailbox |= ENINT_COALESCE0x40; |
6799 | ahd_outb(ahd, HS_MAILBOX, ahd->hs_mailbox)(((ahd)->tags[(0x0b) >> 8])->write_1(((ahd)->bshs [(0x0b) >> 8]), ((0x0b) & 0xFF), (ahd->hs_mailbox ))); |
6800 | ahd_flush_device_writes(ahd); |
6801 | ahd_run_qoutfifo(ahd); |
6802 | } |
6803 | |
6804 | /* |
6805 | * Ensure that the card is paused in a location |
6806 | * outside of all critical sections and that all |
6807 | * pending work is completed prior to returning. |
6808 | * This routine should only be called from outside |
6809 | * an interrupt context. |
6810 | */ |
6811 | void |
6812 | ahd_pause_and_flushwork(struct ahd_softc *ahd) |
6813 | { |
6814 | u_int intstat; |
6815 | u_int maxloops; |
6816 | |
6817 | maxloops = 1000; |
6818 | ahd->flags |= AHD_ALL_INTERRUPTS; |
6819 | ahd_pause(ahd); |
6820 | /* |
6821 | * Freeze the outgoing selections. We do this only |
6822 | * until we are safely paused without further selections |
6823 | * pending. |
6824 | */ |
6825 | ahd->qfreeze_cnt--; |
6826 | ahd_outw(ahd, KERNEL_QFREEZE_COUNT0x134, ahd->qfreeze_cnt); |
6827 | ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN)(((ahd)->tags[(0x14d) >> 8])->write_1(((ahd)-> bshs[(0x14d) >> 8]), ((0x14d) & 0xFF), ((((ahd)-> tags[(0x14d) >> 8])->read_1(((ahd)->bshs[(0x14d) >> 8]), ((0x14d) & 0xFF))) | 0x04))); |
6828 | do { |
6829 | |
6830 | ahd_unpause(ahd); |
6831 | /* |
6832 | * Give the sequencer some time to service |
6833 | * any active selections. |
6834 | */ |
6835 | aic_delay(500)(*delay_func)(500); |
6836 | |
6837 | ahd_intr(ahd); |
6838 | ahd_pause(ahd); |
6839 | intstat = ahd_inb(ahd, INTSTAT)(((ahd)->tags[(0x01) >> 8])->read_1(((ahd)->bshs [(0x01) >> 8]), ((0x01) & 0xFF))); |
6840 | if ((intstat & INT_PEND0xff) == 0) { |
6841 | ahd_clear_critical_section(ahd); |
6842 | intstat = ahd_inb(ahd, INTSTAT)(((ahd)->tags[(0x01) >> 8])->read_1(((ahd)->bshs [(0x01) >> 8]), ((0x01) & 0xFF))); |
6843 | } |
6844 | } while (--maxloops |
6845 | && (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0) |
6846 | && ((intstat & INT_PEND0xff) != 0 |
6847 | || (ahd_inb(ahd, SCSISEQ0)(((ahd)->tags[(0x3a) >> 8])->read_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF))) & ENSELO0x40) != 0 |
6848 | || (ahd_inb(ahd, SSTAT0)(((ahd)->tags[(0x4b) >> 8])->read_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF))) & (SELDO0x40|SELINGO0x10)) != 0)); |
6849 | |
6850 | if (maxloops == 0) { |
6851 | printf("Infinite interrupt loop, INTSTAT = %x", |
6852 | ahd_inb(ahd, INTSTAT)(((ahd)->tags[(0x01) >> 8])->read_1(((ahd)->bshs [(0x01) >> 8]), ((0x01) & 0xFF)))); |
6853 | } |
6854 | ahd->qfreeze_cnt++; |
6855 | ahd_outw(ahd, KERNEL_QFREEZE_COUNT0x134, ahd->qfreeze_cnt); |
6856 | |
6857 | ahd_flush_qoutfifo(ahd); |
6858 | |
6859 | ahd->flags &= ~AHD_ALL_INTERRUPTS; |
6860 | } |
6861 | |
6862 | int |
6863 | ahd_suspend(struct ahd_softc *ahd) |
6864 | { |
6865 | |
6866 | ahd_pause_and_flushwork(ahd); |
6867 | |
6868 | if (!TAILQ_EMPTY(&ahd->pending_scbs)(((&ahd->pending_scbs)->tqh_first) == ((void *)0))) { |
6869 | ahd_unpause(ahd); |
6870 | return (EBUSY16); |
6871 | } |
6872 | ahd_shutdown(ahd); |
6873 | return (0); |
6874 | } |
6875 | |
6876 | int |
6877 | ahd_resume(struct ahd_softc *ahd) |
6878 | { |
6879 | |
6880 | ahd_reset(ahd, /*reinit*/TRUE1); |
6881 | ahd_intr_enable(ahd, TRUE1); |
6882 | ahd_restart(ahd); |
6883 | return (0); |
6884 | } |
6885 | |
6886 | /************************** Busy Target Table *********************************/ |
6887 | /* |
6888 | * Set SCBPTR to the SCB that contains the busy |
6889 | * table entry for TCL. Return the offset into |
6890 | * the SCB that contains the entry for TCL. |
6891 | * saved_scbid is dereferenced and set to the |
6892 | * scbid that should be restored once manipulation |
6893 | * of the TCL entry is complete. |
6894 | */ |
6895 | u_int ahd_index_busy_tcl(struct ahd_softc *, u_int *, u_int); |
6896 | u_int |
6897 | ahd_index_busy_tcl(struct ahd_softc *ahd, u_int *saved_scbid, u_int tcl) |
6898 | { |
6899 | /* |
6900 | * Index to the SCB that contains the busy entry. |
6901 | */ |
6902 | 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", 6902);; |
6903 | *saved_scbid = ahd_get_scbptr(ahd); |
6904 | ahd_set_scbptr(ahd, TCL_LUN(tcl)(tcl & (256 - 1)) |
6905 | | ((TCL_TARGET_OFFSET(tcl)((((tcl) >> 4) & 0xf0) >> 4) & 0xC) << 4)); |
6906 | |
6907 | /* |
6908 | * And now calculate the SCB offset to the entry. |
6909 | * Each entry is 2 bytes wide, hence the |
6910 | * multiplication by 2. |
6911 | */ |
6912 | return (((TCL_TARGET_OFFSET(tcl)((((tcl) >> 4) & 0xf0) >> 4) & 0x3) << 1) + SCB_DISCONNECTED_LISTS0x1b8); |
6913 | } |
6914 | |
6915 | /* |
6916 | * Return the untagged transaction id for a given target/channel lun. |
6917 | */ |
6918 | u_int |
6919 | ahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl) |
6920 | { |
6921 | u_int scbid; |
6922 | u_int scb_offset; |
6923 | u_int saved_scbptr; |
6924 | |
6925 | scb_offset = ahd_index_busy_tcl(ahd, &saved_scbptr, tcl); |
6926 | scbid = ahd_inw_scbram(ahd, scb_offset); |
6927 | ahd_set_scbptr(ahd, saved_scbptr); |
6928 | return (scbid); |
6929 | } |
6930 | |
6931 | void |
6932 | ahd_busy_tcl(struct ahd_softc *ahd, u_int tcl, u_int scbid) |
6933 | { |
6934 | u_int scb_offset; |
6935 | u_int saved_scbptr; |
6936 | |
6937 | scb_offset = ahd_index_busy_tcl(ahd, &saved_scbptr, tcl); |
6938 | ahd_outw(ahd, scb_offset, scbid); |
6939 | ahd_set_scbptr(ahd, saved_scbptr); |
6940 | } |
6941 | |
6942 | /************************** SCB and SCB queue management **********************/ |
6943 | int |
6944 | ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, int target, |
6945 | char channel, int lun, u_int tag, role_t role) |
6946 | { |
6947 | int targ = SCB_GET_TARGET(ahd, scb)((((scb)->hscb->scsiid) & 0xf0) >> 0x04); |
6948 | char chan = SCB_GET_CHANNEL(ahd, scb)('A'); |
6949 | int slun = SCB_GET_LUN(scb)((scb)->hscb->lun); |
6950 | int match; |
6951 | |
6952 | match = ((chan == channel) || (channel == ALL_CHANNELS'\0')); |
6953 | if (match != 0) |
6954 | match = ((targ == target) || (target == CAM_TARGET_WILDCARD((u_int)~0))); |
6955 | if (match != 0) |
6956 | match = ((lun == slun) || (lun == CAM_LUN_WILDCARD-1)); |
6957 | if (match != 0) { |
6958 | #if AHD_TARGET_MODE |
6959 | int group; |
6960 | |
6961 | group = XPT_FC_GROUP(scb->io_ctx->ccb_h.func_code); |
6962 | if (role == ROLE_INITIATOR) { |
6963 | match = (group != XPT_FC_GROUP_TMODE) |
6964 | && ((tag == SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag))) |
6965 | || (tag == SCB_LIST_NULL0xFF00)); |
6966 | } else if (role == ROLE_TARGET) { |
6967 | match = (group == XPT_FC_GROUP_TMODE) |
6968 | && ((tag == scb->io_ctx->csio.tag_id) |
6969 | || (tag == SCB_LIST_NULL0xFF00)); |
6970 | } |
6971 | #else /* !AHD_TARGET_MODE */ |
6972 | match = ((tag == SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag))) || (tag == SCB_LIST_NULL0xFF00)); |
6973 | #endif /* AHD_TARGET_MODE */ |
6974 | } |
6975 | |
6976 | return match; |
6977 | } |
6978 | |
6979 | void |
6980 | ahd_freeze_devq(struct ahd_softc *ahd, struct scb *scb) |
6981 | { |
6982 | int target; |
6983 | char channel; |
6984 | int lun; |
6985 | |
6986 | target = SCB_GET_TARGET(ahd, scb)((((scb)->hscb->scsiid) & 0xf0) >> 0x04); |
6987 | lun = SCB_GET_LUN(scb)((scb)->hscb->lun); |
6988 | channel = SCB_GET_CHANNEL(ahd, scb)('A'); |
6989 | |
6990 | ahd_search_qinfifo(ahd, target, channel, lun, |
6991 | /*tag*/SCB_LIST_NULL0xFF00, ROLE_UNKNOWN, |
6992 | CAM_REQUEUE_REQ, SEARCH_COMPLETE); |
6993 | } |
6994 | |
6995 | void |
6996 | ahd_qinfifo_requeue_tail(struct ahd_softc *ahd, struct scb *scb) |
6997 | { |
6998 | struct scb *prev_scb; |
6999 | ahd_mode_state saved_modes; |
7000 | |
7001 | saved_modes = ahd_save_modes(ahd); |
7002 | ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); |
7003 | prev_scb = NULL((void *)0); |
7004 | if (ahd_qinfifo_count(ahd) != 0) { |
7005 | u_int prev_tag; |
7006 | u_int prev_pos; |
7007 | |
7008 | prev_pos = AHD_QIN_WRAP(ahd->qinfifonext - 1)((ahd->qinfifonext - 1) & (512 -1)); |
7009 | prev_tag = ahd->qinfifo[prev_pos]; |
7010 | prev_scb = ahd_lookup_scb(ahd, prev_tag); |
7011 | } |
7012 | ahd_qinfifo_requeue(ahd, prev_scb, scb); |
7013 | ahd_set_hnscb_qoff(ahd, ahd->qinfifonext); |
7014 | ahd_restore_modes(ahd, saved_modes); |
7015 | } |
7016 | |
7017 | void |
7018 | ahd_qinfifo_requeue(struct ahd_softc *ahd, struct scb *prev_scb, |
7019 | struct scb *scb) |
7020 | { |
7021 | if (prev_scb == NULL((void *)0)) { |
7022 | uint32_t busaddr; |
7023 | |
7024 | busaddr = aic_le32toh(scb->hscb->hscb_busaddr)((__uint32_t)(scb->hscb->hscb_busaddr)); |
7025 | ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR0x124, busaddr); |
7026 | } else { |
7027 | prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr; |
7028 | ahd_sync_scb(ahd, prev_scb, |
7029 | BUS_DMASYNC_PREREAD0x01|BUS_DMASYNC_PREWRITE0x04); |
7030 | } |
7031 | ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)((ahd->qinfifonext) & (512 -1))] = SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)); |
7032 | ahd->qinfifonext++; |
7033 | scb->hscb->next_hscb_busaddr = ahd->next_queued_hscb->hscb_busaddr; |
7034 | ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD0x01|BUS_DMASYNC_PREWRITE0x04); |
7035 | } |
7036 | |
7037 | int |
7038 | ahd_qinfifo_count(struct ahd_softc *ahd) |
7039 | { |
7040 | u_int qinpos; |
7041 | u_int wrap_qinpos; |
7042 | u_int wrap_qinfifonext; |
7043 | |
7044 | AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK)ahd_assert_modes(ahd, (0x01 << (AHD_MODE_CCHAN)), (0x01 << (AHD_MODE_CCHAN)), "/usr/src/sys/dev/ic/aic79xx.c", 7044);; |
7045 | qinpos = ahd_get_snscb_qoff(ahd); |
7046 | wrap_qinpos = AHD_QIN_WRAP(qinpos)((qinpos) & (512 -1)); |
7047 | wrap_qinfifonext = AHD_QIN_WRAP(ahd->qinfifonext)((ahd->qinfifonext) & (512 -1)); |
7048 | if (wrap_qinfifonext >= wrap_qinpos) |
7049 | return (wrap_qinfifonext - wrap_qinpos); |
7050 | else |
7051 | return (wrap_qinfifonext |
7052 | + NUM_ELEMENTS(ahd->qinfifo)(sizeof(ahd->qinfifo) / sizeof(*ahd->qinfifo)) - wrap_qinpos); |
7053 | } |
7054 | |
7055 | void |
7056 | ahd_reset_cmds_pending(struct ahd_softc *ahd) |
7057 | { |
7058 | struct scb *scb; |
7059 | ahd_mode_state saved_modes; |
7060 | u_int pending_cmds; |
7061 | |
7062 | saved_modes = ahd_save_modes(ahd); |
7063 | ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); |
7064 | |
7065 | /* |
7066 | * Don't count any commands as outstanding that the |
7067 | * sequencer has already marked for completion. |
7068 | */ |
7069 | ahd_flush_qoutfifo(ahd); |
7070 | |
7071 | pending_cmds = 0; |
7072 | TAILQ_FOREACH(scb, &ahd->pending_scbs, next)for((scb) = ((&ahd->pending_scbs)->tqh_first); (scb ) != ((void *)0); (scb) = ((scb)->next.tqe_next)) { |
7073 | pending_cmds++; |
7074 | } |
7075 | ahd_outw(ahd, CMDS_PENDING0x154, pending_cmds - ahd_qinfifo_count(ahd)); |
7076 | ahd_restore_modes(ahd, saved_modes); |
7077 | ahd->flags &= ~AHD_UPDATE_PEND_CMDS; |
7078 | } |
7079 | |
7080 | void |
7081 | ahd_done_with_status(struct ahd_softc *ahd, struct scb *scb, uint32_t status) |
7082 | { |
7083 | cam_status ostat; |
7084 | cam_status cstat; |
7085 | |
7086 | ostat = aic_get_transaction_status(scb)(((scb)->xs->flags & 0x00008) ? CAM_REQ_CMP : (scb) ->xs->error); |
7087 | if (ostat == CAM_REQ_INPROG) |
7088 | aic_set_transaction_status(scb, status)(scb)->xs->error = (status); |
7089 | cstat = aic_get_transaction_status(scb)(((scb)->xs->flags & 0x00008) ? CAM_REQ_CMP : (scb) ->xs->error); |
7090 | if (cstat != CAM_REQ_CMP) |
7091 | aic_freeze_scb(scb); |
7092 | ahd_done(ahd, scb); |
7093 | } |
7094 | |
7095 | int |
7096 | ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, |
7097 | int lun, u_int tag, role_t role, uint32_t status, |
7098 | ahd_search_action action) |
7099 | { |
7100 | struct scb *scb; |
7101 | struct scb *mk_msg_scb; |
7102 | struct scb *prev_scb; |
7103 | ahd_mode_state saved_modes; |
7104 | u_int qinstart; |
7105 | u_int qinpos; |
7106 | u_int qintail; |
7107 | u_int tid_next; |
7108 | u_int tid_prev; |
7109 | u_int scbid; |
7110 | u_int seq_flags2; |
7111 | u_int savedscbptr; |
7112 | uint32_t busaddr; |
7113 | int found; |
7114 | int targets; |
7115 | |
7116 | /* Must be in CCHAN mode */ |
7117 | saved_modes = ahd_save_modes(ahd); |
7118 | ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); |
7119 | |
7120 | /* |
7121 | * Halt any pending SCB DMA. The sequencer will reinitiate |
7122 | * this dma if the qinfifo is not empty once we unpause. |
7123 | */ |
7124 | if ((ahd_inb(ahd, CCSCBCTL)(((ahd)->tags[(0xad) >> 8])->read_1(((ahd)->bshs [(0xad) >> 8]), ((0xad) & 0xFF))) & (CCARREN0x10|CCSCBEN0x08|CCSCBDIR0x04)) |
7125 | == (CCARREN0x10|CCSCBEN0x08|CCSCBDIR0x04)) { |
7126 | ahd_outb(ahd, CCSCBCTL,(((ahd)->tags[(0xad) >> 8])->write_1(((ahd)->bshs [(0xad) >> 8]), ((0xad) & 0xFF), ((((ahd)->tags[ (0xad) >> 8])->read_1(((ahd)->bshs[(0xad) >> 8]), ((0xad) & 0xFF))) & ~(0x10|0x08)))) |
7127 | ahd_inb(ahd, CCSCBCTL) & ~(CCARREN|CCSCBEN))(((ahd)->tags[(0xad) >> 8])->write_1(((ahd)->bshs [(0xad) >> 8]), ((0xad) & 0xFF), ((((ahd)->tags[ (0xad) >> 8])->read_1(((ahd)->bshs[(0xad) >> 8]), ((0xad) & 0xFF))) & ~(0x10|0x08)))); |
7128 | while ((ahd_inb(ahd, CCSCBCTL)(((ahd)->tags[(0xad) >> 8])->read_1(((ahd)->bshs [(0xad) >> 8]), ((0xad) & 0xFF))) & (CCARREN0x10|CCSCBEN0x08)) != 0) |
7129 | ; |
7130 | } |
7131 | /* Determine sequencer's position in the qinfifo. */ |
7132 | qintail = AHD_QIN_WRAP(ahd->qinfifonext)((ahd->qinfifonext) & (512 -1)); |
7133 | qinstart = ahd_get_snscb_qoff(ahd); |
7134 | qinpos = AHD_QIN_WRAP(qinstart)((qinstart) & (512 -1)); |
7135 | found = 0; |
7136 | prev_scb = NULL((void *)0); |
7137 | |
7138 | if (action == SEARCH_PRINT) { |
7139 | printf("qinstart = %d qinfifonext = %d\nQINFIFO:", |
7140 | qinstart, ahd->qinfifonext); |
7141 | } |
7142 | |
7143 | /* |
7144 | * Start with an empty queue. Entries that are not chosen |
7145 | * for removal will be re-added to the queue as we go. |
7146 | */ |
7147 | ahd->qinfifonext = qinstart; |
7148 | busaddr = aic_le32toh(ahd->next_queued_hscb->hscb_busaddr)((__uint32_t)(ahd->next_queued_hscb->hscb_busaddr)); |
7149 | ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR0x124, busaddr); |
7150 | |
7151 | while (qinpos != qintail) { |
7152 | scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]); |
7153 | if (scb == NULL((void *)0)) { |
7154 | printf("qinpos = %d, SCB index = %d\n", |
7155 | qinpos, ahd->qinfifo[qinpos]); |
7156 | panic("Loop 1"); |
7157 | } |
7158 | |
7159 | if (ahd_match_scb(ahd, scb, target, channel, lun, tag, role)) { |
7160 | /* |
7161 | * We found an scb that needs to be acted on. |
7162 | */ |
7163 | found++; |
7164 | switch (action) { |
7165 | case SEARCH_COMPLETE: |
7166 | if ((scb->flags & SCB_ACTIVE) == 0) |
7167 | printf("Inactive SCB in qinfifo\n"); |
7168 | ahd_done_with_status(ahd, scb, status); |
7169 | /* FALLTHROUGH */ |
7170 | case SEARCH_REMOVE: |
7171 | break; |
7172 | case SEARCH_PRINT: |
7173 | printf(" 0x%x", ahd->qinfifo[qinpos]); |
7174 | /* FALLTHROUGH */ |
7175 | case SEARCH_COUNT: |
7176 | ahd_qinfifo_requeue(ahd, prev_scb, scb); |
7177 | prev_scb = scb; |
7178 | break; |
7179 | } |
7180 | } else { |
7181 | ahd_qinfifo_requeue(ahd, prev_scb, scb); |
7182 | prev_scb = scb; |
7183 | } |
7184 | qinpos = AHD_QIN_WRAP(qinpos+1)((qinpos+1) & (512 -1)); |
7185 | } |
7186 | |
7187 | ahd_set_hnscb_qoff(ahd, ahd->qinfifonext); |
7188 | |
7189 | if (action == SEARCH_PRINT) |
7190 | printf("\nWAITING_TID_QUEUES:\n"); |
7191 | |
7192 | /* |
7193 | * Search waiting for selection lists. We traverse the |
7194 | * list of "their ids" waiting for selection and, if |
7195 | * appropriate, traverse the SCBs of each "their id" |
7196 | * looking for matches. |
7197 | */ |
7198 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
7199 | seq_flags2 = ahd_inb(ahd, SEQ_FLAGS2)(((ahd)->tags[(0x14d) >> 8])->read_1(((ahd)->bshs [(0x14d) >> 8]), ((0x14d) & 0xFF))); |
7200 | if ((seq_flags2 & PENDING_MK_MESSAGE0x01) != 0) { |
7201 | scbid = ahd_inw(ahd, MK_MESSAGE_SCB0x160); |
7202 | mk_msg_scb = ahd_lookup_scb(ahd, scbid); |
7203 | } else |
7204 | mk_msg_scb = NULL((void *)0); |
7205 | savedscbptr = ahd_get_scbptr(ahd); |
7206 | tid_next = ahd_inw(ahd, WAITING_TID_HEAD0x120); |
7207 | tid_prev = SCB_LIST_NULL0xFF00; |
7208 | targets = 0; |
7209 | for (scbid = tid_next; !SCBID_IS_NULL(scbid)(((scbid) & 0xFF00 ) == 0xFF00); scbid = tid_next) { |
7210 | u_int tid_head; |
7211 | u_int tid_tail; |
7212 | |
7213 | targets++; |
7214 | if (targets > AHD_NUM_TARGETS16) |
7215 | panic("TID LIST LOOP"); |
7216 | |
7217 | if (scbid >= ahd->scb_data.numscbs) { |
7218 | printf("%s: Waiting TID List inconsistency. " |
7219 | "SCB index == 0x%x, yet numscbs == 0x%x.", |
7220 | ahd_name(ahd), scbid, ahd->scb_data.numscbs); |
7221 | ahd_dump_card_state(ahd); |
7222 | panic("for safety"); |
7223 | } |
7224 | scb = ahd_lookup_scb(ahd, scbid); |
7225 | if (scb == NULL((void *)0)) { |
7226 | printf("%s: SCB = 0x%x Not Active!\n", |
7227 | ahd_name(ahd), scbid); |
7228 | panic("Waiting TID List traversal"); |
7229 | } |
7230 | ahd_set_scbptr(ahd, scbid); |
7231 | tid_next = ahd_inw_scbram(ahd, SCB_NEXT20x1ae); |
7232 | if (ahd_match_scb(ahd, scb, target, channel, CAM_LUN_WILDCARD-1, |
7233 | SCB_LIST_NULL0xFF00, ROLE_UNKNOWN) == 0) { |
7234 | tid_prev = scbid; |
7235 | continue; |
7236 | } |
7237 | |
7238 | /* |
7239 | * We found a list of scbs that needs to be searched. |
7240 | */ |
7241 | if (action == SEARCH_PRINT) |
7242 | printf(" %d ( ", SCB_GET_TARGET(ahd, scb)((((scb)->hscb->scsiid) & 0xf0) >> 0x04)); |
7243 | tid_head = scbid; |
7244 | found += ahd_search_scb_list(ahd, target, channel, |
7245 | lun, tag, role, status, |
7246 | action, &tid_head, &tid_tail, |
7247 | SCB_GET_TARGET(ahd, scb)((((scb)->hscb->scsiid) & 0xf0) >> 0x04)); |
7248 | /* |
7249 | * Check any MK_MESSAGE SCB that is still waiting to |
7250 | * enter this target's waiting for selection queue. |
7251 | */ |
7252 | if (mk_msg_scb != NULL((void *)0) |
7253 | && ahd_match_scb(ahd, mk_msg_scb, target, channel, |
7254 | lun, tag, role)) { |
7255 | |
7256 | /* |
7257 | * We found an scb that needs to be acted on. |
7258 | */ |
7259 | found++; |
7260 | switch (action) { |
7261 | case SEARCH_COMPLETE: |
7262 | if ((mk_msg_scb->flags & SCB_ACTIVE) == 0) |
7263 | printf("Inactive SCB pending MK_MSG\n"); |
7264 | ahd_done_with_status(ahd, mk_msg_scb, status); |
7265 | /* FALLTHROUGH */ |
7266 | case SEARCH_REMOVE: |
7267 | { |
7268 | u_int tail_offset; |
7269 | |
7270 | printf("Removing MK_MSG scb\n"); |
7271 | |
7272 | /* |
7273 | * Reset our tail to the tail of the |
7274 | * main per-target list. |
7275 | */ |
7276 | tail_offset = WAITING_SCB_TAILS0x100 |
7277 | + (2 * SCB_GET_TARGET(ahd, mk_msg_scb)((((mk_msg_scb)->hscb->scsiid) & 0xf0) >> 0x04 )); |
7278 | ahd_outw(ahd, tail_offset, tid_tail); |
7279 | |
7280 | seq_flags2 &= ~PENDING_MK_MESSAGE0x01; |
7281 | ahd_outb(ahd, SEQ_FLAGS2, seq_flags2)(((ahd)->tags[(0x14d) >> 8])->write_1(((ahd)-> bshs[(0x14d) >> 8]), ((0x14d) & 0xFF), (seq_flags2) )); |
7282 | ahd_outw(ahd, CMDS_PENDING0x154, |
7283 | ahd_inw(ahd, CMDS_PENDING0x154)-1); |
7284 | mk_msg_scb = NULL((void *)0); |
7285 | break; |
7286 | } |
7287 | case SEARCH_PRINT: |
7288 | printf(" 0x%x", SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag))); |
7289 | /* FALLTHROUGH */ |
7290 | case SEARCH_COUNT: |
7291 | break; |
7292 | } |
7293 | } |
7294 | |
7295 | if (mk_msg_scb != NULL((void *)0) |
7296 | && SCBID_IS_NULL(tid_head)(((tid_head) & 0xFF00 ) == 0xFF00) |
7297 | && ahd_match_scb(ahd, scb, target, channel, CAM_LUN_WILDCARD-1, |
7298 | SCB_LIST_NULL0xFF00, ROLE_UNKNOWN)) { |
7299 | |
7300 | /* |
7301 | * When removing the last SCB for a target |
7302 | * queue with a pending MK_MESSAGE scb, we |
7303 | * must queue the MK_MESSAGE scb. |
7304 | */ |
7305 | printf("Queueing mk_msg_scb\n"); |
7306 | tid_head = ahd_inw(ahd, MK_MESSAGE_SCB0x160); |
7307 | seq_flags2 &= ~PENDING_MK_MESSAGE0x01; |
7308 | ahd_outb(ahd, SEQ_FLAGS2, seq_flags2)(((ahd)->tags[(0x14d) >> 8])->write_1(((ahd)-> bshs[(0x14d) >> 8]), ((0x14d) & 0xFF), (seq_flags2) )); |
7309 | mk_msg_scb = NULL((void *)0); |
7310 | } |
7311 | if (tid_head != scbid) |
7312 | ahd_stitch_tid_list(ahd, tid_prev, tid_head, tid_next); |
7313 | if (!SCBID_IS_NULL(tid_head)(((tid_head) & 0xFF00 ) == 0xFF00)) |
7314 | tid_prev = tid_head; |
7315 | if (action == SEARCH_PRINT) |
7316 | printf(")\n"); |
7317 | } |
7318 | |
7319 | /* Restore saved state. */ |
7320 | ahd_set_scbptr(ahd, savedscbptr); |
7321 | ahd_restore_modes(ahd, saved_modes); |
7322 | return (found); |
7323 | } |
7324 | |
7325 | int |
7326 | ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, |
7327 | int lun, u_int tag, role_t role, uint32_t status, |
7328 | ahd_search_action action, u_int *list_head, |
7329 | u_int *list_tail, u_int tid) |
7330 | { |
7331 | struct scb *scb; |
7332 | u_int scbid; |
7333 | u_int next; |
7334 | u_int prev; |
7335 | int found; |
7336 | |
7337 | 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", 7337);; |
7338 | found = 0; |
7339 | prev = SCB_LIST_NULL0xFF00; |
7340 | next = *list_head; |
7341 | *list_tail = SCB_LIST_NULL0xFF00; |
7342 | for (scbid = next; !SCBID_IS_NULL(scbid)(((scbid) & 0xFF00 ) == 0xFF00); scbid = next) { |
7343 | if (scbid >= ahd->scb_data.numscbs) { |
7344 | printf("%s:SCB List inconsistency. " |
7345 | "SCB == 0x%x, yet numscbs == 0x%x.", |
7346 | ahd_name(ahd), scbid, ahd->scb_data.numscbs); |
7347 | ahd_dump_card_state(ahd); |
7348 | panic("for safety"); |
7349 | } |
7350 | scb = ahd_lookup_scb(ahd, scbid); |
7351 | if (scb == NULL((void *)0)) { |
7352 | printf("%s: SCB = %d Not Active!\n", |
7353 | ahd_name(ahd), scbid); |
7354 | panic("Waiting List traversal"); |
7355 | } |
7356 | ahd_set_scbptr(ahd, scbid); |
7357 | *list_tail = scbid; |
7358 | next = ahd_inw_scbram(ahd, SCB_NEXT0x1ac); |
7359 | if (ahd_match_scb(ahd, scb, target, channel, |
7360 | lun, SCB_LIST_NULL0xFF00, role) == 0) { |
7361 | prev = scbid; |
7362 | continue; |
7363 | } |
7364 | found++; |
7365 | switch (action) { |
7366 | case SEARCH_COMPLETE: |
7367 | if ((scb->flags & SCB_ACTIVE) == 0) |
7368 | printf("Inactive SCB in Waiting List\n"); |
7369 | ahd_done_with_status(ahd, scb, status); |
7370 | /* FALLTHROUGH */ |
7371 | case SEARCH_REMOVE: |
7372 | ahd_rem_wscb(ahd, scbid, prev, next, tid); |
7373 | *list_tail = prev; |
7374 | if (SCBID_IS_NULL(prev)(((prev) & 0xFF00 ) == 0xFF00)) |
7375 | *list_head = next; |
7376 | break; |
7377 | case SEARCH_PRINT: |
7378 | printf("0x%x ", scbid); |
7379 | case SEARCH_COUNT: |
7380 | prev = scbid; |
7381 | break; |
7382 | } |
7383 | if (found > AHD_SCB_MAX512) |
7384 | panic("SCB LIST LOOP"); |
7385 | } |
7386 | if (action == SEARCH_COMPLETE |
7387 | || action == SEARCH_REMOVE) |
7388 | ahd_outw(ahd, CMDS_PENDING0x154, ahd_inw(ahd, CMDS_PENDING0x154) - found); |
7389 | return (found); |
7390 | } |
7391 | |
7392 | void |
7393 | ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev, |
7394 | u_int tid_cur, u_int tid_next) |
7395 | { |
7396 | 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", 7396);; |
7397 | |
7398 | if (SCBID_IS_NULL(tid_cur)(((tid_cur) & 0xFF00 ) == 0xFF00)) { |
7399 | |
7400 | /* Bypass current TID list */ |
7401 | if (SCBID_IS_NULL(tid_prev)(((tid_prev) & 0xFF00 ) == 0xFF00)) { |
7402 | ahd_outw(ahd, WAITING_TID_HEAD0x120, tid_next); |
7403 | } else { |
7404 | ahd_set_scbptr(ahd, tid_prev); |
7405 | ahd_outw(ahd, SCB_NEXT20x1ae, tid_next); |
7406 | } |
7407 | if (SCBID_IS_NULL(tid_next)(((tid_next) & 0xFF00 ) == 0xFF00)) |
7408 | ahd_outw(ahd, WAITING_TID_TAIL0x122, tid_prev); |
7409 | } else { |
7410 | |
7411 | /* Stitch through tid_cur */ |
7412 | if (SCBID_IS_NULL(tid_prev)(((tid_prev) & 0xFF00 ) == 0xFF00)) { |
7413 | ahd_outw(ahd, WAITING_TID_HEAD0x120, tid_cur); |
7414 | } else { |
7415 | ahd_set_scbptr(ahd, tid_prev); |
7416 | ahd_outw(ahd, SCB_NEXT20x1ae, tid_cur); |
7417 | } |
7418 | ahd_set_scbptr(ahd, tid_cur); |
7419 | ahd_outw(ahd, SCB_NEXT20x1ae, tid_next); |
7420 | |
7421 | if (SCBID_IS_NULL(tid_next)(((tid_next) & 0xFF00 ) == 0xFF00)) |
7422 | ahd_outw(ahd, WAITING_TID_TAIL0x122, tid_cur); |
7423 | } |
7424 | } |
7425 | |
7426 | /* |
7427 | * Manipulate the waiting for selection list and return the |
7428 | * scb that follows the one that we remove. |
7429 | */ |
7430 | u_int |
7431 | ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid, |
7432 | u_int prev, u_int next, u_int tid) |
7433 | { |
7434 | u_int tail_offset; |
7435 | |
7436 | 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", 7436);; |
7437 | if (!SCBID_IS_NULL(prev)(((prev) & 0xFF00 ) == 0xFF00)) { |
7438 | ahd_set_scbptr(ahd, prev); |
7439 | ahd_outw(ahd, SCB_NEXT0x1ac, next); |
7440 | } |
7441 | |
7442 | /* |
7443 | * SCBs that have MK_MESSAGE set in them may |
7444 | * cause the tail pointer to be updated without |
7445 | * setting the next pointer of the previous tail. |
7446 | * Only clear the tail if the removed SCB was |
7447 | * the tail. |
7448 | */ |
7449 | tail_offset = WAITING_SCB_TAILS0x100 + (2 * tid); |
7450 | if (SCBID_IS_NULL(next)(((next) & 0xFF00 ) == 0xFF00) |
7451 | && ahd_inw(ahd, tail_offset) == scbid) |
7452 | ahd_outw(ahd, tail_offset, prev); |
7453 | |
7454 | ahd_add_scb_to_free_list(ahd, scbid); |
7455 | return (next); |
7456 | } |
7457 | |
7458 | /* |
7459 | * Add the SCB as selected by SCBPTR onto the on chip list of |
7460 | * free hardware SCBs. This list is empty/unused if we are not |
7461 | * performing SCB paging. |
7462 | */ |
7463 | void |
7464 | ahd_add_scb_to_free_list(struct ahd_softc *ahd, u_int scbid) |
7465 | { |
7466 | /* XXX Need some other mechanism to designate "free". */ |
7467 | /* |
7468 | * Invalidate the tag so that our abort |
7469 | * routines don't think it's active. |
7470 | ahd_outb(ahd, SCB_TAG, SCB_LIST_NULL); |
7471 | */ |
7472 | } |
7473 | |
7474 | /******************************** Error Handling ******************************/ |
7475 | /* |
7476 | * Abort all SCBs that match the given description (target/channel/lun/tag), |
7477 | * setting their status to the passed in status if the status has not already |
7478 | * been modified from CAM_REQ_INPROG. This routine assumes that the sequencer |
7479 | * is paused before it is called. |
7480 | */ |
7481 | int |
7482 | ahd_abort_scbs(struct ahd_softc *ahd, int target, char channel, |
7483 | int lun, u_int tag, role_t role, uint32_t status) |
7484 | { |
7485 | struct scb *scbp; |
7486 | struct scb *scbp_next; |
7487 | u_int i, j; |
7488 | u_int maxtarget; |
7489 | u_int minlun; |
7490 | u_int maxlun; |
7491 | int found; |
7492 | ahd_mode_state saved_modes; |
7493 | |
7494 | /* restore this when we're done */ |
7495 | saved_modes = ahd_save_modes(ahd); |
7496 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
7497 | |
7498 | found = ahd_search_qinfifo(ahd, target, channel, lun, SCB_LIST_NULL0xFF00, |
7499 | role, CAM_REQUEUE_REQ, SEARCH_COMPLETE); |
7500 | |
7501 | /* |
7502 | * Clean out the busy target table for any untagged commands. |
7503 | */ |
7504 | i = 0; |
7505 | maxtarget = 16; |
7506 | if (target != CAM_TARGET_WILDCARD((u_int)~0)) { |
7507 | i = target; |
7508 | if (channel == 'B') |
7509 | i += 8; |
7510 | maxtarget = i + 1; |
7511 | } |
7512 | |
7513 | if (lun == CAM_LUN_WILDCARD-1) { |
7514 | minlun = 0; |
7515 | maxlun = AHD_NUM_LUNS_NONPKT64; |
7516 | } else if (lun >= AHD_NUM_LUNS_NONPKT64) { |
7517 | minlun = maxlun = 0; |
7518 | } else { |
7519 | minlun = lun; |
7520 | maxlun = lun + 1; |
7521 | } |
7522 | |
7523 | if (role != ROLE_TARGET) { |
7524 | for (;i < maxtarget; i++) { |
7525 | for (j = minlun;j < maxlun; j++) { |
7526 | u_int scbid; |
7527 | u_int tcl; |
7528 | |
7529 | tcl = BUILD_TCL_RAW(i, 'A', j)((j) | ((i) << 8)); |
7530 | scbid = ahd_find_busy_tcl(ahd, tcl); |
7531 | scbp = ahd_lookup_scb(ahd, scbid); |
7532 | if (scbp == NULL((void *)0) |
7533 | || ahd_match_scb(ahd, scbp, target, channel, |
7534 | lun, tag, role) == 0) |
7535 | continue; |
7536 | ahd_unbusy_tcl(ahd, BUILD_TCL_RAW(i, 'A', j)((j) | ((i) << 8))); |
7537 | } |
7538 | } |
7539 | } |
7540 | |
7541 | /* |
7542 | * Don't abort commands that have already completed, |
7543 | * but haven't quite made it up to the host yet. |
7544 | */ |
7545 | ahd_flush_qoutfifo(ahd); |
7546 | |
7547 | /* |
7548 | * Go through the pending CCB list and look for |
7549 | * commands for this target that are still active. |
7550 | * These are other tagged commands that were |
7551 | * disconnected when the reset occurred. |
7552 | */ |
7553 | scbp_next = TAILQ_FIRST(&ahd->pending_scbs)((&ahd->pending_scbs)->tqh_first); |
7554 | while (scbp_next != NULL((void *)0)) { |
7555 | scbp = scbp_next; |
7556 | scbp_next = TAILQ_NEXT(scbp, next)((scbp)->next.tqe_next); |
7557 | if (ahd_match_scb(ahd, scbp, target, channel, lun, tag, role)) { |
7558 | cam_status ostat; |
7559 | |
7560 | ostat = aic_get_transaction_status(scbp)(((scbp)->xs->flags & 0x00008) ? CAM_REQ_CMP : (scbp )->xs->error); |
7561 | if (ostat == CAM_REQ_INPROG) |
7562 | aic_set_transaction_status(scbp, status)(scbp)->xs->error = (status); |
7563 | if (aic_get_transaction_status(scbp)(((scbp)->xs->flags & 0x00008) ? CAM_REQ_CMP : (scbp )->xs->error) != CAM_REQ_CMP) |
7564 | aic_freeze_scb(scbp); |
7565 | if ((scbp->flags & SCB_ACTIVE) == 0) |
7566 | printf("Inactive SCB on pending list\n"); |
7567 | ahd_done(ahd, scbp); |
7568 | found++; |
7569 | } |
7570 | } |
7571 | ahd_restore_modes(ahd, saved_modes); |
7572 | ahd->flags |= AHD_UPDATE_PEND_CMDS; |
7573 | return found; |
7574 | } |
7575 | |
7576 | void |
7577 | ahd_reset_current_bus(struct ahd_softc *ahd) |
7578 | { |
7579 | uint8_t scsiseq; |
7580 | |
7581 | 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", 7581);; |
7582 | ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) & ~ENSCSIRST)(((ahd)->tags[(0x57) >> 8])->write_1(((ahd)->bshs [(0x57) >> 8]), ((0x57) & 0xFF), ((((ahd)->tags[ (0x57) >> 8])->read_1(((ahd)->bshs[(0x57) >> 8]), ((0x57) & 0xFF))) & ~0x20))); |
7583 | scsiseq = ahd_inb(ahd, SCSISEQ0)(((ahd)->tags[(0x3a) >> 8])->read_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF))) & ~(ENSELO0x40|ENARBO0x20|SCSIRSTO0x01); |
7584 | ahd_outb(ahd, SCSISEQ0, scsiseq | SCSIRSTO)(((ahd)->tags[(0x3a) >> 8])->write_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF), (scsiseq | 0x01))); |
7585 | ahd_flush_device_writes(ahd); |
7586 | aic_delay(AHD_BUSRESET_DELAY)(*delay_func)(25); |
7587 | /* Turn off the bus reset */ |
7588 | ahd_outb(ahd, SCSISEQ0, scsiseq)(((ahd)->tags[(0x3a) >> 8])->write_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF), (scsiseq))); |
7589 | ahd_flush_device_writes(ahd); |
7590 | aic_delay(AHD_BUSRESET_DELAY)(*delay_func)(25); |
7591 | if ((ahd->bugs & AHD_SCSIRST_BUG) != 0) { |
7592 | /* |
7593 | * 2A Razor #474 |
7594 | * Certain chip state is not cleared for |
7595 | * SCSI bus resets that we initiate, so |
7596 | * we must reset the chip. |
7597 | */ |
7598 | ahd_reset(ahd, /*reinit*/TRUE1); |
7599 | ahd_intr_enable(ahd, /*enable*/TRUE1); |
7600 | 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", 7600);; |
7601 | } |
7602 | |
7603 | ahd_clear_intstat(ahd); |
7604 | } |
7605 | |
7606 | int |
7607 | ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) |
7608 | { |
7609 | u_int initiator; |
7610 | u_int target; |
7611 | u_int max_scsiid; |
7612 | int found; |
7613 | u_int fifo; |
7614 | u_int next_fifo; |
7615 | |
7616 | ahd->pending_device = NULL((void *)0); |
7617 | |
7618 | ahd_pause(ahd); |
7619 | |
7620 | /* Make sure the sequencer is in a safe location. */ |
7621 | ahd_clear_critical_section(ahd); |
7622 | |
7623 | #if AHD_TARGET_MODE |
7624 | if ((ahd->flags & AHD_TARGETROLE) != 0) { |
7625 | ahd_run_tqinfifo(ahd, /*paused*/TRUE1); |
7626 | } |
7627 | #endif |
7628 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
7629 | |
7630 | /* |
7631 | * Disable selections so no automatic hardware |
7632 | * functions will modify chip state. |
7633 | */ |
7634 | ahd_outb(ahd, SCSISEQ0, 0)(((ahd)->tags[(0x3a) >> 8])->write_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF), (0))); |
7635 | ahd_outb(ahd, SCSISEQ1, 0)(((ahd)->tags[(0x3b) >> 8])->write_1(((ahd)->bshs [(0x3b) >> 8]), ((0x3b) & 0xFF), (0))); |
7636 | |
7637 | /* |
7638 | * Safely shut down our DMA engines. Always start with |
7639 | * the FIFO that is not currently active (if any are |
7640 | * actively connected). |
7641 | */ |
7642 | next_fifo = fifo = ahd_inb(ahd, DFFSTAT)(((ahd)->tags[(0x3f) >> 8])->read_1(((ahd)->bshs [(0x3f) >> 8]), ((0x3f) & 0xFF))) & CURRFIFO0x03; |
7643 | if (next_fifo > CURRFIFO_10x01) |
7644 | /* If disconnected, arbitrarily start with FIFO1. */ |
7645 | next_fifo = fifo = 0; |
7646 | do { |
7647 | next_fifo ^= CURRFIFO_10x01; |
7648 | ahd_set_modes(ahd, next_fifo, next_fifo); |
7649 | ahd_outb(ahd, DFCNTRL,(((ahd)->tags[(0x19) >> 8])->write_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF), ((((ahd)->tags[ (0x19) >> 8])->read_1(((ahd)->bshs[(0x19) >> 8]), ((0x19) & 0xFF))) & ~(0x20|0x08)))) |
7650 | ahd_inb(ahd, DFCNTRL) & ~(SCSIEN|HDMAEN))(((ahd)->tags[(0x19) >> 8])->write_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF), ((((ahd)->tags[ (0x19) >> 8])->read_1(((ahd)->bshs[(0x19) >> 8]), ((0x19) & 0xFF))) & ~(0x20|0x08)))); |
7651 | while ((ahd_inb(ahd, DFCNTRL)(((ahd)->tags[(0x19) >> 8])->read_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF))) & HDMAENACK0x08) != 0) |
7652 | aic_delay(10)(*delay_func)(10); |
7653 | /* |
7654 | * Set CURRFIFO to the now inactive channel. |
7655 | */ |
7656 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
7657 | ahd_outb(ahd, DFFSTAT, next_fifo)(((ahd)->tags[(0x3f) >> 8])->write_1(((ahd)->bshs [(0x3f) >> 8]), ((0x3f) & 0xFF), (next_fifo))); |
7658 | } while (next_fifo != fifo); |
7659 | |
7660 | /* |
7661 | * Reset the bus if we are initiating this reset |
7662 | */ |
7663 | ahd_clear_msg_state(ahd); |
7664 | 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|0x20)))) |
7665 | ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST))(((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|0x20)))); |
7666 | |
7667 | if (initiate_reset) |
7668 | ahd_reset_current_bus(ahd); |
7669 | |
7670 | ahd_clear_intstat(ahd); |
7671 | |
7672 | /* |
7673 | * Clean up all the state information for the |
7674 | * pending transactions on this bus. |
7675 | */ |
7676 | found = ahd_abort_scbs(ahd, CAM_TARGET_WILDCARD((u_int)~0), channel, |
7677 | CAM_LUN_WILDCARD-1, SCB_LIST_NULL0xFF00, |
7678 | ROLE_UNKNOWN, CAM_SCSI_BUS_RESET); |
7679 | |
7680 | /* |
7681 | * Cleanup anything left in the FIFOs. |
7682 | */ |
7683 | ahd_clear_fifo(ahd, 0); |
7684 | ahd_clear_fifo(ahd, 1); |
7685 | |
7686 | /* |
7687 | * Revert to async/narrow transfers until we renegotiate. |
7688 | */ |
7689 | max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7; |
7690 | for (target = 0; target <= max_scsiid; target++) { |
7691 | |
7692 | if (ahd->enabled_targets[target] == NULL((void *)0)) |
7693 | continue; |
7694 | for (initiator = 0; initiator <= max_scsiid; initiator++) { |
7695 | struct ahd_devinfo devinfo; |
7696 | |
7697 | ahd_compile_devinfo(&devinfo, target, initiator, |
7698 | CAM_LUN_WILDCARD-1, |
7699 | 'A', ROLE_UNKNOWN); |
7700 | ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT0x00, |
7701 | AHD_TRANS_CUR0x01, /*paused*/TRUE1); |
7702 | ahd_set_syncrate(ahd, &devinfo, /*period*/0, |
7703 | /*offset*/0, /*ppr_options*/0, |
7704 | AHD_TRANS_CUR0x01, /*paused*/TRUE1); |
7705 | } |
7706 | } |
7707 | |
7708 | #ifdef AHD_TARGET_MODE |
7709 | max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7; |
7710 | |
7711 | /* |
7712 | * Send an immediate notify ccb to all target more peripheral |
7713 | * drivers affected by this action. |
7714 | */ |
7715 | for (target = 0; target <= max_scsiid; target++) { |
7716 | struct ahd_tmode_tstate* tstate; |
7717 | u_int lun; |
7718 | |
7719 | tstate = ahd->enabled_targets[target]; |
7720 | if (tstate == NULL((void *)0)) |
7721 | continue; |
7722 | for (lun = 0; lun < AHD_NUM_LUNS256; lun++) { |
7723 | struct ahd_tmode_lstate* lstate; |
7724 | |
7725 | lstate = tstate->enabled_luns[lun]; |
7726 | if (lstate == NULL((void *)0)) |
7727 | continue; |
7728 | |
7729 | ahd_queue_lstate_event(ahd, lstate, CAM_TARGET_WILDCARD((u_int)~0), |
7730 | EVENT_TYPE_BUS_RESET0xFF, /*arg*/0); |
7731 | ahd_send_lstate_events(ahd, lstate); |
7732 | } |
7733 | } |
7734 | #endif |
7735 | #if 0 |
7736 | /* Notify the XPT that a bus reset occurred */ |
7737 | ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD((u_int)~0), |
7738 | CAM_LUN_WILDCARD-1, AC_BUS_RESET, NULL((void *)0)); |
7739 | #endif |
7740 | ahd_restart(ahd); |
7741 | /* |
7742 | * Freeze the SIMQ until our poller can determine that |
7743 | * the bus reset has really gone away. We set the initial |
7744 | * timer to 0 to have the check performed as soon as possible |
7745 | * from the timer context. |
7746 | */ |
7747 | if ((ahd->flags & AHD_RESET_POLL_ACTIVE) == 0) { |
7748 | ahd->flags |= AHD_RESET_POLL_ACTIVE; |
7749 | aic_freeze_simq(ahd); |
7750 | aic_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd); |
7751 | } |
7752 | return (found); |
7753 | } |
7754 | |
7755 | |
7756 | #define AHD_RESET_POLL_MS1 1 |
7757 | void |
7758 | ahd_reset_poll(void *arg) |
7759 | { |
7760 | struct ahd_softc *ahd; |
7761 | u_int scsiseq1; |
7762 | int l; |
7763 | int s; |
7764 | |
7765 | ahd_list_lock(&l)*(&l) = splraise(0x3); |
7766 | ahd = ahd_find_softc((struct ahd_softc *)arg); |
7767 | if (ahd == NULL((void *)0)) { |
7768 | printf("ahd_reset_poll: Instance %p no longer exists\n", arg); |
7769 | ahd_list_unlock(&l)spllower(*(&l)); |
7770 | return; |
7771 | } |
7772 | ahd_lock(ahd, &s)*(&s) = splraise(0x3); |
7773 | ahd_pause(ahd); |
7774 | ahd_update_modes(ahd); |
7775 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
7776 | ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI)(((ahd)->tags[(0x4c) >> 8])->write_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF), (0x20))); |
7777 | if ((ahd_inb(ahd, SSTAT1)(((ahd)->tags[(0x4c) >> 8])->read_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF))) & SCSIRSTI0x20) != 0) { |
7778 | aic_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_MS1, |
7779 | ahd_reset_poll, ahd); |
7780 | ahd_unpause(ahd); |
7781 | ahd_unlock(ahd, &s)spllower(*(&s)); |
7782 | ahd_list_unlock(&l)spllower(*(&l)); |
7783 | return; |
7784 | } |
7785 | |
7786 | /* Reset is now low. Complete chip reinitialization. */ |
7787 | ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST)(((ahd)->tags[(0x57) >> 8])->write_1(((ahd)->bshs [(0x57) >> 8]), ((0x57) & 0xFF), ((((ahd)->tags[ (0x57) >> 8])->read_1(((ahd)->bshs[(0x57) >> 8]), ((0x57) & 0xFF))) | 0x20))); |
7788 | scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE)(((ahd)->tags[(0x14b) >> 8])->read_1(((ahd)->bshs [(0x14b) >> 8]), ((0x14b) & 0xFF))); |
7789 | ahd_outb(ahd, SCSISEQ1, scsiseq1 & (ENSELI|ENRSELI|ENAUTOATNP))(((ahd)->tags[(0x3b) >> 8])->write_1(((ahd)->bshs [(0x3b) >> 8]), ((0x3b) & 0xFF), (scsiseq1 & (0x20 |0x10|0x02)))); |
7790 | ahd_unpause(ahd); |
7791 | ahd->flags &= ~AHD_RESET_POLL_ACTIVE; |
7792 | ahd_unlock(ahd, &s)spllower(*(&s)); |
7793 | aic_release_simq(ahd); |
7794 | ahd_list_unlock(&l)spllower(*(&l)); |
7795 | } |
7796 | |
7797 | /**************************** Statistics Processing ***************************/ |
7798 | void |
7799 | ahd_stat_timer(void *arg) |
7800 | { |
7801 | struct ahd_softc *ahd; |
7802 | int l; |
7803 | int s; |
7804 | int enint_coal; |
7805 | |
7806 | ahd_list_lock(&l)*(&l) = splraise(0x3); |
7807 | ahd = ahd_find_softc((struct ahd_softc *)arg); |
7808 | if (ahd == NULL((void *)0)) { |
7809 | printf("ahd_stat_timer: Instance %p no longer exists\n", arg); |
7810 | ahd_list_unlock(&l)spllower(*(&l)); |
7811 | return; |
7812 | } |
7813 | ahd_lock(ahd, &s)*(&s) = splraise(0x3); |
7814 | |
7815 | enint_coal = ahd->hs_mailbox & ENINT_COALESCE0x40; |
7816 | if (ahd->cmdcmplt_total > ahd->int_coalescing_threshold) |
7817 | enint_coal |= ENINT_COALESCE0x40; |
7818 | else if (ahd->cmdcmplt_total < ahd->int_coalescing_stop_threshold) |
7819 | enint_coal &= ~ENINT_COALESCE0x40; |
7820 | |
7821 | if (enint_coal != (ahd->hs_mailbox & ENINT_COALESCE0x40)) { |
7822 | ahd_enable_coalescing(ahd, enint_coal); |
7823 | #ifdef AHD_DEBUG |
7824 | if ((ahd_debug & AHD_SHOW_INT_COALESCING) != 0) |
7825 | printf("%s: Interrupt coalescing " |
7826 | "now %sabled. Cmds %d\n", |
7827 | ahd_name(ahd), |
7828 | (enint_coal & ENINT_COALESCE0x40) ? "en" : "dis", |
7829 | ahd->cmdcmplt_total); |
7830 | #endif |
7831 | } |
7832 | |
7833 | ahd->cmdcmplt_bucket = (ahd->cmdcmplt_bucket+1) & (AHD_STAT_BUCKETS4-1); |
7834 | ahd->cmdcmplt_total -= ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]; |
7835 | ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket] = 0; |
7836 | aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_MS250, |
7837 | ahd_stat_timer, ahd); |
7838 | ahd_unlock(ahd, &s)spllower(*(&s)); |
7839 | ahd_list_unlock(&l)spllower(*(&l)); |
7840 | } |
7841 | |
7842 | /****************************** Status Processing *****************************/ |
7843 | void |
7844 | ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb) |
7845 | { |
7846 | if (scb->hscb->shared_data.istatus.scsi_status != 0) { |
7847 | ahd_handle_scsi_status(ahd, scb); |
7848 | } else { |
7849 | ahd_calc_residual(ahd, scb); |
7850 | ahd_done(ahd, scb); |
7851 | } |
7852 | } |
7853 | |
7854 | void |
7855 | ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) |
7856 | { |
7857 | struct hardware_scb *hscb; |
7858 | int paused; |
7859 | |
7860 | /* |
7861 | * The sequencer freezes its select-out queue |
7862 | * anytime a SCSI status error occurs. We must |
7863 | * handle the error and increment our qfreeze count |
7864 | * to allow the sequencer to continue. We don't |
7865 | * bother clearing critical sections here since all |
7866 | * operations are on data structures that the sequencer |
7867 | * is not touching once the queue is frozen. |
7868 | */ |
7869 | hscb = scb->hscb; |
7870 | |
7871 | if (ahd_is_paused(ahd)) { |
7872 | paused = 1; |
7873 | } else { |
7874 | paused = 0; |
7875 | ahd_pause(ahd); |
7876 | } |
7877 | |
7878 | /* Freeze the queue until the client sees the error. */ |
7879 | ahd_freeze_devq(ahd, scb); |
7880 | aic_freeze_scb(scb); |
7881 | ahd->qfreeze_cnt++; |
7882 | ahd_outw(ahd, KERNEL_QFREEZE_COUNT0x134, ahd->qfreeze_cnt); |
7883 | |
7884 | if (paused == 0) |
7885 | ahd_unpause(ahd); |
7886 | |
7887 | /* Don't want to clobber the original sense code */ |
7888 | if ((scb->flags & SCB_SENSE) != 0) { |
7889 | /* |
7890 | * Clear the SCB_SENSE Flag and perform |
7891 | * a normal command completion. |
7892 | */ |
7893 | scb->flags &= ~SCB_SENSE; |
7894 | aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL)(scb)->xs->error = (CAM_AUTOSENSE_FAIL); |
7895 | ahd_done(ahd, scb); |
7896 | return; |
7897 | } |
7898 | aic_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR)(scb)->xs->error = (CAM_SCSI_STATUS_ERROR); |
7899 | aic_set_scsi_status(scb, hscb->shared_data.istatus.scsi_status)(scb)->xs->status = (hscb->shared_data.istatus.scsi_status ); |
7900 | switch (hscb->shared_data.istatus.scsi_status) { |
7901 | case STATUS_PKT_SENSE0xff: |
7902 | { |
7903 | struct scsi_status_iu_header *siu; |
7904 | |
7905 | ahd_sync_sense(ahd, scb, BUS_DMASYNC_POSTREAD0x02); |
7906 | siu = (struct scsi_status_iu_header *)scb->sense_data; |
7907 | aic_set_scsi_status(scb, siu->status)(scb)->xs->status = (siu->status); |
7908 | #ifdef AHD_DEBUG |
7909 | if ((ahd_debug & AHD_SHOW_SENSE) != 0) { |
7910 | ahd_print_path(ahd, scb); |
7911 | printf("SCB 0x%x Received PKT Status of 0x%x\n", |
7912 | SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)), siu->status); |
7913 | printf("\tflags = 0x%x, sense len = 0x%x, " |
7914 | "pktfail = 0x%x\n", |
7915 | siu->flags, scsi_4btoul(siu->sense_length)(_4btol(siu->sense_length)), |
7916 | scsi_4btoul(siu->pkt_failures_length)(_4btol(siu->pkt_failures_length))); |
7917 | } |
7918 | #endif |
7919 | if ((siu->flags & SIU_RSPVALID0x1) != 0) { |
7920 | ahd_print_path(ahd, scb); |
7921 | if (scsi_4btoul(siu->pkt_failures_length)(_4btol(siu->pkt_failures_length)) < 4) { |
7922 | printf("Unable to parse pkt_failures\n"); |
7923 | } else { |
7924 | |
7925 | switch (SIU_PKTFAIL_CODE(siu)((siu)->data[3])) { |
7926 | case SIU_PFC_NONE0x00: |
7927 | printf("No packet failure found\n"); |
7928 | break; |
7929 | case SIU_PFC_CIU_FIELDS_INVALID0x02: |
7930 | printf("Invalid Command IU Field\n"); |
7931 | break; |
7932 | case SIU_PFC_TMF_NOT_SUPPORTED0x04: |
7933 | printf("TMF not supported\n"); |
7934 | break; |
7935 | case SIU_PFC_TMF_FAILED0x05: |
7936 | printf("TMF failed\n"); |
7937 | break; |
7938 | case SIU_PFC_INVALID_TYPE_CODE0x06: |
7939 | printf("Invalid L_Q Type code\n"); |
7940 | break; |
7941 | case SIU_PFC_ILLEGAL_REQUEST0x07: |
7942 | printf("Illegal request\n"); |
7943 | default: |
7944 | break; |
7945 | } |
7946 | } |
7947 | if (siu->status == SCSI_STATUS_OK0x00) |
7948 | aic_set_transaction_status(scb,(scb)->xs->error = (CAM_REQ_CMP_ERR) |
7949 | CAM_REQ_CMP_ERR)(scb)->xs->error = (CAM_REQ_CMP_ERR); |
7950 | } |
7951 | if ((siu->flags & SIU_SNSVALID0x2) != 0) { |
7952 | scb->flags |= SCB_PKT_SENSE; |
7953 | #ifdef AHD_DEBUG |
7954 | if ((ahd_debug & AHD_SHOW_SENSE) != 0) |
7955 | printf("Sense data available\n"); |
7956 | #endif |
7957 | } |
7958 | ahd_done(ahd, scb); |
7959 | break; |
7960 | } |
7961 | case SCSI_STATUS_CMD_TERMINATED0x22: |
7962 | case SCSI_STATUS_CHECK_COND0x02: |
7963 | { |
7964 | struct ahd_devinfo devinfo; |
7965 | struct ahd_dma_seg *sg; |
7966 | struct scsi_sense *sc; |
7967 | struct ahd_initiator_tinfo *targ_info; |
7968 | struct ahd_tmode_tstate *tstate; |
7969 | struct ahd_transinfo *tinfo; |
7970 | #ifdef AHD_DEBUG |
7971 | if (ahd_debug & AHD_SHOW_SENSE) { |
7972 | ahd_print_path(ahd, scb); |
7973 | printf("SCB %d: requests Check Status\n", |
7974 | SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag))); |
7975 | } |
7976 | #endif |
7977 | |
7978 | if (aic_perform_autosense(scb)(1) == 0) |
7979 | break; |
7980 | |
7981 | ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb)(((scb)->hscb->scsiid) & 0x0f), |
7982 | SCB_GET_TARGET(ahd, scb)((((scb)->hscb->scsiid) & 0xf0) >> 0x04), |
7983 | SCB_GET_LUN(scb)((scb)->hscb->lun), |
7984 | SCB_GET_CHANNEL(ahd, scb)('A'), |
7985 | ROLE_INITIATOR); |
7986 | targ_info = ahd_fetch_transinfo(ahd, |
7987 | devinfo.channel, |
7988 | devinfo.our_scsiid, |
7989 | devinfo.target, |
7990 | &tstate); |
7991 | tinfo = &targ_info->curr; |
7992 | sg = scb->sg_list; |
7993 | sc = (struct scsi_sense *)hscb->shared_data.idata.cdb; |
7994 | /* |
7995 | * Save off the residual if there is one. |
7996 | */ |
7997 | ahd_update_residual(ahd, scb); |
7998 | #ifdef AHD_DEBUG |
7999 | if (ahd_debug & AHD_SHOW_SENSE) { |
8000 | ahd_print_path(ahd, scb); |
8001 | printf("Sending Sense\n"); |
8002 | } |
8003 | #endif |
8004 | scb->sg_count = 0; |
8005 | sg = ahd_sg_setup(ahd, scb, sg, ahd_get_sense_bufaddr(ahd, scb), |
8006 | aic_get_sense_bufsize(ahd, scb)(sizeof(struct scsi_sense_data)), |
8007 | /*last*/TRUE1); |
8008 | sc->opcode = REQUEST_SENSE0x03; |
8009 | sc->byte2 = 0; |
8010 | if (tinfo->protocol_version <= SCSI_REV_20x02 |
8011 | && SCB_GET_LUN(scb)((scb)->hscb->lun) < 8) |
8012 | sc->byte2 = SCB_GET_LUN(scb)((scb)->hscb->lun) << 5; |
8013 | sc->unused[0] = 0; |
8014 | sc->unused[1] = 0; |
8015 | sc->length = aic_get_sense_bufsize(ahd, scb)(sizeof(struct scsi_sense_data)); |
8016 | sc->control = 0; |
8017 | |
8018 | /* |
8019 | * We can't allow the target to disconnect. |
8020 | * This will be an untagged transaction and |
8021 | * having the target disconnect will make this |
8022 | * transaction indistinguishable from outstanding |
8023 | * tagged transactions. |
8024 | */ |
8025 | hscb->control = 0; |
8026 | |
8027 | /* |
8028 | * This request sense could be because the |
8029 | * the device lost power or in some other |
8030 | * way has lost our transfer negotiations. |
8031 | * Renegotiate if appropriate. Unit attention |
8032 | * errors will be reported before any data |
8033 | * phases occur. |
8034 | */ |
8035 | if (aic_get_residual(scb)((scb)->xs->resid) == aic_get_transfer_length(scb)((scb)->xs->datalen)) { |
8036 | ahd_update_neg_request(ahd, &devinfo, |
8037 | tstate, targ_info, |
8038 | AHD_NEG_IF_NON_ASYNC); |
8039 | } |
8040 | if (tstate->auto_negotiate & devinfo.target_mask) { |
8041 | hscb->control |= MK_MESSAGE0x10; |
8042 | scb->flags &= |
8043 | ~(SCB_NEGOTIATE|SCB_ABORT|SCB_DEVICE_RESET); |
8044 | scb->flags |= SCB_AUTO_NEGOTIATE; |
8045 | } |
8046 | hscb->cdb_len = sizeof(*sc); |
8047 | ahd_setup_data_scb(ahd, scb); |
8048 | scb->flags |= SCB_SENSE; |
8049 | ahd_queue_scb(ahd, scb); |
8050 | /* |
8051 | * Ensure we have enough time to actually |
8052 | * retrieve the sense, but only schedule |
8053 | * the timer if we are not in recovery or |
8054 | * this is a recovery SCB that is allowed |
8055 | * to have an active timer. |
8056 | */ |
8057 | aic_scb_timer_reset(scb, 5 * 1000); |
8058 | break; |
8059 | } |
8060 | case SCSI_STATUS_OK0x00: |
8061 | printf("%s: Interrupted for status of 0???\n", |
8062 | ahd_name(ahd)); |
8063 | /* FALLTHROUGH */ |
8064 | default: |
8065 | ahd_done(ahd, scb); |
8066 | break; |
8067 | } |
8068 | } |
8069 | |
8070 | /* |
8071 | * Calculate the residual for a just completed SCB. |
8072 | */ |
8073 | void |
8074 | ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb) |
8075 | { |
8076 | struct hardware_scb *hscb; |
8077 | struct initiator_status *spkt; |
8078 | uint32_t sgptr; |
8079 | uint32_t resid_sgptr; |
8080 | uint32_t resid; |
8081 | |
8082 | /* |
8083 | * 5 cases. |
8084 | * 1) No residual. |
8085 | * SG_STATUS_VALID clear in sgptr. |
8086 | * 2) Transferless command |
8087 | * 3) Never performed any transfers. |
8088 | * sgptr has SG_FULL_RESID set. |
8089 | * 4) No residual but target did not |
8090 | * save data pointers after the |
8091 | * last transfer, so sgptr was |
8092 | * never updated. |
8093 | * 5) We have a partial residual. |
8094 | * Use residual_sgptr to determine |
8095 | * where we are. |
8096 | */ |
8097 | |
8098 | hscb = scb->hscb; |
8099 | sgptr = aic_le32toh(hscb->sgptr)((__uint32_t)(hscb->sgptr)); |
8100 | if ((sgptr & SG_STATUS_VALID0x04) == 0) |
8101 | /* Case 1 */ |
8102 | return; |
8103 | sgptr &= ~SG_STATUS_VALID0x04; |
8104 | |
8105 | if ((sgptr & SG_LIST_NULL0x01) != 0) |
8106 | /* Case 2 */ |
8107 | return; |
8108 | |
8109 | /* |
8110 | * Residual fields are the same in both |
8111 | * target and initiator status packets, |
8112 | * so we can always use the initiator fields |
8113 | * regardless of the role for this SCB. |
8114 | */ |
8115 | spkt = &hscb->shared_data.istatus; |
8116 | resid_sgptr = aic_le32toh(spkt->residual_sgptr)((__uint32_t)(spkt->residual_sgptr)); |
8117 | if ((sgptr & SG_FULL_RESID0x02) != 0) { |
8118 | /* Case 3 */ |
8119 | resid = aic_get_transfer_length(scb)((scb)->xs->datalen); |
8120 | } else if ((resid_sgptr & SG_LIST_NULL0x01) != 0) { |
8121 | /* Case 4 */ |
8122 | return; |
8123 | } else if ((resid_sgptr & SG_OVERRUN_RESID0x02) != 0) { |
8124 | ahd_print_path(ahd, scb); |
8125 | printf("data overrun detected Tag == 0x%x.\n", |
8126 | SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag))); |
8127 | ahd_freeze_devq(ahd, scb); |
8128 | aic_set_transaction_status(scb, CAM_DATA_RUN_ERR)(scb)->xs->error = (CAM_DATA_RUN_ERR); |
8129 | aic_freeze_scb(scb); |
8130 | return; |
8131 | } else if ((resid_sgptr & ~SG_PTR_MASK0xFFFFFFF8) != 0) { |
8132 | panic("Bogus resid sgptr value 0x%x", resid_sgptr); |
8133 | /* NOTREACHED */ |
8134 | } else { |
8135 | struct ahd_dma_seg *sg; |
8136 | |
8137 | /* |
8138 | * Remainder of the SG where the transfer |
8139 | * stopped. |
8140 | */ |
8141 | resid = aic_le32toh(spkt->residual_datacnt)((__uint32_t)(spkt->residual_datacnt)) & AHD_SG_LEN_MASK0x00FFFFFF; |
8142 | sg = ahd_sg_bus_to_virt(ahd, scb, resid_sgptr & SG_PTR_MASK0xFFFFFFF8); |
8143 | |
8144 | /* The residual sg_ptr always points to the next sg */ |
8145 | sg--; |
8146 | |
8147 | /* |
8148 | * Add up the contents of all residual |
8149 | * SG segments that are after the SG where |
8150 | * the transfer stopped. |
8151 | */ |
8152 | while ((aic_le32toh(sg->len)((__uint32_t)(sg->len)) & AHD_DMA_LAST_SEG0x80000000) == 0) { |
8153 | sg++; |
8154 | resid += aic_le32toh(sg->len)((__uint32_t)(sg->len)) & AHD_SG_LEN_MASK0x00FFFFFF; |
8155 | } |
8156 | } |
8157 | if ((scb->flags & SCB_SENSE) == 0) |
8158 | aic_set_residual(scb, resid)(scb)->xs->resid = (resid); |
8159 | else |
8160 | aic_set_sense_residual(scb, resid)(scb)->xs->resid = (resid); |
8161 | |
8162 | #ifdef AHD_DEBUG |
8163 | if ((ahd_debug & AHD_SHOW_MISC) != 0) { |
8164 | ahd_print_path(ahd, scb); |
8165 | printf("Handled %sResidual of %d bytes\n", |
8166 | (scb->flags & SCB_SENSE) ? "Sense " : "", resid); |
8167 | } |
8168 | #endif |
8169 | } |
8170 | |
8171 | /******************************* Target Mode **********************************/ |
8172 | #ifdef AHD_TARGET_MODE |
8173 | /* |
8174 | * Add a target mode event to this lun's queue |
8175 | */ |
8176 | void |
8177 | ahd_queue_lstate_event(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate, |
8178 | u_int initiator_id, u_int event_type, u_int event_arg) |
8179 | { |
8180 | struct ahd_tmode_event *event; |
8181 | int pending; |
8182 | |
8183 | xpt_freeze_devq(lstate->path, /*count*/1); |
8184 | if (lstate->event_w_idx >= lstate->event_r_idx) |
8185 | pending = lstate->event_w_idx - lstate->event_r_idx; |
8186 | else |
8187 | pending = AHD_TMODE_EVENT_BUFFER_SIZE8 + 1 |
8188 | - (lstate->event_r_idx - lstate->event_w_idx); |
8189 | |
8190 | if (event_type == EVENT_TYPE_BUS_RESET0xFF |
8191 | || event_type == MSG_BUS_DEV_RESET0x0c) { |
8192 | /* |
8193 | * Any earlier events are irrelevant, so reset our buffer. |
8194 | * This has the effect of allowing us to deal with reset |
8195 | * floods (an external device holding down the reset line) |
8196 | * without losing the event that is really interesting. |
8197 | */ |
8198 | lstate->event_r_idx = 0; |
8199 | lstate->event_w_idx = 0; |
8200 | xpt_release_devq(lstate->path, pending, /*runqueue*/FALSE0); |
8201 | } |
8202 | |
8203 | if (pending == AHD_TMODE_EVENT_BUFFER_SIZE8) { |
8204 | xpt_print_path(lstate->path); |
8205 | printf("immediate event %x:%x lost\n", |
8206 | lstate->event_buffer[lstate->event_r_idx].event_type, |
8207 | lstate->event_buffer[lstate->event_r_idx].event_arg); |
8208 | lstate->event_r_idx++; |
8209 | if (lstate->event_r_idx == AHD_TMODE_EVENT_BUFFER_SIZE8) |
8210 | lstate->event_r_idx = 0; |
8211 | xpt_release_devq(lstate->path, /*count*/1, /*runqueue*/FALSE0); |
8212 | } |
8213 | |
8214 | event = &lstate->event_buffer[lstate->event_w_idx]; |
8215 | event->initiator_id = initiator_id; |
8216 | event->event_type = event_type; |
8217 | event->event_arg = event_arg; |
8218 | lstate->event_w_idx++; |
8219 | if (lstate->event_w_idx == AHD_TMODE_EVENT_BUFFER_SIZE8) |
8220 | lstate->event_w_idx = 0; |
8221 | } |
8222 | |
8223 | /* |
8224 | * Send any target mode events queued up waiting |
8225 | * for immediate notify resources. |
8226 | */ |
8227 | void |
8228 | ahd_send_lstate_events(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate) |
8229 | { |
8230 | struct ccb_hdr *ccbh; |
8231 | struct ccb_immed_notify *inot; |
8232 | |
8233 | while (lstate->event_r_idx != lstate->event_w_idx |
8234 | && (ccbh = SLIST_FIRST(&lstate->immed_notifies)((&lstate->immed_notifies)->slh_first)) != NULL((void *)0)) { |
8235 | struct ahd_tmode_event *event; |
8236 | |
8237 | event = &lstate->event_buffer[lstate->event_r_idx]; |
8238 | SLIST_REMOVE_HEAD(&lstate->immed_notifies, sim_links.sle)do { (&lstate->immed_notifies)->slh_first = (&lstate ->immed_notifies)->slh_first->sim_links.sle.sle_next ; } while (0); |
8239 | inot = (struct ccb_immed_notify *)ccbh; |
8240 | switch (event->event_type) { |
8241 | case EVENT_TYPE_BUS_RESET0xFF: |
8242 | ccbh->status = CAM_SCSI_BUS_RESET|CAM_DEV_QFRZN; |
8243 | break; |
8244 | default: |
8245 | ccbh->status = CAM_MESSAGE_RECV|CAM_DEV_QFRZN; |
8246 | inot->message_args[0] = event->event_type; |
8247 | inot->message_args[1] = event->event_arg; |
8248 | break; |
8249 | } |
8250 | inot->initiator_id = event->initiator_id; |
8251 | inot->sense_len = 0; |
8252 | xpt_done((union ccb *)inot); |
8253 | lstate->event_r_idx++; |
8254 | if (lstate->event_r_idx == AHD_TMODE_EVENT_BUFFER_SIZE8) |
8255 | lstate->event_r_idx = 0; |
8256 | } |
8257 | } |
8258 | #endif |
8259 | |
8260 | /******************** Sequencer Program Patching/Download *********************/ |
8261 | |
8262 | #ifdef AHD_DUMP_SEQ |
8263 | void |
8264 | ahd_dumpseq(struct ahd_softc* ahd) |
8265 | { |
8266 | int i; |
8267 | int max_prog; |
8268 | |
8269 | max_prog = 2048; |
8270 | |
8271 | ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM)(((ahd)->tags[(0xd6) >> 8])->write_1(((ahd)->bshs [(0xd6) >> 8]), ((0xd6) & 0xFF), (0x80|0x20|0x10|0x01 ))); |
8272 | ahd_outw(ahd, PRGMCNT0xde, 0); |
8273 | for (i = 0; i < max_prog; i++) { |
8274 | uint8_t ins_bytes[4]; |
8275 | |
8276 | ahd_insb(ahd, SEQRAM, ins_bytes, 4)(((ahd)->tags[(0xda) >> 8])->read_multi_1(((ahd)-> bshs[(0xda) >> 8]), ((0xda & 0xFF)), (ins_bytes), ( 4))); |
8277 | printf("0x%08x\n", ins_bytes[0] << 24 |
8278 | | ins_bytes[1] << 16 |
8279 | | ins_bytes[2] << 8 |
8280 | | ins_bytes[3]); |
8281 | } |
8282 | } |
8283 | #endif |
8284 | |
8285 | void |
8286 | ahd_loadseq(struct ahd_softc *ahd) |
8287 | { |
8288 | struct cs cs_table[NUM_CRITICAL_SECTIONS(sizeof(critical_sections) / sizeof(*critical_sections))]; |
8289 | u_int begin_set[NUM_CRITICAL_SECTIONS(sizeof(critical_sections) / sizeof(*critical_sections))]; |
8290 | u_int end_set[NUM_CRITICAL_SECTIONS(sizeof(critical_sections) / sizeof(*critical_sections))]; |
8291 | const struct patch *cur_patch; |
8292 | u_int cs_count; |
8293 | u_int cur_cs; |
8294 | u_int i; |
8295 | int downloaded; |
8296 | u_int skip_addr; |
8297 | u_int sg_prefetch_cnt; |
8298 | u_int sg_prefetch_cnt_limit; |
8299 | u_int sg_prefetch_align; |
8300 | u_int sg_size; |
8301 | u_int cacheline_mask; |
8302 | uint8_t download_consts[DOWNLOAD_CONST_COUNT0x08]; |
8303 | |
8304 | if (bootverbose0) |
8305 | printf("%s: Downloading Sequencer Program...", |
8306 | ahd_name(ahd)); |
8307 | |
8308 | #if DOWNLOAD_CONST_COUNT0x08 != 8 |
8309 | #error "Download Const Mismatch" |
8310 | #endif |
8311 | /* |
8312 | * Start out with 0 critical sections |
8313 | * that apply to this firmware load. |
8314 | */ |
8315 | cs_count = 0; |
8316 | cur_cs = 0; |
8317 | memset(begin_set, 0, sizeof(begin_set))__builtin_memset((begin_set), (0), (sizeof(begin_set))); |
8318 | memset(end_set, 0, sizeof(end_set))__builtin_memset((end_set), (0), (sizeof(end_set))); |
8319 | |
8320 | /* |
8321 | * Setup downloadable constant table. |
8322 | * |
8323 | * The computation for the S/G prefetch variables is |
8324 | * a bit complicated. We would like to always fetch |
8325 | * in terms of cachelined sized increments. However, |
8326 | * if the cacheline is not an even multiple of the |
8327 | * SG element size or is larger than our SG RAM, using |
8328 | * just the cache size might leave us with only a portion |
8329 | * of an SG element at the tail of a prefetch. If the |
8330 | * cacheline is larger than our S/G prefetch buffer less |
8331 | * the size of an SG element, we may round down to a cacheline |
8332 | * that doesn't contain any or all of the S/G of interest |
8333 | * within the bounds of our S/G ram. Provide variables to |
8334 | * the sequencer that will allow it to handle these edge |
8335 | * cases. |
8336 | */ |
8337 | /* Start by aligning to the nearest cacheline. */ |
8338 | sg_prefetch_align = ahd->pci_cachesize; |
8339 | if (sg_prefetch_align == 0) |
8340 | sg_prefetch_align = 8; |
8341 | /* Round down to the nearest power of 2. */ |
8342 | while (powerof2(sg_prefetch_align)((((sg_prefetch_align)-1)&(sg_prefetch_align))==0) == 0) |
8343 | sg_prefetch_align--; |
8344 | |
8345 | cacheline_mask = sg_prefetch_align - 1; |
8346 | |
8347 | /* |
8348 | * If the cacheline boundary is greater than half our prefetch RAM |
8349 | * we risk not being able to fetch even a single complete S/G |
8350 | * segment if we align to that boundary. |
8351 | */ |
8352 | if (sg_prefetch_align > CCSGADDR_MAX0x80/2) |
8353 | sg_prefetch_align = CCSGADDR_MAX0x80/2; |
8354 | /* Start by fetching a single cacheline. */ |
8355 | sg_prefetch_cnt = sg_prefetch_align; |
8356 | /* |
8357 | * Increment the prefetch count by cachelines until |
8358 | * at least one S/G element will fit. |
8359 | */ |
8360 | sg_size = sizeof(struct ahd_dma_seg); |
8361 | if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) |
8362 | sg_size = sizeof(struct ahd_dma64_seg); |
8363 | while (sg_prefetch_cnt < sg_size) |
8364 | sg_prefetch_cnt += sg_prefetch_align; |
8365 | /* |
8366 | * If the cacheline is not an even multiple of |
8367 | * the S/G size, we may only get a partial S/G when |
8368 | * we align. Add a cacheline if this is the case. |
8369 | */ |
8370 | if ((sg_prefetch_align % sg_size) != 0 |
8371 | && (sg_prefetch_cnt < CCSGADDR_MAX0x80)) |
8372 | sg_prefetch_cnt += sg_prefetch_align; |
8373 | /* |
8374 | * Lastly, compute a value that the sequencer can use |
8375 | * to determine if the remainder of the CCSGRAM buffer |
8376 | * has a full S/G element in it. |
8377 | */ |
8378 | sg_prefetch_cnt_limit = -(sg_prefetch_cnt - sg_size + 1); |
8379 | download_consts[SG_PREFETCH_CNT0x00] = sg_prefetch_cnt; |
8380 | download_consts[SG_PREFETCH_CNT_LIMIT0x01] = sg_prefetch_cnt_limit; |
8381 | download_consts[SG_PREFETCH_ALIGN_MASK0x02] = ~(sg_prefetch_align - 1); |
8382 | download_consts[SG_PREFETCH_ADDR_MASK0x03] = (sg_prefetch_align - 1); |
8383 | download_consts[SG_SIZEOF0x04] = sg_size; |
8384 | download_consts[PKT_OVERRUN_BUFOFFSET0x05] = |
8385 | (ahd->overrun_buf - (uint8_t *)ahd->qoutfifo) / 256; |
8386 | download_consts[SCB_TRANSFER_SIZE0x06] = SCB_TRANSFER_SIZE_1BYTE_LUN0x30; |
8387 | download_consts[CACHELINE_MASK0x07] = cacheline_mask; |
8388 | cur_patch = patches; |
8389 | downloaded = 0; |
8390 | skip_addr = 0; |
8391 | ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM)(((ahd)->tags[(0xd6) >> 8])->write_1(((ahd)->bshs [(0xd6) >> 8]), ((0xd6) & 0xFF), (0x80|0x20|0x10|0x01 ))); |
8392 | ahd_outw(ahd, PRGMCNT0xde, 0); |
8393 | |
8394 | for (i = 0; i < sizeof(seqprog)/4; i++) { |
8395 | if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) { |
8396 | /* |
8397 | * Don't download this instruction as it |
8398 | * is in a patch that was removed. |
8399 | */ |
8400 | continue; |
8401 | } |
8402 | /* |
8403 | * Move through the CS table until we find a CS |
8404 | * that might apply to this instruction. |
8405 | */ |
8406 | for (; cur_cs < NUM_CRITICAL_SECTIONS(sizeof(critical_sections) / sizeof(*critical_sections)); cur_cs++) { |
8407 | if (critical_sections[cur_cs].end <= i) { |
8408 | if (begin_set[cs_count] == TRUE1 |
8409 | && end_set[cs_count] == FALSE0) { |
8410 | cs_table[cs_count].end = downloaded; |
8411 | end_set[cs_count] = TRUE1; |
8412 | cs_count++; |
8413 | } |
8414 | continue; |
8415 | } |
8416 | if (critical_sections[cur_cs].begin <= i |
8417 | && begin_set[cs_count] == FALSE0) { |
8418 | cs_table[cs_count].begin = downloaded; |
8419 | begin_set[cs_count] = TRUE1; |
8420 | } |
8421 | break; |
8422 | } |
8423 | ahd_download_instr(ahd, i, download_consts); |
8424 | downloaded++; |
8425 | } |
8426 | |
8427 | ahd->num_critical_sections = cs_count; |
8428 | if (cs_count != 0) { |
8429 | ahd->critical_sections = mallocarray(cs_count, |
8430 | sizeof(struct cs), M_DEVBUF2, M_NOWAIT0x0002); |
8431 | if (ahd->critical_sections == NULL((void *)0)) |
8432 | panic("ahd_loadseq: Could not malloc"); |
8433 | cs_count *= sizeof(struct cs); |
8434 | |
8435 | memcpy(ahd->critical_sections, cs_table, cs_count)__builtin_memcpy((ahd->critical_sections), (cs_table), (cs_count )); |
8436 | } |
8437 | ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE)(((ahd)->tags[(0xd6) >> 8])->write_1(((ahd)->bshs [(0xd6) >> 8]), ((0xd6) & 0xFF), (0x80|0x20|0x10))); |
8438 | |
8439 | if (bootverbose0) { |
8440 | printf(" %d instructions downloaded\n", downloaded); |
8441 | printf("%s: Features 0x%x, Bugs 0x%x, Flags 0x%x\n", |
8442 | ahd_name(ahd), ahd->features, ahd->bugs, ahd->flags); |
8443 | } |
8444 | } |
8445 | |
8446 | int |
8447 | ahd_check_patch(struct ahd_softc *ahd, const struct patch **start_patch, |
8448 | u_int start_instr, u_int *skip_addr) |
8449 | { |
8450 | const struct patch *cur_patch; |
8451 | const struct patch *last_patch; |
8452 | u_int num_patches; |
8453 | |
8454 | num_patches = sizeof(patches)/sizeof(struct patch); |
8455 | last_patch = &patches[num_patches]; |
8456 | cur_patch = *start_patch; |
8457 | |
8458 | while (cur_patch < last_patch && start_instr == cur_patch->begin) { |
8459 | |
8460 | if (cur_patch->patch_func(ahd) == 0) { |
8461 | |
8462 | /* Start rejecting code */ |
8463 | *skip_addr = start_instr + cur_patch->skip_instr; |
8464 | cur_patch += cur_patch->skip_patch; |
8465 | } else { |
8466 | /* Accepted this patch. Advance to the next |
8467 | * one and wait for our instruction pointer to |
8468 | * hit this point. |
8469 | */ |
8470 | cur_patch++; |
8471 | } |
8472 | } |
8473 | |
8474 | *start_patch = cur_patch; |
8475 | if (start_instr < *skip_addr) |
8476 | /* Still skipping */ |
8477 | return (0); |
8478 | |
8479 | return (1); |
8480 | } |
8481 | |
8482 | u_int |
8483 | ahd_resolve_seqaddr(struct ahd_softc *ahd, u_int address) |
8484 | { |
8485 | const struct patch *cur_patch; |
8486 | int address_offset; |
8487 | u_int skip_addr; |
8488 | u_int i; |
8489 | |
8490 | address_offset = 0; |
8491 | cur_patch = patches; |
8492 | skip_addr = 0; |
8493 | |
8494 | for (i = 0; i < address;) { |
8495 | |
8496 | ahd_check_patch(ahd, &cur_patch, i, &skip_addr); |
8497 | |
8498 | if (skip_addr > i) { |
8499 | int end_addr; |
8500 | |
8501 | end_addr = MIN(address, skip_addr)(((address)<(skip_addr))?(address):(skip_addr)); |
8502 | address_offset += end_addr - i; |
8503 | i = skip_addr; |
8504 | } else { |
8505 | i++; |
8506 | } |
8507 | } |
8508 | return (address - address_offset); |
8509 | } |
8510 | |
8511 | void |
8512 | ahd_download_instr(struct ahd_softc *ahd, u_int instrptr, uint8_t *dconsts) |
8513 | { |
8514 | union ins_formats instr; |
8515 | struct ins_format1 *fmt1_ins; |
8516 | struct ins_format3 *fmt3_ins; |
8517 | u_int opcode; |
8518 | |
8519 | /* |
8520 | * The firmware is always compiled into a little endian format. |
8521 | */ |
8522 | instr.integer = aic_le32toh(*(uint32_t*)&seqprog[instrptr * 4])((__uint32_t)(*(uint32_t*)&seqprog[instrptr * 4])); |
8523 | |
8524 | fmt1_ins = &instr.format1; |
8525 | fmt3_ins = NULL((void *)0); |
8526 | |
8527 | /* Pull the opcode */ |
8528 | opcode = instr.format1.opcode; |
8529 | switch (opcode) { |
8530 | case AIC_OP_JMP0x8: |
8531 | case AIC_OP_JC0x9: |
8532 | case AIC_OP_JNC0xa: |
8533 | case AIC_OP_CALL0xb: |
8534 | case AIC_OP_JNE0xc: |
8535 | case AIC_OP_JNZ0xd: |
8536 | case AIC_OP_JE0xe: |
8537 | case AIC_OP_JZ0xf: |
8538 | { |
8539 | fmt3_ins = &instr.format3; |
8540 | fmt3_ins->address = ahd_resolve_seqaddr(ahd, fmt3_ins->address); |
8541 | /* FALLTHROUGH */ |
8542 | } |
8543 | case AIC_OP_OR0x0: |
8544 | case AIC_OP_AND0x1: |
8545 | case AIC_OP_XOR0x2: |
8546 | case AIC_OP_ADD0x3: |
8547 | case AIC_OP_ADC0x4: |
8548 | case AIC_OP_BMOV0x6: |
8549 | if (fmt1_ins->parity != 0) { |
8550 | fmt1_ins->immediate = dconsts[fmt1_ins->immediate]; |
8551 | } |
8552 | fmt1_ins->parity = 0; |
8553 | /* FALLTHROUGH */ |
8554 | case AIC_OP_ROL0x5: |
8555 | { |
8556 | int i, count; |
8557 | |
8558 | /* Calculate odd parity for the instruction */ |
8559 | for (i = 0, count = 0; i < 31; i++) { |
8560 | uint32_t mask; |
8561 | |
8562 | mask = 0x01 << i; |
8563 | if ((instr.integer & mask) != 0) |
8564 | count++; |
8565 | } |
8566 | if ((count & 0x01) == 0) |
8567 | instr.format1.parity = 1; |
8568 | |
8569 | /* The sequencer is a little endian cpu */ |
8570 | instr.integer = aic_htole32(instr.integer)((__uint32_t)(instr.integer)); |
8571 | ahd_outsb(ahd, SEQRAM, instr.bytes, 4)(((ahd)->tags[(0xda) >> 8])->write_multi_1(((ahd) ->bshs[(0xda) >> 8]), ((0xda & 0xFF)), (instr.bytes ), (4))); |
8572 | break; |
8573 | } |
8574 | default: |
8575 | panic("Unknown opcode encountered in seq program"); |
8576 | break; |
8577 | } |
8578 | } |
8579 | |
8580 | int |
8581 | ahd_probe_stack_size(struct ahd_softc *ahd) |
8582 | { |
8583 | int last_probe; |
8584 | |
8585 | last_probe = 0; |
8586 | while (1) { |
8587 | int i; |
8588 | |
8589 | /* |
8590 | * We avoid using 0 as a pattern to avoid |
8591 | * confusion if the stack implementation |
8592 | * "back-fills" with zeros when "poping' |
8593 | * entries. |
8594 | */ |
8595 | for (i = 1; i <= last_probe+1; i++) { |
8596 | ahd_outb(ahd, STACK, i & 0xFF)(((ahd)->tags[(0xf2) >> 8])->write_1(((ahd)->bshs [(0xf2) >> 8]), ((0xf2) & 0xFF), (i & 0xFF))); |
8597 | ahd_outb(ahd, STACK, (i >> 8) & 0xFF)(((ahd)->tags[(0xf2) >> 8])->write_1(((ahd)->bshs [(0xf2) >> 8]), ((0xf2) & 0xFF), ((i >> 8) & 0xFF))); |
8598 | } |
8599 | |
8600 | /* Verify */ |
8601 | for (i = last_probe+1; i > 0; i--) { |
8602 | u_int stack_entry; |
8603 | |
8604 | stack_entry = ahd_inb(ahd, STACK)(((ahd)->tags[(0xf2) >> 8])->read_1(((ahd)->bshs [(0xf2) >> 8]), ((0xf2) & 0xFF))) |
8605 | |(ahd_inb(ahd, STACK)(((ahd)->tags[(0xf2) >> 8])->read_1(((ahd)->bshs [(0xf2) >> 8]), ((0xf2) & 0xFF))) << 8); |
8606 | if (stack_entry != i) |
8607 | goto sized; |
8608 | } |
8609 | last_probe++; |
8610 | } |
8611 | sized: |
8612 | return (last_probe); |
8613 | } |
8614 | |
8615 | void |
8616 | ahd_dump_all_cards_state(void) |
8617 | { |
8618 | struct ahd_softc *list_ahd; |
8619 | |
8620 | 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) ) { |
8621 | ahd_dump_card_state(list_ahd); |
8622 | } |
8623 | } |
8624 | |
8625 | int |
8626 | ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries, |
8627 | const char *name, u_int address, u_int value, |
8628 | u_int *cur_column, u_int wrap_point) |
8629 | { |
8630 | u_int printed_mask; |
8631 | int entry, printed; |
8632 | |
8633 | if (cur_column != NULL((void *)0) && *cur_column >= wrap_point) { |
8634 | printf("\n"); |
8635 | *cur_column = 0; |
8636 | } |
8637 | printed = printf("%s[0x%x]", name, value); |
8638 | if (table == NULL((void *)0)) { |
8639 | printed += printf(" "); |
8640 | if (cur_column != NULL((void *)0)) |
8641 | *cur_column += printed; |
8642 | return (printed); |
8643 | } |
8644 | |
8645 | printed_mask = 0; |
8646 | while (printed_mask != 0xFF) { |
8647 | for (entry = 0; entry < num_entries; entry++) { |
8648 | if (((value & table[entry].mask) != table[entry].value) |
8649 | || ((printed_mask & table[entry].mask) == |
8650 | table[entry].mask)) |
8651 | continue; |
8652 | |
8653 | printed += printf("%s%s", |
8654 | printed_mask == 0 ? ":(" : "|", |
8655 | table[entry].name); |
8656 | printed_mask |= table[entry].mask; |
8657 | |
8658 | break; |
8659 | } |
8660 | if (entry >= num_entries) |
8661 | break; |
8662 | } |
8663 | |
8664 | printed += printf("%s", printed_mask == 0 ? " " : ") "); |
8665 | if (cur_column != NULL((void *)0)) |
8666 | *cur_column += printed; |
8667 | |
8668 | return (printed); |
8669 | } |
8670 | |
8671 | void |
8672 | ahd_dump_card_state(struct ahd_softc *ahd) |
8673 | { |
8674 | struct scb *scb; |
8675 | ahd_mode_state saved_modes; |
8676 | u_int dffstat; |
8677 | int paused; |
8678 | u_int scb_index; |
8679 | u_int saved_scb_index; |
8680 | u_int cur_col; |
8681 | int i; |
8682 | |
8683 | if (ahd_is_paused(ahd)) { |
8684 | paused = 1; |
8685 | } else { |
8686 | paused = 0; |
8687 | ahd_pause(ahd); |
8688 | } |
8689 | saved_modes = ahd_save_modes(ahd); |
8690 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
8691 | printf("================== Dump Card State Begins =================\n" |
8692 | "%s: Dumping Card State at program address 0x%x Mode 0x%x\n", |
8693 | ahd_name(ahd), |
8694 | ahd_inw(ahd, CURADDR0xf4), |
8695 | ahd_build_mode_state(ahd, ahd->saved_src_mode, |
8696 | ahd->saved_dst_mode)); |
8697 | if (paused) |
8698 | printf("Card was paused\n"); |
8699 | |
8700 | if (ahd_check_cmdcmpltqueues(ahd)) |
8701 | printf("Completions are pending\n"); |
8702 | |
8703 | /* |
8704 | * Mode independent registers. |
8705 | */ |
8706 | cur_col = 0; |
8707 | ahd_intstat_print(ahd_inb(ahd, INTSTAT), &cur_col, 50)ahd_print_register(((void *)0), 0, "INTSTAT", 0x01, (((ahd)-> tags[(0x01) >> 8])->read_1(((ahd)->bshs[(0x01) >> 8]), ((0x01) & 0xFF))), &cur_col, 50); |
8708 | ahd_seloid_print(ahd_inb(ahd, SELOID), &cur_col, 50)ahd_print_register(((void *)0), 0, "SELOID", 0x6b, (((ahd)-> tags[(0x6b) >> 8])->read_1(((ahd)->bshs[(0x6b) >> 8]), ((0x6b) & 0xFF))), &cur_col, 50); |
8709 | ahd_selid_print(ahd_inb(ahd, SELID), &cur_col, 50)ahd_print_register(((void *)0), 0, "SELID", 0x49, (((ahd)-> tags[(0x49) >> 8])->read_1(((ahd)->bshs[(0x49) >> 8]), ((0x49) & 0xFF))), &cur_col, 50); |
8710 | ahd_hs_mailbox_print(ahd_inb(ahd, LOCAL_HS_MAILBOX), &cur_col, 50)ahd_print_register(((void *)0), 0, "HS_MAILBOX", 0x0b, (((ahd )->tags[(0x157) >> 8])->read_1(((ahd)->bshs[(0x157 ) >> 8]), ((0x157) & 0xFF))), &cur_col, 50); |
8711 | ahd_intctl_print(ahd_inb(ahd, INTCTL), &cur_col, 50)ahd_print_register(((void *)0), 0, "INTCTL", 0x18, (((ahd)-> tags[(0x18) >> 8])->read_1(((ahd)->bshs[(0x18) >> 8]), ((0x18) & 0xFF))), &cur_col, 50); |
8712 | ahd_seqintstat_print(ahd_inb(ahd, SEQINTSTAT), &cur_col, 50)ahd_print_register(((void *)0), 0, "SEQINTSTAT", 0x0c, (((ahd )->tags[(0x0c) >> 8])->read_1(((ahd)->bshs[(0x0c ) >> 8]), ((0x0c) & 0xFF))), &cur_col, 50); |
8713 | ahd_saved_mode_print(ahd_inb(ahd, SAVED_MODE), &cur_col, 50)ahd_print_register(((void *)0), 0, "SAVED_MODE", 0x136, (((ahd )->tags[(0x136) >> 8])->read_1(((ahd)->bshs[(0x136 ) >> 8]), ((0x136) & 0xFF))), &cur_col, 50); |
8714 | ahd_dffstat_print(ahd_inb(ahd, DFFSTAT), &cur_col, 50)ahd_print_register(((void *)0), 0, "DFFSTAT", 0x3f, (((ahd)-> tags[(0x3f) >> 8])->read_1(((ahd)->bshs[(0x3f) >> 8]), ((0x3f) & 0xFF))), &cur_col, 50); |
8715 | ahd_scsisigi_print(ahd_inb(ahd, SCSISIGI), &cur_col, 50)ahd_print_register(((void *)0), 0, "SCSISIGI", 0x41, (((ahd)-> tags[(0x41) >> 8])->read_1(((ahd)->bshs[(0x41) >> 8]), ((0x41) & 0xFF))), &cur_col, 50); |
8716 | ahd_scsiphase_print(ahd_inb(ahd, SCSIPHASE), &cur_col, 50)ahd_print_register(((void *)0), 0, "SCSIPHASE", 0x42, (((ahd) ->tags[(0x42) >> 8])->read_1(((ahd)->bshs[(0x42 ) >> 8]), ((0x42) & 0xFF))), &cur_col, 50); |
8717 | ahd_scsibus_print(ahd_inb(ahd, SCSIBUS), &cur_col, 50)ahd_print_register(((void *)0), 0, "SCSIBUS", 0x46, (((ahd)-> tags[(0x46) >> 8])->read_1(((ahd)->bshs[(0x46) >> 8]), ((0x46) & 0xFF))), &cur_col, 50); |
8718 | ahd_lastphase_print(ahd_inb(ahd, LASTPHASE), &cur_col, 50)ahd_print_register(((void *)0), 0, "LASTPHASE", 0x13c, (((ahd )->tags[(0x13c) >> 8])->read_1(((ahd)->bshs[(0x13c ) >> 8]), ((0x13c) & 0xFF))), &cur_col, 50); |
8719 | ahd_scsiseq0_print(ahd_inb(ahd, SCSISEQ0), &cur_col, 50)ahd_print_register(((void *)0), 0, "SCSISEQ0", 0x3a, (((ahd)-> tags[(0x3a) >> 8])->read_1(((ahd)->bshs[(0x3a) >> 8]), ((0x3a) & 0xFF))), &cur_col, 50); |
8720 | ahd_scsiseq1_print(ahd_inb(ahd, SCSISEQ1), &cur_col, 50)ahd_print_register(((void *)0), 0, "SCSISEQ1", 0x3b, (((ahd)-> tags[(0x3b) >> 8])->read_1(((ahd)->bshs[(0x3b) >> 8]), ((0x3b) & 0xFF))), &cur_col, 50); |
8721 | ahd_seqctl0_print(ahd_inb(ahd, SEQCTL0), &cur_col, 50)ahd_print_register(((void *)0), 0, "SEQCTL0", 0xd6, (((ahd)-> tags[(0xd6) >> 8])->read_1(((ahd)->bshs[(0xd6) >> 8]), ((0xd6) & 0xFF))), &cur_col, 50); |
8722 | ahd_seqintctl_print(ahd_inb(ahd, SEQINTCTL), &cur_col, 50)ahd_print_register(((void *)0), 0, "SEQINTCTL", 0xd9, (((ahd) ->tags[(0xd9) >> 8])->read_1(((ahd)->bshs[(0xd9 ) >> 8]), ((0xd9) & 0xFF))), &cur_col, 50); |
8723 | ahd_seq_flags_print(ahd_inb(ahd, SEQ_FLAGS), &cur_col, 50)ahd_print_register(((void *)0), 0, "SEQ_FLAGS", 0x139, (((ahd )->tags[(0x139) >> 8])->read_1(((ahd)->bshs[(0x139 ) >> 8]), ((0x139) & 0xFF))), &cur_col, 50); |
8724 | ahd_seq_flags2_print(ahd_inb(ahd, SEQ_FLAGS2), &cur_col, 50)ahd_print_register(((void *)0), 0, "SEQ_FLAGS2", 0x14d, (((ahd )->tags[(0x14d) >> 8])->read_1(((ahd)->bshs[(0x14d ) >> 8]), ((0x14d) & 0xFF))), &cur_col, 50); |
8725 | ahd_qfreeze_count_print(ahd_inw(ahd, QFREEZE_COUNT), &cur_col, 50)ahd_print_register(((void *)0), 0, "QFREEZE_COUNT", 0x132, ahd_inw (ahd, 0x132), &cur_col, 50); |
8726 | ahd_kernel_qfreeze_count_print(ahd_inw(ahd, KERNEL_QFREEZE_COUNT),ahd_print_register(((void *)0), 0, "KERNEL_QFREEZE_COUNT", 0x134 , ahd_inw(ahd, 0x134), &cur_col, 50) |
8727 | &cur_col, 50)ahd_print_register(((void *)0), 0, "KERNEL_QFREEZE_COUNT", 0x134 , ahd_inw(ahd, 0x134), &cur_col, 50); |
8728 | ahd_mk_message_scb_print(ahd_inw(ahd, MK_MESSAGE_SCB), &cur_col, 50)ahd_print_register(((void *)0), 0, "MK_MESSAGE_SCB", 0x160, ahd_inw (ahd, 0x160), &cur_col, 50); |
8729 | ahd_mk_message_scsiid_print(ahd_inb(ahd, MK_MESSAGE_SCSIID),ahd_print_register(((void *)0), 0, "MK_MESSAGE_SCSIID", 0x162 , (((ahd)->tags[(0x162) >> 8])->read_1(((ahd)-> bshs[(0x162) >> 8]), ((0x162) & 0xFF))), &cur_col , 50) |
8730 | &cur_col, 50)ahd_print_register(((void *)0), 0, "MK_MESSAGE_SCSIID", 0x162 , (((ahd)->tags[(0x162) >> 8])->read_1(((ahd)-> bshs[(0x162) >> 8]), ((0x162) & 0xFF))), &cur_col , 50); |
8731 | ahd_sstat0_print(ahd_inb(ahd, SSTAT0), &cur_col, 50)ahd_print_register(((void *)0), 0, "SSTAT0", 0x4b, (((ahd)-> tags[(0x4b) >> 8])->read_1(((ahd)->bshs[(0x4b) >> 8]), ((0x4b) & 0xFF))), &cur_col, 50); |
8732 | ahd_sstat1_print(ahd_inb(ahd, SSTAT1), &cur_col, 50)ahd_print_register(((void *)0), 0, "SSTAT1", 0x4c, (((ahd)-> tags[(0x4c) >> 8])->read_1(((ahd)->bshs[(0x4c) >> 8]), ((0x4c) & 0xFF))), &cur_col, 50); |
8733 | ahd_sstat2_print(ahd_inb(ahd, SSTAT2), &cur_col, 50)ahd_print_register(((void *)0), 0, "SSTAT2", 0x4d, (((ahd)-> tags[(0x4d) >> 8])->read_1(((ahd)->bshs[(0x4d) >> 8]), ((0x4d) & 0xFF))), &cur_col, 50); |
8734 | ahd_sstat3_print(ahd_inb(ahd, SSTAT3), &cur_col, 50)ahd_print_register(((void *)0), 0, "SSTAT3", 0x53, (((ahd)-> tags[(0x53) >> 8])->read_1(((ahd)->bshs[(0x53) >> 8]), ((0x53) & 0xFF))), &cur_col, 50); |
8735 | ahd_perrdiag_print(ahd_inb(ahd, PERRDIAG), &cur_col, 50)ahd_print_register(((void *)0), 0, "PERRDIAG", 0x4e, (((ahd)-> tags[(0x4e) >> 8])->read_1(((ahd)->bshs[(0x4e) >> 8]), ((0x4e) & 0xFF))), &cur_col, 50); |
8736 | ahd_simode1_print(ahd_inb(ahd, SIMODE1), &cur_col, 50)ahd_print_register(((void *)0), 0, "SIMODE1", 0x57, (((ahd)-> tags[(0x57) >> 8])->read_1(((ahd)->bshs[(0x57) >> 8]), ((0x57) & 0xFF))), &cur_col, 50); |
8737 | ahd_lqistat0_print(ahd_inb(ahd, LQISTAT0), &cur_col, 50)ahd_print_register(((void *)0), 0, "LQISTAT0", 0x50, (((ahd)-> tags[(0x50) >> 8])->read_1(((ahd)->bshs[(0x50) >> 8]), ((0x50) & 0xFF))), &cur_col, 50); |
8738 | ahd_lqistat1_print(ahd_inb(ahd, LQISTAT1), &cur_col, 50)ahd_print_register(((void *)0), 0, "LQISTAT1", 0x51, (((ahd)-> tags[(0x51) >> 8])->read_1(((ahd)->bshs[(0x51) >> 8]), ((0x51) & 0xFF))), &cur_col, 50); |
8739 | ahd_lqistat2_print(ahd_inb(ahd, LQISTAT2), &cur_col, 50)ahd_print_register(((void *)0), 0, "LQISTAT2", 0x52, (((ahd)-> tags[(0x52) >> 8])->read_1(((ahd)->bshs[(0x52) >> 8]), ((0x52) & 0xFF))), &cur_col, 50); |
8740 | ahd_lqostat0_print(ahd_inb(ahd, LQOSTAT0), &cur_col, 50)ahd_print_register(((void *)0), 0, "LQOSTAT0", 0x54, (((ahd)-> tags[(0x54) >> 8])->read_1(((ahd)->bshs[(0x54) >> 8]), ((0x54) & 0xFF))), &cur_col, 50); |
8741 | ahd_lqostat1_print(ahd_inb(ahd, LQOSTAT1), &cur_col, 50)ahd_print_register(((void *)0), 0, "LQOSTAT1", 0x55, (((ahd)-> tags[(0x55) >> 8])->read_1(((ahd)->bshs[(0x55) >> 8]), ((0x55) & 0xFF))), &cur_col, 50); |
8742 | ahd_lqostat2_print(ahd_inb(ahd, LQOSTAT2), &cur_col, 50)ahd_print_register(((void *)0), 0, "LQOSTAT2", 0x56, (((ahd)-> tags[(0x56) >> 8])->read_1(((ahd)->bshs[(0x56) >> 8]), ((0x56) & 0xFF))), &cur_col, 50); |
8743 | printf("\n"); |
8744 | printf("\nSCB Count = %d CMDS_PENDING = %d LASTSCB 0x%x " |
8745 | "CURRSCB 0x%x NEXTSCB 0x%x\n", |
8746 | ahd->scb_data.numscbs, ahd_inw(ahd, CMDS_PENDING0x154), |
8747 | ahd_inw(ahd, LASTSCB0x5e), ahd_inw(ahd, CURRSCB0x5c), |
8748 | ahd_inw(ahd, NEXTSCB0x5a)); |
8749 | cur_col = 0; |
8750 | /* QINFIFO */ |
8751 | ahd_search_qinfifo(ahd, CAM_TARGET_WILDCARD((u_int)~0), ALL_CHANNELS'\0', |
8752 | CAM_LUN_WILDCARD-1, SCB_LIST_NULL0xFF00, |
8753 | ROLE_UNKNOWN, /*status*/0, SEARCH_PRINT); |
8754 | saved_scb_index = ahd_get_scbptr(ahd); |
8755 | printf("Pending list:"); |
8756 | i = 0; |
8757 | TAILQ_FOREACH(scb, &ahd->pending_scbs, next)for((scb) = ((&ahd->pending_scbs)->tqh_first); (scb ) != ((void *)0); (scb) = ((scb)->next.tqe_next)) { |
8758 | if (i++ > AHD_SCB_MAX512) |
8759 | break; |
8760 | cur_col = printf("\n%3d FIFO_USE[0x%x] ", SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)), |
8761 | ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT0x190)); |
8762 | ahd_set_scbptr(ahd, SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag))); |
8763 | ahd_scb_control_print(ahd_inb_scbram(ahd, SCB_CONTROL),ahd_print_register(((void *)0), 0, "SCB_CONTROL", 0x192, ahd_inb_scbram (ahd, 0x192), &cur_col, 60) |
8764 | &cur_col, 60)ahd_print_register(((void *)0), 0, "SCB_CONTROL", 0x192, ahd_inb_scbram (ahd, 0x192), &cur_col, 60); |
8765 | ahd_scb_scsiid_print(ahd_inb_scbram(ahd, SCB_SCSIID),ahd_print_register(((void *)0), 0, "SCB_SCSIID", 0x193, ahd_inb_scbram (ahd, 0x193), &cur_col, 60) |
8766 | &cur_col, 60)ahd_print_register(((void *)0), 0, "SCB_SCSIID", 0x193, ahd_inb_scbram (ahd, 0x193), &cur_col, 60); |
8767 | } |
8768 | printf("\nTotal %d\n", i); |
8769 | |
8770 | printf("Kernel Free SCB list: "); |
8771 | i = 0; |
8772 | 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)) { |
8773 | printf("%d ", SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag))); |
8774 | } |
8775 | printf("\n"); |
8776 | |
8777 | printf("Sequencer Complete DMA-inprog list: "); |
8778 | scb_index = ahd_inw(ahd, COMPLETE_SCB_DMAINPROG_HEAD0x12a); |
8779 | i = 0; |
8780 | while (!SCBID_IS_NULL(scb_index)(((scb_index) & 0xFF00 ) == 0xFF00) && i++ < AHD_SCB_MAX512) { |
8781 | ahd_set_scbptr(ahd, scb_index); |
8782 | printf("%d ", scb_index); |
8783 | scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE0x18c); |
8784 | } |
8785 | printf("\n"); |
8786 | |
8787 | printf("Sequencer Complete list: "); |
8788 | scb_index = ahd_inw(ahd, COMPLETE_SCB_HEAD0x128); |
8789 | i = 0; |
8790 | while (!SCBID_IS_NULL(scb_index)(((scb_index) & 0xFF00 ) == 0xFF00) && i++ < AHD_SCB_MAX512) { |
8791 | ahd_set_scbptr(ahd, scb_index); |
8792 | printf("%d ", scb_index); |
8793 | scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE0x18c); |
8794 | } |
8795 | printf("\n"); |
8796 | |
8797 | |
8798 | printf("Sequencer DMA-Up and Complete list: "); |
8799 | scb_index = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD0x12c); |
8800 | i = 0; |
8801 | while (!SCBID_IS_NULL(scb_index)(((scb_index) & 0xFF00 ) == 0xFF00) && i++ < AHD_SCB_MAX512) { |
8802 | ahd_set_scbptr(ahd, scb_index); |
8803 | printf("%d ", scb_index); |
8804 | scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE0x18c); |
8805 | } |
8806 | printf("\n"); |
8807 | printf("Sequencer On QFreeze and Complete list: "); |
8808 | scb_index = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD0x130); |
8809 | i = 0; |
8810 | while (!SCBID_IS_NULL(scb_index)(((scb_index) & 0xFF00 ) == 0xFF00) && i++ < AHD_SCB_MAX512) { |
8811 | ahd_set_scbptr(ahd, scb_index); |
8812 | printf("%d ", scb_index); |
8813 | scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE0x18c); |
8814 | } |
8815 | printf("\n"); |
8816 | ahd_set_scbptr(ahd, saved_scb_index); |
8817 | dffstat = ahd_inb(ahd, DFFSTAT)(((ahd)->tags[(0x3f) >> 8])->read_1(((ahd)->bshs [(0x3f) >> 8]), ((0x3f) & 0xFF))); |
8818 | for (i = 0; i < 2; i++) { |
8819 | #ifdef AHD_DEBUG |
8820 | struct scb *fifo_scb; |
8821 | #endif |
8822 | u_int fifo_scbptr; |
8823 | |
8824 | ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i); |
8825 | fifo_scbptr = ahd_get_scbptr(ahd); |
8826 | printf("\n\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n", |
8827 | ahd_name(ahd), i, |
8828 | (dffstat & (FIFO0FREE0x10 << i)) ? "Free" : "Active", |
8829 | ahd_inw(ahd, LONGJMP_ADDR0xf8), fifo_scbptr); |
8830 | cur_col = 0; |
8831 | ahd_seqimode_print(ahd_inb(ahd, SEQIMODE), &cur_col, 50)ahd_print_register(((void *)0), 0, "SEQIMODE", 0x5c, (((ahd)-> tags[(0x5c) >> 8])->read_1(((ahd)->bshs[(0x5c) >> 8]), ((0x5c) & 0xFF))), &cur_col, 50); |
8832 | ahd_seqintsrc_print(ahd_inb(ahd, SEQINTSRC), &cur_col, 50)ahd_print_register(((void *)0), 0, "SEQINTSRC", 0x5b, (((ahd) ->tags[(0x5b) >> 8])->read_1(((ahd)->bshs[(0x5b ) >> 8]), ((0x5b) & 0xFF))), &cur_col, 50); |
8833 | ahd_dfcntrl_print(ahd_inb(ahd, DFCNTRL), &cur_col, 50)ahd_print_register(((void *)0), 0, "DFCNTRL", 0x19, (((ahd)-> tags[(0x19) >> 8])->read_1(((ahd)->bshs[(0x19) >> 8]), ((0x19) & 0xFF))), &cur_col, 50); |
8834 | ahd_dfstatus_print(ahd_inb(ahd, DFSTATUS), &cur_col, 50)ahd_print_register(((void *)0), 0, "DFSTATUS", 0x1a, (((ahd)-> tags[(0x1a) >> 8])->read_1(((ahd)->bshs[(0x1a) >> 8]), ((0x1a) & 0xFF))), &cur_col, 50); |
8835 | ahd_sg_cache_shadow_print(ahd_inb(ahd, SG_CACHE_SHADOW),ahd_print_register(((void *)0), 0, "SG_CACHE_SHADOW", 0x1b, ( ((ahd)->tags[(0x1b) >> 8])->read_1(((ahd)->bshs [(0x1b) >> 8]), ((0x1b) & 0xFF))), &cur_col, 50 ) |
8836 | &cur_col, 50)ahd_print_register(((void *)0), 0, "SG_CACHE_SHADOW", 0x1b, ( ((ahd)->tags[(0x1b) >> 8])->read_1(((ahd)->bshs [(0x1b) >> 8]), ((0x1b) & 0xFF))), &cur_col, 50 ); |
8837 | ahd_sg_state_print(ahd_inb(ahd, SG_STATE), &cur_col, 50)ahd_print_register(((void *)0), 0, "SG_STATE", 0xa6, (((ahd)-> tags[(0xa6) >> 8])->read_1(((ahd)->bshs[(0xa6) >> 8]), ((0xa6) & 0xFF))), &cur_col, 50); |
8838 | ahd_dffsxfrctl_print(ahd_inb(ahd, DFFSXFRCTL), &cur_col, 50)ahd_print_register(((void *)0), 0, "DFFSXFRCTL", 0x5a, (((ahd )->tags[(0x5a) >> 8])->read_1(((ahd)->bshs[(0x5a ) >> 8]), ((0x5a) & 0xFF))), &cur_col, 50); |
8839 | ahd_soffcnt_print(ahd_inb(ahd, SOFFCNT), &cur_col, 50)ahd_print_register(((void *)0), 0, "SOFFCNT", 0x4f, (((ahd)-> tags[(0x4f) >> 8])->read_1(((ahd)->bshs[(0x4f) >> 8]), ((0x4f) & 0xFF))), &cur_col, 50); |
8840 | ahd_mdffstat_print(ahd_inb(ahd, MDFFSTAT), &cur_col, 50)ahd_print_register(((void *)0), 0, "MDFFSTAT", 0x5d, (((ahd)-> tags[(0x5d) >> 8])->read_1(((ahd)->bshs[(0x5d) >> 8]), ((0x5d) & 0xFF))), &cur_col, 50); |
8841 | if (cur_col > 50) { |
8842 | printf("\n"); |
8843 | cur_col = 0; |
8844 | } |
8845 | cur_col += printf("SHADDR = 0x%x%x, SHCNT = 0x%x ", |
8846 | ahd_inl(ahd, SHADDR0x60+4), |
8847 | ahd_inl(ahd, SHADDR0x60), |
8848 | (ahd_inb(ahd, SHCNT)(((ahd)->tags[(0x68) >> 8])->read_1(((ahd)->bshs [(0x68) >> 8]), ((0x68) & 0xFF))) |
8849 | | (ahd_inb(ahd, SHCNT + 1)(((ahd)->tags[(0x68 + 1) >> 8])->read_1(((ahd)-> bshs[(0x68 + 1) >> 8]), ((0x68 + 1) & 0xFF))) << 8) |
8850 | | (ahd_inb(ahd, SHCNT + 2)(((ahd)->tags[(0x68 + 2) >> 8])->read_1(((ahd)-> bshs[(0x68 + 2) >> 8]), ((0x68 + 2) & 0xFF))) << 16))); |
8851 | if (cur_col > 50) { |
8852 | printf("\n"); |
8853 | cur_col = 0; |
8854 | } |
8855 | cur_col += printf("HADDR = 0x%x%x, HCNT = 0x%x ", |
8856 | ahd_inl(ahd, HADDR0x70+4), |
8857 | ahd_inl(ahd, HADDR0x70), |
8858 | (ahd_inb(ahd, HCNT)(((ahd)->tags[(0x78) >> 8])->read_1(((ahd)->bshs [(0x78) >> 8]), ((0x78) & 0xFF))) |
8859 | | (ahd_inb(ahd, HCNT + 1)(((ahd)->tags[(0x78 + 1) >> 8])->read_1(((ahd)-> bshs[(0x78 + 1) >> 8]), ((0x78 + 1) & 0xFF))) << 8) |
8860 | | (ahd_inb(ahd, HCNT + 2)(((ahd)->tags[(0x78 + 2) >> 8])->read_1(((ahd)-> bshs[(0x78 + 2) >> 8]), ((0x78 + 2) & 0xFF))) << 16))); |
8861 | ahd_ccsgctl_print(ahd_inb(ahd, CCSGCTL), &cur_col, 50)ahd_print_register(((void *)0), 0, "CCSGCTL", 0xad, (((ahd)-> tags[(0xad) >> 8])->read_1(((ahd)->bshs[(0xad) >> 8]), ((0xad) & 0xFF))), &cur_col, 50); |
8862 | #ifdef AHD_DEBUG |
8863 | if ((ahd_debug & AHD_SHOW_SG) != 0) { |
8864 | fifo_scb = ahd_lookup_scb(ahd, fifo_scbptr); |
8865 | if (fifo_scb != NULL((void *)0)) |
8866 | ahd_dump_sglist(fifo_scb); |
8867 | } |
8868 | #endif |
8869 | } |
8870 | printf("\nLQIN: "); |
8871 | for (i = 0; i < 20; i++) |
8872 | printf("0x%x ", ahd_inb(ahd, LQIN + i)(((ahd)->tags[(0x20 + i) >> 8])->read_1(((ahd)-> bshs[(0x20 + i) >> 8]), ((0x20 + i) & 0xFF)))); |
8873 | printf("\n"); |
8874 | ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); |
8875 | printf("%s: LQISTATE = 0x%x, LQOSTATE = 0x%x, OPTIONMODE = 0x%x\n", |
8876 | ahd_name(ahd), ahd_inb(ahd, LQISTATE)(((ahd)->tags[(0x4e) >> 8])->read_1(((ahd)->bshs [(0x4e) >> 8]), ((0x4e) & 0xFF))), ahd_inb(ahd, LQOSTATE)(((ahd)->tags[(0x4f) >> 8])->read_1(((ahd)->bshs [(0x4f) >> 8]), ((0x4f) & 0xFF))), |
8877 | ahd_inb(ahd, OPTIONMODE)(((ahd)->tags[(0x4a) >> 8])->read_1(((ahd)->bshs [(0x4a) >> 8]), ((0x4a) & 0xFF)))); |
8878 | printf("%s: OS_SPACE_CNT = 0x%x MAXCMDCNT = 0x%x\n", |
8879 | ahd_name(ahd), ahd_inb(ahd, OS_SPACE_CNT)(((ahd)->tags[(0x56) >> 8])->read_1(((ahd)->bshs [(0x56) >> 8]), ((0x56) & 0xFF))), |
8880 | ahd_inb(ahd, MAXCMDCNT)(((ahd)->tags[(0x33) >> 8])->read_1(((ahd)->bshs [(0x33) >> 8]), ((0x33) & 0xFF)))); |
8881 | printf("%s: SAVED_SCSIID = 0x%x SAVED_LUN = 0x%x\n", |
8882 | ahd_name(ahd), ahd_inb(ahd, SAVED_SCSIID)(((ahd)->tags[(0x13a) >> 8])->read_1(((ahd)->bshs [(0x13a) >> 8]), ((0x13a) & 0xFF))), |
8883 | ahd_inb(ahd, SAVED_LUN)(((ahd)->tags[(0x13b) >> 8])->read_1(((ahd)->bshs [(0x13b) >> 8]), ((0x13b) & 0xFF)))); |
8884 | ahd_simode0_print(ahd_inb(ahd, SIMODE0), &cur_col, 50)ahd_print_register(((void *)0), 0, "SIMODE0", 0x4b, (((ahd)-> tags[(0x4b) >> 8])->read_1(((ahd)->bshs[(0x4b) >> 8]), ((0x4b) & 0xFF))), &cur_col, 50); |
8885 | printf("\n"); |
8886 | ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); |
8887 | cur_col = 0; |
8888 | ahd_ccscbctl_print(ahd_inb(ahd, CCSCBCTL), &cur_col, 50)ahd_print_register(((void *)0), 0, "CCSCBCTL", 0xad, (((ahd)-> tags[(0xad) >> 8])->read_1(((ahd)->bshs[(0xad) >> 8]), ((0xad) & 0xFF))), &cur_col, 50); |
8889 | printf("\n"); |
8890 | ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode); |
8891 | printf("%s: REG0 == 0x%x, SINDEX = 0x%x, DINDEX = 0x%x\n", |
8892 | ahd_name(ahd), ahd_inw(ahd, REG00xa0), ahd_inw(ahd, SINDEX0xe2), |
8893 | ahd_inw(ahd, DINDEX0xe4)); |
8894 | printf("%s: SCBPTR == 0x%x, SCB_NEXT == 0x%x, SCB_NEXT2 == 0x%x\n", |
8895 | ahd_name(ahd), ahd_get_scbptr(ahd), |
8896 | ahd_inw_scbram(ahd, SCB_NEXT0x1ac), |
8897 | ahd_inw_scbram(ahd, SCB_NEXT20x1ae)); |
8898 | printf("CDB %x %x %x %x %x %x\n", |
8899 | ahd_inb_scbram(ahd, SCB_CDB_STORE0x180), |
8900 | ahd_inb_scbram(ahd, SCB_CDB_STORE0x180+1), |
8901 | ahd_inb_scbram(ahd, SCB_CDB_STORE0x180+2), |
8902 | ahd_inb_scbram(ahd, SCB_CDB_STORE0x180+3), |
8903 | ahd_inb_scbram(ahd, SCB_CDB_STORE0x180+4), |
8904 | ahd_inb_scbram(ahd, SCB_CDB_STORE0x180+5)); |
8905 | printf("STACK:"); |
8906 | for (i = 0; i < ahd->stack_size; i++) { |
8907 | ahd->saved_stack[i] = |
8908 | ahd_inb(ahd, STACK)(((ahd)->tags[(0xf2) >> 8])->read_1(((ahd)->bshs [(0xf2) >> 8]), ((0xf2) & 0xFF)))|(ahd_inb(ahd, STACK)(((ahd)->tags[(0xf2) >> 8])->read_1(((ahd)->bshs [(0xf2) >> 8]), ((0xf2) & 0xFF))) << 8); |
8909 | printf(" 0x%x", ahd->saved_stack[i]); |
8910 | } |
8911 | for (i = ahd->stack_size-1; i >= 0; i--) { |
8912 | ahd_outb(ahd, STACK, ahd->saved_stack[i] & 0xFF)(((ahd)->tags[(0xf2) >> 8])->write_1(((ahd)->bshs [(0xf2) >> 8]), ((0xf2) & 0xFF), (ahd->saved_stack [i] & 0xFF))); |
8913 | ahd_outb(ahd, STACK, (ahd->saved_stack[i] >> 8) & 0xFF)(((ahd)->tags[(0xf2) >> 8])->write_1(((ahd)->bshs [(0xf2) >> 8]), ((0xf2) & 0xFF), ((ahd->saved_stack [i] >> 8) & 0xFF))); |
8914 | } |
8915 | printf("\n================= Dump Card State Ends ==================\n"); |
8916 | ahd_platform_dump_card_state(ahd); |
8917 | ahd_restore_modes(ahd, saved_modes); |
8918 | if (paused == 0) |
8919 | ahd_unpause(ahd); |
8920 | } |
8921 | |
8922 | void |
8923 | ahd_dump_scbs(struct ahd_softc *ahd) |
8924 | { |
8925 | ahd_mode_state saved_modes; |
8926 | u_int saved_scb_index; |
8927 | int i; |
8928 | |
8929 | saved_modes = ahd_save_modes(ahd); |
8930 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); |
8931 | saved_scb_index = ahd_get_scbptr(ahd); |
8932 | for (i = 0; i < AHD_SCB_MAX512; i++) { |
8933 | ahd_set_scbptr(ahd, i); |
8934 | printf("%3d", i); |
8935 | printf("(CTRL 0x%x ID 0x%x N 0x%x N2 0x%x SG 0x%x, RSG 0x%x)\n", |
8936 | ahd_inb_scbram(ahd, SCB_CONTROL0x192), |
8937 | ahd_inb_scbram(ahd, SCB_SCSIID0x193), |
8938 | ahd_inw_scbram(ahd, SCB_NEXT0x1ac), |
8939 | ahd_inw_scbram(ahd, SCB_NEXT20x1ae), |
8940 | ahd_inl_scbram(ahd, SCB_SGPTR0x1a4), |
8941 | ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR0x184)); |
8942 | } |
8943 | printf("\n"); |
8944 | ahd_set_scbptr(ahd, saved_scb_index); |
8945 | ahd_restore_modes(ahd, saved_modes); |
8946 | } |
8947 | |
8948 | |
8949 | /*************************** Timeout Handling *********************************/ |
8950 | void |
8951 | ahd_timeout(void *arg) |
8952 | { |
8953 | struct scb *scb, *list_scb; |
8954 | struct ahd_softc *ahd; |
8955 | char channel; |
8956 | long s; |
8957 | int found; |
8958 | #ifdef AHD_DEBUG |
8959 | int was_paused; |
8960 | #endif |
8961 | |
8962 | scb = (struct scb *)arg; |
8963 | ahd = scb->ahd_softc; |
8964 | |
8965 | ahd_lock(ahd, &s)*(&s) = splraise(0x3); |
8966 | |
8967 | #ifdef AHD_DEBUG |
8968 | was_paused = ahd_is_paused(ahd); |
8969 | printf("%s: SCB %d timed out - Card was %spaused\n", ahd_name(ahd), |
8970 | SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)), was_paused ? "" : "not "); |
8971 | ahd_dump_card_state(ahd); |
8972 | #endif |
8973 | |
8974 | ahd_pause(ahd); |
8975 | |
8976 | if (scb->flags & SCB_ACTIVE) { |
8977 | aic_set_transaction_status(scb, CAM_CMD_TIMEOUT)(scb)->xs->error = (CAM_CMD_TIMEOUT); |
8978 | /* |
8979 | * Go through all of our pending SCBs and remove any scheduled |
8980 | * timeouts for them. They're about to be aborted so no need |
8981 | * for them to timeout. |
8982 | */ |
8983 | TAILQ_FOREACH(list_scb, &ahd->pending_scbs, next)for((list_scb) = ((&ahd->pending_scbs)->tqh_first); (list_scb) != ((void *)0); (list_scb) = ((list_scb)->next .tqe_next)) { |
8984 | if (list_scb->xs) |
8985 | timeout_del(&list_scb->xs->stimeout); |
8986 | } |
8987 | channel = SCB_GET_CHANNEL(ahd, scb)('A'); |
8988 | found = ahd_reset_channel(ahd, channel, /*Initiate Reset*/TRUE1); |
8989 | #ifdef AHD_DEBUG |
8990 | printf("%s: Issued Channel %c Bus Reset. %d SCBs aborted\n", |
8991 | ahd_name(ahd), channel, found); |
8992 | #endif |
8993 | } |
8994 | |
8995 | ahd_unpause(ahd); |
8996 | ahd_unlock(ahd, &s)spllower(*(&s)); |
8997 | } |
8998 | |
8999 | /**************************** Flexport Logic **********************************/ |
9000 | /* |
9001 | * Read count 16bit words from 16bit word address start_addr from the |
9002 | * SEEPROM attached to the controller, into buf, using the controller's |
9003 | * SEEPROM reading state machine. Optionally treat the data as a byte |
9004 | * stream in terms of byte order. |
9005 | */ |
9006 | int |
9007 | ahd_read_seeprom(struct ahd_softc *ahd, uint16_t *buf, |
9008 | u_int start_addr, u_int count, int bytestream) |
9009 | { |
9010 | u_int cur_addr; |
9011 | u_int end_addr; |
9012 | int error; |
9013 | |
9014 | /* |
9015 | * If we never make it through the loop even once, |
9016 | * we were passed invalid arguments. |
9017 | */ |
9018 | error = EINVAL22; |
9019 | 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", 9019);; |
9020 | end_addr = start_addr + count; |
9021 | for (cur_addr = start_addr; cur_addr < end_addr; cur_addr++) { |
9022 | |
9023 | ahd_outb(ahd, SEEADR, cur_addr)(((ahd)->tags[(0xba) >> 8])->write_1(((ahd)->bshs [(0xba) >> 8]), ((0xba) & 0xFF), (cur_addr))); |
9024 | ahd_outb(ahd, SEECTL, SEEOP_READ | SEESTART)(((ahd)->tags[(0xbe) >> 8])->write_1(((ahd)->bshs [(0xbe) >> 8]), ((0xbe) & 0xFF), (0x60 | 0x01))); |
9025 | |
9026 | error = ahd_wait_seeprom(ahd); |
9027 | if (error) { |
9028 | printf("%s: ahd_wait_seeprom timed out\n", ahd_name(ahd)); |
9029 | break; |
9030 | } |
9031 | if (bytestream != 0) { |
9032 | uint8_t *bytestream_ptr; |
9033 | |
9034 | bytestream_ptr = (uint8_t *)buf; |
9035 | *bytestream_ptr++ = ahd_inb(ahd, SEEDAT)(((ahd)->tags[(0xbc) >> 8])->read_1(((ahd)->bshs [(0xbc) >> 8]), ((0xbc) & 0xFF))); |
9036 | *bytestream_ptr = ahd_inb(ahd, SEEDAT+1)(((ahd)->tags[(0xbc +1) >> 8])->read_1(((ahd)-> bshs[(0xbc +1) >> 8]), ((0xbc +1) & 0xFF))); |
9037 | } else { |
9038 | /* |
9039 | * ahd_inw() already handles machine byte order. |
9040 | */ |
9041 | *buf = ahd_inw(ahd, SEEDAT0xbc); |
9042 | } |
9043 | buf++; |
9044 | } |
9045 | return (error); |
9046 | } |
9047 | |
9048 | /* |
9049 | * Write count 16bit words from buf, into SEEPROM attached to the |
9050 | * controller starting at 16bit word address start_addr, using the |
9051 | * controller's SEEPROM writing state machine. |
9052 | */ |
9053 | int |
9054 | ahd_write_seeprom(struct ahd_softc *ahd, uint16_t *buf, |
9055 | u_int start_addr, u_int count) |
9056 | { |
9057 | u_int cur_addr; |
9058 | u_int end_addr; |
9059 | int error; |
9060 | int retval; |
9061 | |
9062 | 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", 9062);; |
9063 | |
9064 | /* Place the chip into write-enable mode */ |
9065 | ahd_outb(ahd, SEEADR, SEEOP_EWEN_ADDR)(((ahd)->tags[(0xba) >> 8])->write_1(((ahd)->bshs [(0xba) >> 8]), ((0xba) & 0xFF), (0xc0))); |
9066 | ahd_outb(ahd, SEECTL, SEEOP_EWEN | SEESTART)(((ahd)->tags[(0xbe) >> 8])->write_1(((ahd)->bshs [(0xbe) >> 8]), ((0xbe) & 0xFF), (0x40 | 0x01))); |
9067 | error = ahd_wait_seeprom(ahd); |
9068 | if (error) |
9069 | return (error); |
9070 | |
9071 | /* |
9072 | * Write the data. If we don't get through the loop at |
9073 | * least once, the arguments were invalid. |
9074 | */ |
9075 | retval = EINVAL22; |
9076 | end_addr = start_addr + count; |
9077 | for (cur_addr = start_addr; cur_addr < end_addr; cur_addr++) { |
9078 | ahd_outw(ahd, SEEDAT0xbc, *buf++); |
9079 | ahd_outb(ahd, SEEADR, cur_addr)(((ahd)->tags[(0xba) >> 8])->write_1(((ahd)->bshs [(0xba) >> 8]), ((0xba) & 0xFF), (cur_addr))); |
9080 | ahd_outb(ahd, SEECTL, SEEOP_WRITE | SEESTART)(((ahd)->tags[(0xbe) >> 8])->write_1(((ahd)->bshs [(0xbe) >> 8]), ((0xbe) & 0xFF), (0x50 | 0x01))); |
9081 | |
9082 | retval = ahd_wait_seeprom(ahd); |
9083 | if (retval) |
9084 | break; |
9085 | } |
9086 | |
9087 | /* |
9088 | * Disable writes. |
9089 | */ |
9090 | ahd_outb(ahd, SEEADR, SEEOP_EWDS_ADDR)(((ahd)->tags[(0xba) >> 8])->write_1(((ahd)->bshs [(0xba) >> 8]), ((0xba) & 0xFF), (0x00))); |
9091 | ahd_outb(ahd, SEECTL, SEEOP_EWDS | SEESTART)(((ahd)->tags[(0xbe) >> 8])->write_1(((ahd)->bshs [(0xbe) >> 8]), ((0xbe) & 0xFF), (0x40 | 0x01))); |
9092 | error = ahd_wait_seeprom(ahd); |
9093 | if (error) |
9094 | return (error); |
9095 | return (retval); |
9096 | } |
9097 | |
9098 | /* |
9099 | * Wait ~100us for the serial eeprom to satisfy our request. |
9100 | */ |
9101 | int |
9102 | ahd_wait_seeprom(struct ahd_softc *ahd) |
9103 | { |
9104 | int cnt; |
9105 | |
9106 | cnt = 5000; |
9107 | while ((ahd_inb(ahd, SEESTAT)(((ahd)->tags[(0xbe) >> 8])->read_1(((ahd)->bshs [(0xbe) >> 8]), ((0xbe) & 0xFF))) & (SEEARBACK0x04|SEEBUSY0x02)) != 0 && --cnt) |
9108 | aic_delay(5)(*delay_func)(5); |
9109 | |
9110 | if (cnt == 0) |
9111 | return (ETIMEDOUT60); |
9112 | return (0); |
9113 | } |
9114 | |
9115 | /* |
9116 | * Validate the two checksums in the per_channel |
9117 | * vital product data struct. |
9118 | */ |
9119 | int |
9120 | ahd_verify_vpd_cksum(struct vpd_config *vpd) |
9121 | { |
9122 | int i; |
9123 | int maxaddr; |
9124 | uint32_t checksum; |
9125 | uint8_t *vpdarray; |
9126 | |
9127 | vpdarray = (uint8_t *)vpd; |
9128 | maxaddr = offsetof(struct vpd_config, vpd_checksum)__builtin_offsetof(struct vpd_config, vpd_checksum); |
9129 | checksum = 0; |
9130 | for (i = offsetof(struct vpd_config, resource_type)__builtin_offsetof(struct vpd_config, resource_type); i < maxaddr; i++) |
9131 | checksum = checksum + vpdarray[i]; |
9132 | if (checksum == 0 |
9133 | || (-checksum & 0xFF) != vpd->vpd_checksum) |
9134 | return (0); |
9135 | |
9136 | checksum = 0; |
9137 | maxaddr = offsetof(struct vpd_config, checksum)__builtin_offsetof(struct vpd_config, checksum); |
9138 | for (i = offsetof(struct vpd_config, default_target_flags)__builtin_offsetof(struct vpd_config, default_target_flags); |
9139 | i < maxaddr; i++) |
9140 | checksum = checksum + vpdarray[i]; |
9141 | if (checksum == 0 |
9142 | || (-checksum & 0xFF) != vpd->checksum) |
9143 | return (0); |
9144 | return (1); |
9145 | } |
9146 | |
9147 | int |
9148 | ahd_verify_cksum(struct seeprom_config *sc) |
9149 | { |
9150 | int i; |
9151 | int maxaddr; |
9152 | uint32_t checksum; |
9153 | uint16_t *scarray; |
9154 | |
9155 | maxaddr = (sizeof(*sc)/2) - 1; |
9156 | checksum = 0; |
9157 | scarray = (uint16_t *)sc; |
9158 | |
9159 | for (i = 0; i < maxaddr; i++) |
9160 | checksum = checksum + scarray[i]; |
9161 | if (checksum == 0 |
9162 | || (checksum & 0xFFFF) != sc->checksum) { |
9163 | return (0); |
9164 | } else { |
9165 | return (1); |
9166 | } |
9167 | } |
9168 | |
9169 | int |
9170 | ahd_acquire_seeprom(struct ahd_softc *ahd) |
9171 | { |
9172 | /* |
9173 | * We should be able to determine the SEEPROM type |
9174 | * from the flexport logic, but unfortunately not |
9175 | * all implementations have this logic and there is |
9176 | * no programmatic method for determining if the logic |
9177 | * is present. |
9178 | */ |
9179 | return (1); |
9180 | #if 0 |
9181 | uint8_t seetype; |
9182 | int error; |
9183 | |
9184 | error = ahd_read_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL0x1, &seetype); |
9185 | if (error != 0 |
9186 | || ((seetype & FLX_ROMSTAT_SEECFG0xF0) == FLX_ROMSTAT_SEE_NONE0xF0)) |
9187 | return (0); |
9188 | return (1); |
9189 | #endif |
9190 | } |
9191 | |
9192 | void |
9193 | ahd_release_seeprom(struct ahd_softc *ahd) |
9194 | { |
9195 | /* Currently a no-op */ |
9196 | } |
9197 | |
9198 | int |
9199 | ahd_write_flexport(struct ahd_softc *ahd, u_int addr, u_int value) |
9200 | { |
9201 | int error; |
9202 | |
9203 | 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", 9203);; |
9204 | if (addr > 7) |
9205 | panic("ahd_write_flexport: address out of range"); |
9206 | ahd_outb(ahd, BRDCTL, BRDEN|(addr << 3))(((ahd)->tags[(0xb9) >> 8])->write_1(((ahd)->bshs [(0xb9) >> 8]), ((0xb9) & 0xFF), (0x04|(addr << 3)))); |
9207 | error = ahd_wait_flexport(ahd); |
9208 | if (error != 0) |
9209 | return (error); |
9210 | ahd_outb(ahd, BRDDAT, value)(((ahd)->tags[(0xb8) >> 8])->write_1(((ahd)->bshs [(0xb8) >> 8]), ((0xb8) & 0xFF), (value))); |
9211 | ahd_flush_device_writes(ahd); |
9212 | ahd_outb(ahd, BRDCTL, BRDSTB|BRDEN|(addr << 3))(((ahd)->tags[(0xb9) >> 8])->write_1(((ahd)->bshs [(0xb9) >> 8]), ((0xb9) & 0xFF), (0x01|0x04|(addr << 3)))); |
9213 | ahd_flush_device_writes(ahd); |
9214 | ahd_outb(ahd, BRDCTL, BRDEN|(addr << 3))(((ahd)->tags[(0xb9) >> 8])->write_1(((ahd)->bshs [(0xb9) >> 8]), ((0xb9) & 0xFF), (0x04|(addr << 3)))); |
9215 | ahd_flush_device_writes(ahd); |
9216 | ahd_outb(ahd, BRDCTL, 0)(((ahd)->tags[(0xb9) >> 8])->write_1(((ahd)->bshs [(0xb9) >> 8]), ((0xb9) & 0xFF), (0))); |
9217 | ahd_flush_device_writes(ahd); |
9218 | return (0); |
9219 | } |
9220 | |
9221 | int |
9222 | ahd_read_flexport(struct ahd_softc *ahd, u_int addr, uint8_t *value) |
9223 | { |
9224 | int error; |
9225 | |
9226 | 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", 9226);; |
9227 | if (addr > 7) |
9228 | panic("ahd_read_flexport: address out of range"); |
9229 | ahd_outb(ahd, BRDCTL, BRDRW|BRDEN|(addr << 3))(((ahd)->tags[(0xb9) >> 8])->write_1(((ahd)->bshs [(0xb9) >> 8]), ((0xb9) & 0xFF), (0x02|0x04|(addr << 3)))); |
9230 | error = ahd_wait_flexport(ahd); |
9231 | if (error != 0) |
9232 | return (error); |
9233 | *value = ahd_inb(ahd, BRDDAT)(((ahd)->tags[(0xb8) >> 8])->read_1(((ahd)->bshs [(0xb8) >> 8]), ((0xb8) & 0xFF))); |
9234 | ahd_outb(ahd, BRDCTL, 0)(((ahd)->tags[(0xb9) >> 8])->write_1(((ahd)->bshs [(0xb9) >> 8]), ((0xb9) & 0xFF), (0))); |
9235 | ahd_flush_device_writes(ahd); |
9236 | return (0); |
9237 | } |
9238 | |
9239 | /* |
9240 | * Wait at most 2 seconds for flexport arbitration to succeed. |
9241 | */ |
9242 | int |
9243 | ahd_wait_flexport(struct ahd_softc *ahd) |
9244 | { |
9245 | int cnt; |
9246 | |
9247 | 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", 9247);; |
9248 | cnt = 1000000 * 2 / 5; |
9249 | while ((ahd_inb(ahd, BRDCTL)(((ahd)->tags[(0xb9) >> 8])->read_1(((ahd)->bshs [(0xb9) >> 8]), ((0xb9) & 0xFF))) & FLXARBACK0x80) == 0 && --cnt) |
9250 | aic_delay(5)(*delay_func)(5); |
9251 | |
9252 | if (cnt == 0) |
9253 | return (ETIMEDOUT60); |
9254 | return (0); |
9255 | } |
9256 | |
9257 | /************************* Target Mode ****************************************/ |
9258 | #ifdef AHD_TARGET_MODE |
9259 | cam_status |
9260 | ahd_find_tmode_devs(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb, |
9261 | struct ahd_tmode_tstate **tstate, |
9262 | struct ahd_tmode_lstate **lstate, |
9263 | int notfound_failure) |
9264 | { |
9265 | |
9266 | if ((ahd->features & AHD_TARGETMODE) == 0) |
9267 | return (CAM_REQ_INVALID); |
9268 | |
9269 | /* |
9270 | * Handle the 'black hole' device that sucks up |
9271 | * requests to unattached luns on enabled targets. |
9272 | */ |
9273 | if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD((u_int)~0) |
9274 | && ccb->ccb_h.target_lun == CAM_LUN_WILDCARD-1) { |
9275 | *tstate = NULL((void *)0); |
9276 | *lstate = ahd->black_hole; |
9277 | } else { |
9278 | u_int max_id; |
9279 | |
9280 | max_id = (ahd->features & AHD_WIDE) ? 15 : 7; |
9281 | if (ccb->ccb_h.target_id > max_id) |
9282 | return (CAM_TID_INVALID); |
9283 | |
9284 | if (ccb->ccb_h.target_lun >= AHD_NUM_LUNS256) |
9285 | return (CAM_LUN_INVALID); |
9286 | |
9287 | *tstate = ahd->enabled_targets[ccb->ccb_h.target_id]; |
9288 | *lstate = NULL((void *)0); |
9289 | if (*tstate != NULL((void *)0)) |
9290 | *lstate = |
9291 | (*tstate)->enabled_luns[ccb->ccb_h.target_lun]; |
9292 | } |
9293 | |
9294 | if (notfound_failure != 0 && *lstate == NULL((void *)0)) |
9295 | return (CAM_PATH_INVALID); |
9296 | |
9297 | return (CAM_REQ_CMP); |
9298 | } |
9299 | |
9300 | void |
9301 | ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) |
9302 | { |
9303 | #if NOT_YET |
9304 | struct ahd_tmode_tstate *tstate; |
9305 | struct ahd_tmode_lstate *lstate; |
9306 | struct ccb_en_lun *cel; |
9307 | cam_status status; |
9308 | u_int target; |
9309 | u_int lun; |
9310 | u_int target_mask; |
9311 | int s; |
9312 | char channel; |
9313 | |
9314 | status = ahd_find_tmode_devs(ahd, sim, ccb, &tstate, &lstate, |
9315 | /*notfound_failure*/FALSE0); |
9316 | |
9317 | if (status != CAM_REQ_CMP) { |
9318 | ccb->ccb_h.status = status; |
9319 | return; |
9320 | } |
9321 | |
9322 | if ((ahd->features & AHD_MULTIROLE) != 0) { |
9323 | u_int our_id; |
9324 | |
9325 | our_id = ahd->our_id; |
9326 | if (ccb->ccb_h.target_id != our_id) { |
9327 | if ((ahd->features & AHD_MULTI_TID) != 0 |
9328 | && (ahd->flags & AHD_INITIATORROLE) != 0) { |
9329 | /* |
9330 | * Only allow additional targets if |
9331 | * the initiator role is disabled. |
9332 | * The hardware cannot handle a re-select-in |
9333 | * on the initiator id during a re-select-out |
9334 | * on a different target id. |
9335 | */ |
9336 | status = CAM_TID_INVALID; |
9337 | } else if ((ahd->flags & AHD_INITIATORROLE) != 0 |
9338 | || ahd->enabled_luns > 0) { |
9339 | /* |
9340 | * Only allow our target id to change |
9341 | * if the initiator role is not configured |
9342 | * and there are no enabled luns which |
9343 | * are attached to the currently registered |
9344 | * scsi id. |
9345 | */ |
9346 | status = CAM_TID_INVALID; |
9347 | } |
9348 | } |
9349 | } |
9350 | |
9351 | if (status != CAM_REQ_CMP) { |
9352 | ccb->ccb_h.status = status; |
9353 | return; |
9354 | } |
9355 | |
9356 | /* |
9357 | * We now have an id that is valid. |
9358 | * If we aren't in target mode, switch modes. |
9359 | */ |
9360 | if ((ahd->flags & AHD_TARGETROLE) == 0 |
9361 | && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD((u_int)~0)) { |
9362 | int s; |
9363 | |
9364 | printf("Configuring Target Mode\n"); |
9365 | ahd_lock(ahd, &s)*(&s) = splraise(0x3); |
9366 | if (LIST_FIRST(&ahd->pending_scbs)((&ahd->pending_scbs)->lh_first) != NULL((void *)0)) { |
9367 | ccb->ccb_h.status = CAM_BUSY; |
9368 | ahd_unlock(ahd, &s)spllower(*(&s)); |
9369 | return; |
9370 | } |
9371 | ahd->flags |= AHD_TARGETROLE; |
9372 | if ((ahd->features & AHD_MULTIROLE) == 0) |
9373 | ahd->flags &= ~AHD_INITIATORROLE; |
9374 | ahd_pause(ahd); |
9375 | ahd_loadseq(ahd); |
9376 | ahd_restart(ahd); |
9377 | ahd_unlock(ahd, &s)spllower(*(&s)); |
9378 | } |
9379 | cel = &ccb->cel; |
9380 | target = ccb->ccb_h.target_id; |
9381 | lun = ccb->ccb_h.target_lun; |
9382 | channel = SCSI_CHANNEL(ahd, sim)('A'); |
9383 | target_mask = 0x01 << target; |
9384 | if (channel == 'B') |
9385 | target_mask <<= 8; |
9386 | |
9387 | if (cel->enable != 0) { |
9388 | u_int scsiseq1; |
9389 | |
9390 | /* Are we already enabled?? */ |
9391 | if (lstate != NULL((void *)0)) { |
9392 | xpt_print_path(ccb->ccb_h.path); |
9393 | printf("Lun already enabled\n"); |
9394 | ccb->ccb_h.status = CAM_LUN_ALRDY_ENA; |
9395 | return; |
9396 | } |
9397 | |
9398 | if (cel->grp6_len != 0 |
9399 | || cel->grp7_len != 0) { |
9400 | /* |
9401 | * Don't (yet?) support vendor |
9402 | * specific commands. |
9403 | */ |
9404 | ccb->ccb_h.status = CAM_REQ_INVALID; |
9405 | printf("Non-zero Group Codes\n"); |
9406 | return; |
9407 | } |
9408 | |
9409 | /* |
9410 | * Seems to be okay. |
9411 | * Setup our data structures. |
9412 | */ |
9413 | if (target != CAM_TARGET_WILDCARD((u_int)~0) && tstate == NULL((void *)0)) { |
9414 | tstate = ahd_alloc_tstate(ahd, target, channel); |
9415 | if (tstate == NULL((void *)0)) { |
9416 | xpt_print_path(ccb->ccb_h.path); |
9417 | printf("Couldn't allocate tstate\n"); |
9418 | ccb->ccb_h.status = CAM_RESRC_UNAVAIL; |
9419 | return; |
9420 | } |
9421 | } |
9422 | lstate = malloc(sizeof(*lstate), M_DEVBUF2, M_NOWAIT0x0002 | M_ZERO0x0008); |
9423 | if (lstate == NULL((void *)0)) { |
9424 | xpt_print_path(ccb->ccb_h.path); |
9425 | printf("Couldn't allocate lstate\n"); |
9426 | ccb->ccb_h.status = CAM_RESRC_UNAVAIL; |
9427 | return; |
9428 | } |
9429 | status = xpt_create_path(&lstate->path, /*periph*/NULL((void *)0), |
9430 | xpt_path_path_id(ccb->ccb_h.path), |
9431 | xpt_path_target_id(ccb->ccb_h.path), |
9432 | xpt_path_lun_id(ccb->ccb_h.path)); |
9433 | if (status != CAM_REQ_CMP) { |
9434 | free(lstate, M_DEVBUF2, 0); |
9435 | xpt_print_path(ccb->ccb_h.path); |
9436 | printf("Couldn't allocate path\n"); |
9437 | ccb->ccb_h.status = CAM_RESRC_UNAVAIL; |
9438 | return; |
9439 | } |
9440 | SLIST_INIT(&lstate->accept_tios){ ((&lstate->accept_tios)->slh_first) = ((void *)0) ; }; |
9441 | SLIST_INIT(&lstate->immed_notifies){ ((&lstate->immed_notifies)->slh_first) = ((void * )0); }; |
9442 | ahd_lock(ahd, &s)*(&s) = splraise(0x3); |
9443 | ahd_pause(ahd); |
9444 | if (target != CAM_TARGET_WILDCARD((u_int)~0)) { |
9445 | tstate->enabled_luns[lun] = lstate; |
9446 | ahd->enabled_luns++; |
9447 | |
9448 | if ((ahd->features & AHD_MULTI_TID) != 0) { |
9449 | u_int targid_mask; |
9450 | |
9451 | targid_mask = ahd_inw(ahd, TARGID0x0f); |
9452 | targid_mask |= target_mask; |
9453 | ahd_outw(ahd, TARGID0x0f, targid_mask); |
9454 | ahd_update_scsiid(ahd, targid_mask); |
9455 | } else { |
9456 | u_int our_id; |
9457 | char channel; |
9458 | |
9459 | channel = SCSI_CHANNEL(ahd, sim)('A'); |
9460 | our_id = SCSI_SCSI_ID(ahd, sim)(ahd->our_id); |
9461 | |
9462 | /* |
9463 | * This can only happen if selections |
9464 | * are not enabled |
9465 | */ |
9466 | if (target != our_id) { |
9467 | u_int sblkctl; |
9468 | char cur_channel; |
9469 | int swap; |
9470 | |
9471 | sblkctl = ahd_inb(ahd, SBLKCTL)(((ahd)->tags[(0x4a) >> 8])->read_1(((ahd)->bshs [(0x4a) >> 8]), ((0x4a) & 0xFF))); |
9472 | cur_channel = (sblkctl & SELBUSB) |
9473 | ? 'B' : 'A'; |
9474 | if ((ahd->features & AHD_TWIN) == 0) |
9475 | cur_channel = 'A'; |
9476 | swap = cur_channel != channel; |
9477 | ahd->our_id = target; |
9478 | |
9479 | if (swap) |
9480 | ahd_outb(ahd, SBLKCTL,(((ahd)->tags[(0x4a) >> 8])->write_1(((ahd)->bshs [(0x4a) >> 8]), ((0x4a) & 0xFF), (sblkctl ^ SELBUSB ))) |
9481 | sblkctl ^ SELBUSB)(((ahd)->tags[(0x4a) >> 8])->write_1(((ahd)->bshs [(0x4a) >> 8]), ((0x4a) & 0xFF), (sblkctl ^ SELBUSB ))); |
9482 | |
9483 | ahd_outb(ahd, SCSIID, target)(((ahd)->tags[(SCSIID) >> 8])->write_1(((ahd)-> bshs[(SCSIID) >> 8]), ((SCSIID) & 0xFF), (target))); |
9484 | |
9485 | if (swap) |
9486 | ahd_outb(ahd, SBLKCTL, sblkctl)(((ahd)->tags[(0x4a) >> 8])->write_1(((ahd)->bshs [(0x4a) >> 8]), ((0x4a) & 0xFF), (sblkctl))); |
9487 | } |
9488 | } |
9489 | } else |
9490 | ahd->black_hole = lstate; |
9491 | /* Allow select-in operations */ |
9492 | if (ahd->black_hole != NULL((void *)0) && ahd->enabled_luns > 0) { |
9493 | scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE)(((ahd)->tags[(0x14b) >> 8])->read_1(((ahd)->bshs [(0x14b) >> 8]), ((0x14b) & 0xFF))); |
9494 | scsiseq1 |= ENSELI0x20; |
9495 | ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq1)(((ahd)->tags[(0x14b) >> 8])->write_1(((ahd)-> bshs[(0x14b) >> 8]), ((0x14b) & 0xFF), (scsiseq1))); |
9496 | scsiseq1 = ahd_inb(ahd, SCSISEQ1)(((ahd)->tags[(0x3b) >> 8])->read_1(((ahd)->bshs [(0x3b) >> 8]), ((0x3b) & 0xFF))); |
9497 | scsiseq1 |= ENSELI0x20; |
9498 | ahd_outb(ahd, SCSISEQ1, scsiseq1)(((ahd)->tags[(0x3b) >> 8])->write_1(((ahd)->bshs [(0x3b) >> 8]), ((0x3b) & 0xFF), (scsiseq1))); |
9499 | } |
9500 | ahd_unpause(ahd); |
9501 | ahd_unlock(ahd, &s)spllower(*(&s)); |
9502 | ccb->ccb_h.status = CAM_REQ_CMP; |
9503 | xpt_print_path(ccb->ccb_h.path); |
9504 | printf("Lun now enabled for target mode\n"); |
9505 | } else { |
9506 | struct scb *scb; |
9507 | int i, empty; |
9508 | |
9509 | if (lstate == NULL((void *)0)) { |
9510 | ccb->ccb_h.status = CAM_LUN_INVALID; |
9511 | return; |
9512 | } |
9513 | |
9514 | ahd_lock(ahd, &s)*(&s) = splraise(0x3); |
9515 | |
9516 | ccb->ccb_h.status = CAM_REQ_CMP; |
9517 | TAILQ_FOREACH(scb, &ahd->pending_scbs, next)for((scb) = ((&ahd->pending_scbs)->tqh_first); (scb ) != ((void *)0); (scb) = ((scb)->next.tqe_next)) { |
9518 | struct ccb_hdr *ccbh; |
9519 | |
9520 | ccbh = &scb->io_ctx->ccb_h; |
9521 | if (ccbh->func_code == XPT_CONT_TARGET_IO |
9522 | && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){ |
9523 | printf("CTIO pending\n"); |
9524 | ccb->ccb_h.status = CAM_REQ_INVALID; |
9525 | ahd_unlock(ahd, &s)spllower(*(&s)); |
9526 | return; |
9527 | } |
9528 | } |
9529 | |
9530 | if (SLIST_FIRST(&lstate->accept_tios)((&lstate->accept_tios)->slh_first) != NULL((void *)0)) { |
9531 | printf("ATIOs pending\n"); |
9532 | ccb->ccb_h.status = CAM_REQ_INVALID; |
9533 | } |
9534 | |
9535 | if (SLIST_FIRST(&lstate->immed_notifies)((&lstate->immed_notifies)->slh_first) != NULL((void *)0)) { |
9536 | printf("INOTs pending\n"); |
9537 | ccb->ccb_h.status = CAM_REQ_INVALID; |
9538 | } |
9539 | |
9540 | if (ccb->ccb_h.status != CAM_REQ_CMP) { |
9541 | ahd_unlock(ahd, &s)spllower(*(&s)); |
9542 | return; |
9543 | } |
9544 | |
9545 | xpt_print_path(ccb->ccb_h.path); |
9546 | printf("Target mode disabled\n"); |
9547 | xpt_free_path(lstate->path); |
9548 | free(lstate, M_DEVBUF2, 0); |
9549 | |
9550 | ahd_pause(ahd); |
9551 | /* Can we clean up the target too? */ |
9552 | if (target != CAM_TARGET_WILDCARD((u_int)~0)) { |
9553 | tstate->enabled_luns[lun] = NULL((void *)0); |
9554 | ahd->enabled_luns--; |
9555 | for (empty = 1, i = 0; i < 8; i++) |
9556 | if (tstate->enabled_luns[i] != NULL((void *)0)) { |
9557 | empty = 0; |
9558 | break; |
9559 | } |
9560 | |
9561 | if (empty) { |
9562 | ahd_free_tstate(ahd, target, channel, |
9563 | /*force*/FALSE0); |
9564 | if (ahd->features & AHD_MULTI_TID) { |
9565 | u_int targid_mask; |
9566 | |
9567 | targid_mask = ahd_inw(ahd, TARGID0x0f); |
9568 | targid_mask &= ~target_mask; |
9569 | ahd_outw(ahd, TARGID0x0f, targid_mask); |
9570 | ahd_update_scsiid(ahd, targid_mask); |
9571 | } |
9572 | } |
9573 | } else { |
9574 | |
9575 | ahd->black_hole = NULL((void *)0); |
9576 | |
9577 | /* |
9578 | * We can't allow selections without |
9579 | * our black hole device. |
9580 | */ |
9581 | empty = TRUE1; |
9582 | } |
9583 | if (ahd->enabled_luns == 0) { |
9584 | /* Disallow select-in */ |
9585 | u_int scsiseq1; |
9586 | |
9587 | scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE)(((ahd)->tags[(0x14b) >> 8])->read_1(((ahd)->bshs [(0x14b) >> 8]), ((0x14b) & 0xFF))); |
9588 | scsiseq1 &= ~ENSELI0x20; |
9589 | ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq1)(((ahd)->tags[(0x14b) >> 8])->write_1(((ahd)-> bshs[(0x14b) >> 8]), ((0x14b) & 0xFF), (scsiseq1))); |
9590 | scsiseq1 = ahd_inb(ahd, SCSISEQ1)(((ahd)->tags[(0x3b) >> 8])->read_1(((ahd)->bshs [(0x3b) >> 8]), ((0x3b) & 0xFF))); |
9591 | scsiseq1 &= ~ENSELI0x20; |
9592 | ahd_outb(ahd, SCSISEQ1, scsiseq1)(((ahd)->tags[(0x3b) >> 8])->write_1(((ahd)->bshs [(0x3b) >> 8]), ((0x3b) & 0xFF), (scsiseq1))); |
9593 | |
9594 | if ((ahd->features & AHD_MULTIROLE) == 0) { |
9595 | printf("Configuring Initiator Mode\n"); |
9596 | ahd->flags &= ~AHD_TARGETROLE; |
9597 | ahd->flags |= AHD_INITIATORROLE; |
9598 | ahd_pause(ahd); |
9599 | ahd_loadseq(ahd); |
9600 | ahd_restart(ahd); |
9601 | /* |
9602 | * Unpaused. The extra unpause |
9603 | * that follows is harmless. |
9604 | */ |
9605 | } |
9606 | } |
9607 | ahd_unpause(ahd); |
9608 | ahd_unlock(ahd, &s)spllower(*(&s)); |
9609 | } |
9610 | #endif |
9611 | } |
9612 | |
9613 | void |
9614 | ahd_update_scsiid(struct ahd_softc *ahd, u_int targid_mask) |
9615 | { |
9616 | #if NOT_YET |
9617 | u_int scsiid_mask; |
9618 | u_int scsiid; |
9619 | |
9620 | if ((ahd->features & AHD_MULTI_TID) == 0) |
9621 | panic("ahd_update_scsiid called on non-multitid unit"); |
9622 | |
9623 | /* |
9624 | * Since we will rely on the TARGID mask |
9625 | * for selection enables, ensure that OID |
9626 | * in SCSIID is not set to some other ID |
9627 | * that we don't want to allow selections on. |
9628 | */ |
9629 | if ((ahd->features & AHD_ULTRA2) != 0) |
9630 | scsiid = ahd_inb(ahd, SCSIID_ULTRA2)(((ahd)->tags[(SCSIID_ULTRA2) >> 8])->read_1(((ahd )->bshs[(SCSIID_ULTRA2) >> 8]), ((SCSIID_ULTRA2) & 0xFF))); |
9631 | else |
9632 | scsiid = ahd_inb(ahd, SCSIID)(((ahd)->tags[(SCSIID) >> 8])->read_1(((ahd)-> bshs[(SCSIID) >> 8]), ((SCSIID) & 0xFF))); |
9633 | scsiid_mask = 0x1 << (scsiid & OID0x0f); |
9634 | if ((targid_mask & scsiid_mask) == 0) { |
9635 | u_int our_id; |
9636 | |
9637 | /* ffs counts from 1 */ |
9638 | our_id = ffs(targid_mask); |
9639 | if (our_id == 0) |
9640 | our_id = ahd->our_id; |
9641 | else |
9642 | our_id--; |
9643 | scsiid &= TID0xf0; |
9644 | scsiid |= our_id; |
9645 | } |
9646 | if ((ahd->features & AHD_ULTRA2) != 0) |
9647 | ahd_outb(ahd, SCSIID_ULTRA2, scsiid)(((ahd)->tags[(SCSIID_ULTRA2) >> 8])->write_1(((ahd )->bshs[(SCSIID_ULTRA2) >> 8]), ((SCSIID_ULTRA2) & 0xFF), (scsiid))); |
9648 | else |
9649 | ahd_outb(ahd, SCSIID, scsiid)(((ahd)->tags[(SCSIID) >> 8])->write_1(((ahd)-> bshs[(SCSIID) >> 8]), ((SCSIID) & 0xFF), (scsiid))); |
9650 | #endif |
9651 | } |
9652 | |
9653 | void |
9654 | ahd_run_tqinfifo(struct ahd_softc *ahd, int paused) |
9655 | { |
9656 | struct target_cmd *cmd; |
9657 | |
9658 | ahd_sync_tqinfifo(ahd, BUS_DMASYNC_POSTREAD0x02); |
9659 | while ((cmd = &ahd->targetcmds[ahd->tqinfifonext])->cmd_valid != 0) { |
9660 | |
9661 | /* |
9662 | * Only advance through the queue if we |
9663 | * have the resources to process the command. |
9664 | */ |
9665 | if (ahd_handle_target_cmd(ahd, cmd) != 0) |
9666 | break; |
9667 | |
9668 | cmd->cmd_valid = 0; |
9669 | ahd_dmamap_sync(ahd, ahd->parent_dmat /*shared_data_dmat*/,(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (ahd->shared_data_dmamap), (ahd_targetcmd_offset(ahd, ahd ->tqinfifonext)), (sizeof(struct target_cmd)), (0x01)) |
9670 | ahd->shared_data_dmamap,(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (ahd->shared_data_dmamap), (ahd_targetcmd_offset(ahd, ahd ->tqinfifonext)), (sizeof(struct target_cmd)), (0x01)) |
9671 | ahd_targetcmd_offset(ahd, ahd->tqinfifonext),(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (ahd->shared_data_dmamap), (ahd_targetcmd_offset(ahd, ahd ->tqinfifonext)), (sizeof(struct target_cmd)), (0x01)) |
9672 | sizeof(struct target_cmd),(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (ahd->shared_data_dmamap), (ahd_targetcmd_offset(ahd, ahd ->tqinfifonext)), (sizeof(struct target_cmd)), (0x01)) |
9673 | BUS_DMASYNC_PREREAD)(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (ahd->shared_data_dmamap), (ahd_targetcmd_offset(ahd, ahd ->tqinfifonext)), (sizeof(struct target_cmd)), (0x01)); |
9674 | ahd->tqinfifonext++; |
9675 | |
9676 | /* |
9677 | * Lazily update our position in the target mode incoming |
9678 | * command queue as seen by the sequencer. |
9679 | */ |
9680 | if ((ahd->tqinfifonext & (HOST_TQINPOS0x80 - 1)) == 1) { |
9681 | u_int hs_mailbox; |
9682 | |
9683 | hs_mailbox = ahd_inb(ahd, HS_MAILBOX)(((ahd)->tags[(0x0b) >> 8])->read_1(((ahd)->bshs [(0x0b) >> 8]), ((0x0b) & 0xFF))); |
9684 | hs_mailbox &= ~HOST_TQINPOS0x80; |
9685 | hs_mailbox |= ahd->tqinfifonext & HOST_TQINPOS0x80; |
9686 | ahd_outb(ahd, HS_MAILBOX, hs_mailbox)(((ahd)->tags[(0x0b) >> 8])->write_1(((ahd)->bshs [(0x0b) >> 8]), ((0x0b) & 0xFF), (hs_mailbox))); |
9687 | } |
9688 | } |
9689 | } |
9690 | |
9691 | int |
9692 | ahd_handle_target_cmd(struct ahd_softc *ahd, struct target_cmd *cmd) |
9693 | { |
9694 | struct ahd_tmode_tstate *tstate; |
9695 | struct ahd_tmode_lstate *lstate; |
9696 | struct ccb_accept_tio *atio; |
9697 | uint8_t *byte; |
9698 | int initiator; |
9699 | int target; |
9700 | int lun; |
9701 | |
9702 | initiator = SCSIID_TARGET(ahd, cmd->scsiid)(((cmd->scsiid) & 0xf0) >> 0x04); |
9703 | target = SCSIID_OUR_ID(cmd->scsiid)((cmd->scsiid) & 0x0f); |
9704 | lun = (cmd->identify & MSG_IDENTIFY_LUNMASK0x01F); |
9705 | |
9706 | byte = cmd->bytes; |
9707 | tstate = ahd->enabled_targets[target]; |
9708 | lstate = NULL((void *)0); |
9709 | if (tstate != NULL((void *)0)) |
9710 | lstate = tstate->enabled_luns[lun]; |
9711 | |
9712 | /* |
9713 | * Commands for disabled luns go to the black hole driver. |
9714 | */ |
9715 | if (lstate == NULL((void *)0)) |
9716 | lstate = ahd->black_hole; |
9717 | |
9718 | atio = (struct ccb_accept_tio*)SLIST_FIRST(&lstate->accept_tios)((&lstate->accept_tios)->slh_first); |
9719 | if (atio == NULL((void *)0)) { |
9720 | ahd->flags |= AHD_TQINFIFO_BLOCKED; |
9721 | /* |
9722 | * Wait for more ATIOs from the peripheral driver for this lun. |
9723 | */ |
9724 | return (1); |
9725 | } else |
9726 | ahd->flags &= ~AHD_TQINFIFO_BLOCKED; |
9727 | #ifdef AHD_DEBUG |
9728 | if ((ahd_debug & AHD_SHOW_TQIN) != 0) |
9729 | printf("Incoming command from %d for %d:%d%s\n", |
9730 | initiator, target, lun, |
9731 | lstate == ahd->black_hole ? "(Black Holed)" : ""); |
9732 | #endif |
9733 | SLIST_REMOVE_HEAD(&lstate->accept_tios, sim_links.sle)do { (&lstate->accept_tios)->slh_first = (&lstate ->accept_tios)->slh_first->sim_links.sle.sle_next; } while (0); |
9734 | |
9735 | if (lstate == ahd->black_hole) { |
9736 | /* Fill in the wildcards */ |
9737 | atio->ccb_h.target_id = target; |
9738 | atio->ccb_h.target_lun = lun; |
9739 | } |
9740 | |
9741 | /* |
9742 | * Package it up and send it off to |
9743 | * whomever has this lun enabled. |
9744 | */ |
9745 | atio->sense_len = 0; |
9746 | atio->init_id = initiator; |
9747 | if (byte[0] != 0xFF) { |
9748 | /* Tag was included */ |
9749 | atio->tag_action = *byte++; |
9750 | atio->tag_id = *byte++; |
9751 | atio->ccb_h.flags = CAM_TAG_ACTION_VALID; |
9752 | } else { |
9753 | atio->ccb_h.flags = 0; |
9754 | } |
9755 | byte++; |
9756 | |
9757 | /* Okay. Now determine the cdb size based on the command code */ |
9758 | switch (*byte >> CMD_GROUP_CODE_SHIFT0x05) { |
9759 | case 0: |
9760 | atio->cdb_len = 6; |
9761 | break; |
9762 | case 1: |
9763 | case 2: |
9764 | atio->cdb_len = 10; |
9765 | break; |
9766 | case 4: |
9767 | atio->cdb_len = 16; |
9768 | break; |
9769 | case 5: |
9770 | atio->cdb_len = 12; |
9771 | break; |
9772 | case 3: |
9773 | default: |
9774 | /* Only copy the opcode. */ |
9775 | atio->cdb_len = 1; |
9776 | printf("Reserved or VU command code type encountered\n"); |
9777 | break; |
9778 | } |
9779 | |
9780 | memcpy(atio->cdb_io.cdb_bytes, byte, atio->cdb_len)__builtin_memcpy((atio->cdb_io.cdb_bytes), (byte), (atio-> cdb_len)); |
9781 | |
9782 | atio->ccb_h.status |= CAM_CDB_RECVD; |
9783 | |
9784 | if ((cmd->identify & MSG_IDENTIFY_DISCFLAG0x40) == 0) { |
9785 | /* |
9786 | * We weren't allowed to disconnect. |
9787 | * We're hanging on the bus until a |
9788 | * continue target I/O comes in response |
9789 | * to this accept tio. |
9790 | */ |
9791 | #ifdef AHD_DEBUG |
9792 | if ((ahd_debug & AHD_SHOW_TQIN) != 0) |
9793 | printf("Received Immediate Command %d:%d:%d - %p\n", |
9794 | initiator, target, lun, ahd->pending_device); |
9795 | #endif |
9796 | ahd->pending_device = lstate; |
9797 | ahd_freeze_ccb((union ccb *)atio); |
9798 | atio->ccb_h.flags |= CAM_DIS_DISCONNECT; |
9799 | } |
9800 | xpt_done((union ccb*)atio); |
9801 | return (0); |
9802 | } |
9803 | |
9804 | #endif |
9805 | |
9806 | int |
9807 | ahd_createdmamem(struct ahd_softc *ahd, size_t size, struct map_node *map, |
9808 | const char *what) |
9809 | { |
9810 | bus_dma_tag_t tag = ahd->parent_dmat; |
9811 | int nseg, error; |
9812 | |
9813 | bzero(map, sizeof(*map))__builtin_bzero((map), (sizeof(*map))); |
9814 | |
9815 | if ((error = bus_dmamap_create(tag, size, 1, size, 0, BUS_DMA_NOWAIT,(*(tag)->_dmamap_create)((tag), (size), (1), (size), (0), ( 0x0001), (&map->dmamap)) |
9816 | &map->dmamap)(*(tag)->_dmamap_create)((tag), (size), (1), (size), (0), ( 0x0001), (&map->dmamap))) != 0) { |
9817 | printf("%s: failed to create DMA map for %s, error = %d\n", |
9818 | ahd_name(ahd), what, error); |
9819 | return (error); |
9820 | } |
9821 | |
9822 | if ((error = bus_dmamem_alloc(tag, size, PAGE_SIZE, 0, &map->dmaseg,(*(tag)->_dmamem_alloc)((tag), (size), ((1 << 12)), ( 0), (&map->dmaseg), (1), (&nseg), (0x0001)) |
9823 | 1, &nseg, BUS_DMA_NOWAIT)(*(tag)->_dmamem_alloc)((tag), (size), ((1 << 12)), ( 0), (&map->dmaseg), (1), (&nseg), (0x0001))) != 0) { |
9824 | printf("%s: failed to allocate DMA mem for %s, error = %d\n", |
9825 | ahd_name(ahd), what, error); |
9826 | goto destroy; |
9827 | } |
9828 | |
9829 | if ((error = bus_dmamem_map(tag, &map->dmaseg, nseg, size,(*(tag)->_dmamem_map)((tag), (&map->dmaseg), (nseg) , (size), ((caddr_t *)&map->vaddr), (0x0001|0x0004)) |
9830 | (caddr_t *)&map->vaddr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)(*(tag)->_dmamem_map)((tag), (&map->dmaseg), (nseg) , (size), ((caddr_t *)&map->vaddr), (0x0001|0x0004))) != 0) { |
9831 | printf("%s: failed to map DMA mem for %s, error = %d\n", |
9832 | ahd_name(ahd), what, error); |
9833 | goto free; |
9834 | } |
9835 | |
9836 | if ((error = bus_dmamap_load(tag, map->dmamap, map->vaddr, size, NULL,(*(tag)->_dmamap_load)((tag), (map->dmamap), (map->vaddr ), (size), (((void *)0)), (0x0001)) |
9837 | BUS_DMA_NOWAIT)(*(tag)->_dmamap_load)((tag), (map->dmamap), (map->vaddr ), (size), (((void *)0)), (0x0001))) != 0) { |
9838 | printf("%s: failed to load DMA map for %s, error = %d\n", |
9839 | ahd_name(ahd), what, error); |
9840 | goto unmap; |
9841 | } |
9842 | |
9843 | map->size = size; |
9844 | map->busaddr = map->dmamap->dm_segs[0].ds_addr; |
9845 | return (0); |
9846 | |
9847 | unmap: |
9848 | bus_dmamem_unmap(tag, map->vaddr, size)(*(tag)->_dmamem_unmap)((tag), (map->vaddr), (size)); |
9849 | free: |
9850 | bus_dmamem_free(tag, &map->dmaseg, 1)(*(tag)->_dmamem_free)((tag), (&map->dmaseg), (1)); |
9851 | destroy: |
9852 | bus_dmamap_destroy(tag, map->dmamap)(*(tag)->_dmamap_destroy)((tag), (map->dmamap)); |
9853 | |
9854 | bzero(map, sizeof(*map))__builtin_bzero((map), (sizeof(*map))); |
9855 | return (error); |
9856 | } |
9857 | |
9858 | void |
9859 | ahd_freedmamem(struct ahd_softc* ahd, struct map_node *map) |
9860 | { |
9861 | bus_dma_tag_t tag = ahd->parent_dmat; |
9862 | |
9863 | bus_dmamap_unload(tag, map->dmamap)(*(tag)->_dmamap_unload)((tag), (map->dmamap)); |
9864 | bus_dmamem_unmap(tag, map->vaddr, map->size)(*(tag)->_dmamem_unmap)((tag), (map->vaddr), (map->size )); |
9865 | bus_dmamem_free(tag, &map->dmaseg, 1)(*(tag)->_dmamem_free)((tag), (&map->dmaseg), (1)); |
9866 | bus_dmamap_destroy(tag, map->dmamap)(*(tag)->_dmamap_destroy)((tag), (map->dmamap)); |
9867 | } |
9868 | |
9869 | char * |
9870 | ahd_name(struct ahd_softc *ahd) |
9871 | { |
9872 | return (ahd->name); |
9873 | } |
9874 | |
9875 | void |
9876 | ahd_known_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst) |
9877 | { |
9878 | ahd->src_mode = src; |
9879 | ahd->dst_mode = dst; |
9880 | ahd->saved_src_mode = src; |
9881 | ahd->saved_dst_mode = dst; |
9882 | } |
9883 | |
9884 | ahd_mode_state |
9885 | ahd_build_mode_state(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst) |
9886 | { |
9887 | return ((src << SRC_MODE_SHIFT0x00) | (dst << DST_MODE_SHIFT0x04)); |
9888 | } |
9889 | |
9890 | void |
9891 | ahd_extract_mode_state(struct ahd_softc *ahd, ahd_mode_state state, |
9892 | ahd_mode *src, ahd_mode *dst) |
9893 | { |
9894 | *src = (state & SRC_MODE0x07) >> SRC_MODE_SHIFT0x00; |
9895 | *dst = (state & DST_MODE0x70) >> DST_MODE_SHIFT0x04; |
9896 | } |
9897 | |
9898 | void |
9899 | ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst) |
9900 | { |
9901 | if (ahd->src_mode == src && ahd->dst_mode == dst) |
9902 | return; |
9903 | #ifdef AHD_DEBUG |
9904 | if (ahd->src_mode == AHD_MODE_UNKNOWN |
9905 | || ahd->dst_mode == AHD_MODE_UNKNOWN) |
9906 | panic("Setting mode prior to saving it."); |
9907 | if ((ahd_debug & AHD_SHOW_MODEPTR) != 0) |
9908 | printf("%s: Setting mode 0x%x\n", ahd_name(ahd), |
9909 | ahd_build_mode_state(ahd, src, dst)); |
9910 | #endif |
9911 | ahd_outb(ahd, MODE_PTR, ahd_build_mode_state(ahd, src, dst))(((ahd)->tags[(0x00) >> 8])->write_1(((ahd)->bshs [(0x00) >> 8]), ((0x00) & 0xFF), (ahd_build_mode_state (ahd, src, dst)))); |
9912 | ahd->src_mode = src; |
9913 | ahd->dst_mode = dst; |
9914 | } |
9915 | |
9916 | void |
9917 | ahd_update_modes(struct ahd_softc *ahd) |
9918 | { |
9919 | ahd_mode_state mode_ptr; |
9920 | ahd_mode src; |
9921 | ahd_mode dst; |
9922 | |
9923 | mode_ptr = ahd_inb(ahd, MODE_PTR)(((ahd)->tags[(0x00) >> 8])->read_1(((ahd)->bshs [(0x00) >> 8]), ((0x00) & 0xFF))); |
9924 | #ifdef AHD_DEBUG |
9925 | if ((ahd_debug & AHD_SHOW_MODEPTR) != 0) |
9926 | printf("Reading mode 0x%x\n", mode_ptr); |
9927 | #endif |
9928 | ahd_extract_mode_state(ahd, mode_ptr, &src, &dst); |
9929 | ahd_known_modes(ahd, src, dst); |
9930 | } |
9931 | |
9932 | void |
9933 | ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode, |
9934 | ahd_mode dstmode, const char *file, int line) |
9935 | { |
9936 | #ifdef AHD_DEBUG |
9937 | if ((srcmode & AHD_MK_MSK(ahd->src_mode)(0x01 << (ahd->src_mode))) == 0 |
9938 | || (dstmode & AHD_MK_MSK(ahd->dst_mode)(0x01 << (ahd->dst_mode))) == 0) { |
9939 | panic("%s:%s:%d: Mode assertion failed.", |
9940 | ahd_name(ahd), file, line); |
9941 | } |
9942 | #endif |
9943 | } |
9944 | |
9945 | ahd_mode_state |
9946 | ahd_save_modes(struct ahd_softc *ahd) |
9947 | { |
9948 | if (ahd->src_mode == AHD_MODE_UNKNOWN |
9949 | || ahd->dst_mode == AHD_MODE_UNKNOWN) |
9950 | ahd_update_modes(ahd); |
9951 | |
9952 | return (ahd_build_mode_state(ahd, ahd->src_mode, ahd->dst_mode)); |
9953 | } |
9954 | |
9955 | void |
9956 | ahd_restore_modes(struct ahd_softc *ahd, ahd_mode_state state) |
9957 | { |
9958 | ahd_mode src; |
9959 | ahd_mode dst; |
9960 | |
9961 | ahd_extract_mode_state(ahd, state, &src, &dst); |
9962 | ahd_set_modes(ahd, src, dst); |
9963 | } |
9964 | |
9965 | /* |
9966 | * Determine whether the sequencer has halted code execution. |
9967 | * Returns non-zero status if the sequencer is stopped. |
9968 | */ |
9969 | int |
9970 | ahd_is_paused(struct ahd_softc *ahd) |
9971 | { |
9972 | return ((ahd_inb(ahd, HCNTRL)(((ahd)->tags[(0x05) >> 8])->read_1(((ahd)->bshs [(0x05) >> 8]), ((0x05) & 0xFF))) & PAUSE0x04) != 0); |
9973 | } |
9974 | |
9975 | /* |
9976 | * Request that the sequencer stop and wait, indefinitely, for it |
9977 | * to stop. The sequencer will only acknowledge that it is paused |
9978 | * once it has reached an instruction boundary and PAUSEDIS is |
9979 | * cleared in the SEQCTL register. The sequencer may use PAUSEDIS |
9980 | * for critical sections. |
9981 | */ |
9982 | void |
9983 | ahd_pause(struct ahd_softc *ahd) |
9984 | { |
9985 | ahd_outb(ahd, HCNTRL, ahd->pause)(((ahd)->tags[(0x05) >> 8])->write_1(((ahd)->bshs [(0x05) >> 8]), ((0x05) & 0xFF), (ahd->pause))); |
9986 | |
9987 | /* |
9988 | * Since the sequencer can disable pausing in a critical section, we |
9989 | * must loop until it actually stops. |
9990 | */ |
9991 | while (ahd_is_paused(ahd) == 0) |
9992 | ; |
9993 | } |
9994 | |
9995 | /* |
9996 | * Allow the sequencer to continue program execution. |
9997 | * We check here to ensure that no additional interrupt |
9998 | * sources that would cause the sequencer to halt have been |
9999 | * asserted. If, for example, a SCSI bus reset is detected |
10000 | * while we are fielding a different, pausing, interrupt type, |
10001 | * we don't want to release the sequencer before going back |
10002 | * into our interrupt handler and dealing with this new |
10003 | * condition. |
10004 | */ |
10005 | void |
10006 | ahd_unpause(struct ahd_softc *ahd) |
10007 | { |
10008 | /* |
10009 | * Automatically restore our modes to those saved |
10010 | * prior to the first change of the mode. |
10011 | */ |
10012 | if (ahd->saved_src_mode != AHD_MODE_UNKNOWN |
10013 | && ahd->saved_dst_mode != AHD_MODE_UNKNOWN) { |
10014 | if ((ahd->flags & AHD_UPDATE_PEND_CMDS) != 0) |
10015 | ahd_reset_cmds_pending(ahd); |
10016 | ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode); |
10017 | } |
10018 | |
10019 | if ((ahd_inb(ahd, INTSTAT)(((ahd)->tags[(0x01) >> 8])->read_1(((ahd)->bshs [(0x01) >> 8]), ((0x01) & 0xFF))) & ~CMDCMPLT0x02) == 0) |
10020 | ahd_outb(ahd, HCNTRL, ahd->unpause)(((ahd)->tags[(0x05) >> 8])->write_1(((ahd)->bshs [(0x05) >> 8]), ((0x05) & 0xFF), (ahd->unpause)) ); |
10021 | |
10022 | ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN); |
10023 | } |
10024 | |
10025 | void * |
10026 | ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb, |
10027 | void *sgptr, bus_addr_t addr, bus_size_t len, int last) |
10028 | { |
10029 | scb->sg_count++; |
10030 | if (sizeof(bus_addr_t) > 4 |
10031 | && (ahd->flags & AHD_64BIT_ADDRESSING) != 0) { |
10032 | struct ahd_dma64_seg *sg; |
10033 | |
10034 | sg = (struct ahd_dma64_seg *)sgptr; |
10035 | sg->addr = aic_htole64(addr)((__uint64_t)(addr)); |
10036 | sg->len = aic_htole32(len | (last ? AHD_DMA_LAST_SEG : 0))((__uint32_t)(len | (last ? 0x80000000 : 0))); |
10037 | return (sg + 1); |
10038 | } else { |
10039 | struct ahd_dma_seg *sg; |
10040 | |
10041 | sg = (struct ahd_dma_seg *)sgptr; |
10042 | sg->addr = aic_htole32(addr & 0xFFFFFFFF)((__uint32_t)(addr & 0xFFFFFFFF)); |
10043 | sg->len = aic_htole32(len | ((addr >> 8) & 0x7F000000)((__uint32_t)(len | ((addr >> 8) & 0x7F000000) | (last ? 0x80000000 : 0))) |
10044 | | (last ? AHD_DMA_LAST_SEG : 0))((__uint32_t)(len | ((addr >> 8) & 0x7F000000) | (last ? 0x80000000 : 0))); |
10045 | return (sg + 1); |
10046 | } |
10047 | } |
10048 | |
10049 | void |
10050 | ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb) |
10051 | { |
10052 | /* XXX Handle target mode SCBs. */ |
10053 | scb->crc_retry_count = 0; |
10054 | if ((scb->flags & SCB_PACKETIZED) != 0) { |
10055 | /* XXX what about ACA?? It is type 4, but TAG_TYPE == 0x3. */ |
10056 | scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE0x03; |
10057 | } else { |
10058 | if (aic_get_transfer_length(scb)((scb)->xs->datalen) & 0x01) |
10059 | scb->hscb->task_attribute = SCB_XFERLEN_ODD0x01; |
10060 | else |
10061 | scb->hscb->task_attribute = 0; |
10062 | } |
10063 | |
10064 | if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR(16 - sizeof(sense_addr_t)) |
10065 | || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR0x80) != 0) |
10066 | scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr = |
10067 | aic_htole32(scb->sense_busaddr)((__uint32_t)(scb->sense_busaddr)); |
10068 | } |
10069 | |
10070 | void |
10071 | ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb) |
10072 | { |
10073 | /* |
10074 | * Copy the first SG into the "current" data pointer area. |
10075 | */ |
10076 | if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) { |
10077 | struct ahd_dma64_seg *sg; |
10078 | |
10079 | sg = (struct ahd_dma64_seg *)scb->sg_list; |
10080 | scb->hscb->dataptr = sg->addr; |
10081 | scb->hscb->datacnt = sg->len; |
10082 | } else { |
10083 | struct ahd_dma_seg *sg; |
10084 | uint32_t *dataptr_words; |
10085 | |
10086 | sg = (struct ahd_dma_seg *)scb->sg_list; |
10087 | dataptr_words = (uint32_t*)&scb->hscb->dataptr; |
10088 | dataptr_words[0] = sg->addr; |
10089 | dataptr_words[1] = 0; |
10090 | if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) { |
10091 | uint64_t high_addr; |
10092 | |
10093 | high_addr = aic_le32toh(sg->len)((__uint32_t)(sg->len)) & 0x7F000000; |
10094 | scb->hscb->dataptr |= aic_htole64(high_addr << 8)((__uint64_t)(high_addr << 8)); |
10095 | } |
10096 | scb->hscb->datacnt = sg->len; |
10097 | } |
10098 | /* |
10099 | * Note where to find the SG entries in bus space. |
10100 | * We also set the full residual flag which the |
10101 | * sequencer will clear as soon as a data transfer |
10102 | * occurs. |
10103 | */ |
10104 | scb->hscb->sgptr = aic_htole32(scb->sg_list_busaddr|SG_FULL_RESID)((__uint32_t)(scb->sg_list_busaddr|0x02)); |
10105 | } |
10106 | |
10107 | void |
10108 | ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb) |
10109 | { |
10110 | scb->hscb->sgptr = aic_htole32(SG_LIST_NULL)((__uint32_t)(0x01)); |
10111 | scb->hscb->dataptr = 0; |
10112 | scb->hscb->datacnt = 0; |
10113 | } |
10114 | |
10115 | size_t |
10116 | ahd_sg_size(struct ahd_softc *ahd) |
10117 | { |
10118 | if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) |
10119 | return (sizeof(struct ahd_dma64_seg)); |
10120 | return (sizeof(struct ahd_dma_seg)); |
10121 | } |
10122 | |
10123 | void * |
10124 | ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr) |
10125 | { |
10126 | bus_addr_t sg_offset; |
10127 | |
10128 | /* sg_list_phys points to entry 1, not 0 */ |
10129 | sg_offset = sg_busaddr - (scb->sg_list_busaddr - ahd_sg_size(ahd)); |
10130 | return ((uint8_t *)scb->sg_list + sg_offset); |
10131 | } |
10132 | |
10133 | uint32_t |
10134 | ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg) |
10135 | { |
10136 | bus_addr_t sg_offset; |
10137 | |
10138 | /* sg_list_phys points to entry 1, not 0 */ |
10139 | sg_offset = ((uint8_t *)sg - (uint8_t *)scb->sg_list) |
10140 | - ahd_sg_size(ahd); |
10141 | |
10142 | return (scb->sg_list_busaddr + sg_offset); |
10143 | } |
10144 | |
10145 | void |
10146 | ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op) |
10147 | { |
10148 | ahd_dmamap_sync(ahd, ahd->parent_dmat, scb->hscb_map->dmamap,(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (scb->hscb_map->dmamap), ((uint8_t*)scb->hscb - scb ->hscb_map->vaddr), (sizeof(*scb->hscb)), (op)) |
10149 | /*offset*/(uint8_t*)scb->hscb - scb->hscb_map->vaddr,(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (scb->hscb_map->dmamap), ((uint8_t*)scb->hscb - scb ->hscb_map->vaddr), (sizeof(*scb->hscb)), (op)) |
10150 | /*len*/sizeof(*scb->hscb), op)(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (scb->hscb_map->dmamap), ((uint8_t*)scb->hscb - scb ->hscb_map->vaddr), (sizeof(*scb->hscb)), (op)); |
10151 | } |
10152 | |
10153 | void |
10154 | ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op) |
10155 | { |
10156 | if (scb->sg_count == 0) |
10157 | return; |
10158 | |
10159 | ahd_dmamap_sync(ahd, ahd->parent_dmat,(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (scb->sense_map->dmamap), (scb->sg_list_busaddr - ahd_sg_size(ahd)), (ahd_sg_size(ahd) * scb->sg_count), (op )) |
10160 | scb->sense_map->dmamap,(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (scb->sense_map->dmamap), (scb->sg_list_busaddr - ahd_sg_size(ahd)), (ahd_sg_size(ahd) * scb->sg_count), (op )) |
10161 | /*offset*/scb->sg_list_busaddr - ahd_sg_size(ahd),(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (scb->sense_map->dmamap), (scb->sg_list_busaddr - ahd_sg_size(ahd)), (ahd_sg_size(ahd) * scb->sg_count), (op )) |
10162 | /*len*/ahd_sg_size(ahd) * scb->sg_count, op)(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (scb->sense_map->dmamap), (scb->sg_list_busaddr - ahd_sg_size(ahd)), (ahd_sg_size(ahd) * scb->sg_count), (op )); |
10163 | } |
10164 | |
10165 | void |
10166 | ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op) |
10167 | { |
10168 | ahd_dmamap_sync(ahd, ahd->parent_dmat,(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (scb->sense_map->dmamap), (scb->sense_busaddr), ( 0x100), (op)) |
10169 | scb->sense_map->dmamap,(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (scb->sense_map->dmamap), (scb->sense_busaddr), ( 0x100), (op)) |
10170 | /*offset*/scb->sense_busaddr,(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (scb->sense_map->dmamap), (scb->sense_busaddr), ( 0x100), (op)) |
10171 | /*len*/AHD_SENSE_BUFSIZE, op)(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (scb->sense_map->dmamap), (scb->sense_busaddr), ( 0x100), (op)); |
10172 | } |
10173 | |
10174 | uint32_t |
10175 | ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index) |
10176 | { |
10177 | return (((uint8_t *)&ahd->targetcmds[index]) |
10178 | - (uint8_t *)ahd->qoutfifo); |
10179 | } |
10180 | |
10181 | void |
10182 | ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb) |
10183 | { |
10184 | uint32_t sgptr; |
10185 | |
10186 | sgptr = aic_le32toh(scb->hscb->sgptr)((__uint32_t)(scb->hscb->sgptr)); |
10187 | if ((sgptr & SG_STATUS_VALID0x04) != 0) |
10188 | ahd_handle_scb_status(ahd, scb); |
10189 | else |
10190 | ahd_done(ahd, scb); |
10191 | } |
10192 | |
10193 | /* |
10194 | * Determine whether the sequencer reported a residual |
10195 | * for this SCB/transaction. |
10196 | */ |
10197 | void |
10198 | ahd_update_residual(struct ahd_softc *ahd, struct scb *scb) |
10199 | { |
10200 | uint32_t sgptr; |
10201 | |
10202 | sgptr = aic_le32toh(scb->hscb->sgptr)((__uint32_t)(scb->hscb->sgptr)); |
10203 | if ((sgptr & SG_STATUS_VALID0x04) != 0) |
10204 | ahd_calc_residual(ahd, scb); |
10205 | } |
10206 | |
10207 | /* |
10208 | * Return pointers to the transfer negotiation information |
10209 | * for the specified our_id/remote_id pair. |
10210 | */ |
10211 | struct ahd_initiator_tinfo * |
10212 | ahd_fetch_transinfo(struct ahd_softc *ahd, char channel, u_int our_id, |
10213 | u_int remote_id, struct ahd_tmode_tstate **tstate) |
10214 | { |
10215 | /* |
10216 | * Transfer data structures are stored from the perspective |
10217 | * of the target role. Since the parameters for a connection |
10218 | * in the initiator role to a given target are the same as |
10219 | * when the roles are reversed, we pretend we are the target. |
10220 | */ |
10221 | if (channel == 'B') |
10222 | our_id += 8; |
10223 | *tstate = ahd->enabled_targets[our_id]; |
10224 | return (&(*tstate)->transinfo[remote_id]); |
10225 | } |
10226 | |
10227 | #define AHD_COPY_COL_IDX(dst, src)do { dst->hscb->scsiid = src->hscb->scsiid; dst-> hscb->lun = src->hscb->lun; } while (0) \ |
10228 | do { \ |
10229 | dst->hscb->scsiid = src->hscb->scsiid; \ |
10230 | dst->hscb->lun = src->hscb->lun; \ |
10231 | } while (0) |
10232 | |
10233 | uint16_t |
10234 | ahd_inw(struct ahd_softc *ahd, u_int port) |
10235 | { |
10236 | /* |
10237 | * Read high byte first as some registers increment |
10238 | * or have other side effects when the low byte is |
10239 | * read. |
10240 | */ |
10241 | return ((ahd_inb(ahd, port+1)(((ahd)->tags[(port+1) >> 8])->read_1(((ahd)-> bshs[(port+1) >> 8]), ((port+1) & 0xFF))) << 8) | ahd_inb(ahd, port)(((ahd)->tags[(port) >> 8])->read_1(((ahd)->bshs [(port) >> 8]), ((port) & 0xFF)))); |
10242 | } |
10243 | |
10244 | void |
10245 | ahd_outw(struct ahd_softc *ahd, u_int port, u_int value) |
10246 | { |
10247 | /* |
10248 | * Write low byte first to accommodate registers |
10249 | * such as PRGMCNT where the order maters. |
10250 | */ |
10251 | ahd_outb(ahd, port, value & 0xFF)(((ahd)->tags[(port) >> 8])->write_1(((ahd)->bshs [(port) >> 8]), ((port) & 0xFF), (value & 0xFF) )); |
10252 | ahd_outb(ahd, port+1, (value >> 8) & 0xFF)(((ahd)->tags[(port+1) >> 8])->write_1(((ahd)-> bshs[(port+1) >> 8]), ((port+1) & 0xFF), ((value >> 8) & 0xFF))); |
10253 | } |
10254 | |
10255 | uint32_t |
10256 | ahd_inl(struct ahd_softc *ahd, u_int port) |
10257 | { |
10258 | return ((ahd_inb(ahd, port)(((ahd)->tags[(port) >> 8])->read_1(((ahd)->bshs [(port) >> 8]), ((port) & 0xFF)))) |
10259 | | (ahd_inb(ahd, port+1)(((ahd)->tags[(port+1) >> 8])->read_1(((ahd)-> bshs[(port+1) >> 8]), ((port+1) & 0xFF))) << 8) |
10260 | | (ahd_inb(ahd, port+2)(((ahd)->tags[(port+2) >> 8])->read_1(((ahd)-> bshs[(port+2) >> 8]), ((port+2) & 0xFF))) << 16) |
10261 | | (ahd_inb(ahd, port+3)(((ahd)->tags[(port+3) >> 8])->read_1(((ahd)-> bshs[(port+3) >> 8]), ((port+3) & 0xFF))) << 24)); |
10262 | } |
10263 | |
10264 | void |
10265 | ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value) |
10266 | { |
10267 | ahd_outb(ahd, port, (value) & 0xFF)(((ahd)->tags[(port) >> 8])->write_1(((ahd)->bshs [(port) >> 8]), ((port) & 0xFF), ((value) & 0xFF ))); |
10268 | ahd_outb(ahd, port+1, ((value) >> 8) & 0xFF)(((ahd)->tags[(port+1) >> 8])->write_1(((ahd)-> bshs[(port+1) >> 8]), ((port+1) & 0xFF), (((value) >> 8) & 0xFF))); |
10269 | ahd_outb(ahd, port+2, ((value) >> 16) & 0xFF)(((ahd)->tags[(port+2) >> 8])->write_1(((ahd)-> bshs[(port+2) >> 8]), ((port+2) & 0xFF), (((value) >> 16) & 0xFF))); |
10270 | ahd_outb(ahd, port+3, ((value) >> 24) & 0xFF)(((ahd)->tags[(port+3) >> 8])->write_1(((ahd)-> bshs[(port+3) >> 8]), ((port+3) & 0xFF), (((value) >> 24) & 0xFF))); |
10271 | } |
10272 | |
10273 | uint64_t |
10274 | ahd_inq(struct ahd_softc *ahd, u_int port) |
10275 | { |
10276 | return ((ahd_inb(ahd, port)(((ahd)->tags[(port) >> 8])->read_1(((ahd)->bshs [(port) >> 8]), ((port) & 0xFF)))) |
10277 | | (ahd_inb(ahd, port+1)(((ahd)->tags[(port+1) >> 8])->read_1(((ahd)-> bshs[(port+1) >> 8]), ((port+1) & 0xFF))) << 8) |
10278 | | (ahd_inb(ahd, port+2)(((ahd)->tags[(port+2) >> 8])->read_1(((ahd)-> bshs[(port+2) >> 8]), ((port+2) & 0xFF))) << 16) |
10279 | | (ahd_inb(ahd, port+3)(((ahd)->tags[(port+3) >> 8])->read_1(((ahd)-> bshs[(port+3) >> 8]), ((port+3) & 0xFF))) << 24) |
10280 | | (((uint64_t)ahd_inb(ahd, port+4)(((ahd)->tags[(port+4) >> 8])->read_1(((ahd)-> bshs[(port+4) >> 8]), ((port+4) & 0xFF)))) << 32) |
10281 | | (((uint64_t)ahd_inb(ahd, port+5)(((ahd)->tags[(port+5) >> 8])->read_1(((ahd)-> bshs[(port+5) >> 8]), ((port+5) & 0xFF)))) << 40) |
10282 | | (((uint64_t)ahd_inb(ahd, port+6)(((ahd)->tags[(port+6) >> 8])->read_1(((ahd)-> bshs[(port+6) >> 8]), ((port+6) & 0xFF)))) << 48) |
10283 | | (((uint64_t)ahd_inb(ahd, port+7)(((ahd)->tags[(port+7) >> 8])->read_1(((ahd)-> bshs[(port+7) >> 8]), ((port+7) & 0xFF)))) << 56)); |
10284 | } |
10285 | |
10286 | void |
10287 | ahd_outq(struct ahd_softc *ahd, u_int port, uint64_t value) |
10288 | { |
10289 | ahd_outb(ahd, port, value & 0xFF)(((ahd)->tags[(port) >> 8])->write_1(((ahd)->bshs [(port) >> 8]), ((port) & 0xFF), (value & 0xFF) )); |
10290 | ahd_outb(ahd, port+1, (value >> 8) & 0xFF)(((ahd)->tags[(port+1) >> 8])->write_1(((ahd)-> bshs[(port+1) >> 8]), ((port+1) & 0xFF), ((value >> 8) & 0xFF))); |
10291 | ahd_outb(ahd, port+2, (value >> 16) & 0xFF)(((ahd)->tags[(port+2) >> 8])->write_1(((ahd)-> bshs[(port+2) >> 8]), ((port+2) & 0xFF), ((value >> 16) & 0xFF))); |
10292 | ahd_outb(ahd, port+3, (value >> 24) & 0xFF)(((ahd)->tags[(port+3) >> 8])->write_1(((ahd)-> bshs[(port+3) >> 8]), ((port+3) & 0xFF), ((value >> 24) & 0xFF))); |
10293 | ahd_outb(ahd, port+4, (value >> 32) & 0xFF)(((ahd)->tags[(port+4) >> 8])->write_1(((ahd)-> bshs[(port+4) >> 8]), ((port+4) & 0xFF), ((value >> 32) & 0xFF))); |
10294 | ahd_outb(ahd, port+5, (value >> 40) & 0xFF)(((ahd)->tags[(port+5) >> 8])->write_1(((ahd)-> bshs[(port+5) >> 8]), ((port+5) & 0xFF), ((value >> 40) & 0xFF))); |
10295 | ahd_outb(ahd, port+6, (value >> 48) & 0xFF)(((ahd)->tags[(port+6) >> 8])->write_1(((ahd)-> bshs[(port+6) >> 8]), ((port+6) & 0xFF), ((value >> 48) & 0xFF))); |
10296 | ahd_outb(ahd, port+7, (value >> 56) & 0xFF)(((ahd)->tags[(port+7) >> 8])->write_1(((ahd)-> bshs[(port+7) >> 8]), ((port+7) & 0xFF), ((value >> 56) & 0xFF))); |
10297 | } |
10298 | |
10299 | u_int |
10300 | ahd_get_scbptr(struct ahd_softc *ahd) |
10301 | { |
10302 | 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" , 10303); |
10303 | ~(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" , 10303);; |
10304 | return (ahd_inb(ahd, SCBPTR)(((ahd)->tags[(0xa8) >> 8])->read_1(((ahd)->bshs [(0xa8) >> 8]), ((0xa8) & 0xFF))) | (ahd_inb(ahd, SCBPTR + 1)(((ahd)->tags[(0xa8 + 1) >> 8])->read_1(((ahd)-> bshs[(0xa8 + 1) >> 8]), ((0xa8 + 1) & 0xFF))) << 8)); |
10305 | } |
10306 | |
10307 | void |
10308 | ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr) |
10309 | { |
10310 | 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" , 10311); |
10311 | ~(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" , 10311);; |
10312 | ahd_outb(ahd, SCBPTR, scbptr & 0xFF)(((ahd)->tags[(0xa8) >> 8])->write_1(((ahd)->bshs [(0xa8) >> 8]), ((0xa8) & 0xFF), (scbptr & 0xFF ))); |
10313 | ahd_outb(ahd, SCBPTR+1, (scbptr >> 8) & 0xFF)(((ahd)->tags[(0xa8 +1) >> 8])->write_1(((ahd)-> bshs[(0xa8 +1) >> 8]), ((0xa8 +1) & 0xFF), ((scbptr >> 8) & 0xFF))); |
10314 | } |
10315 | |
10316 | u_int |
10317 | ahd_get_hnscb_qoff(struct ahd_softc *ahd) |
10318 | { |
10319 | return (ahd_inw_atomic(ahd, HNSCB_QOFF)((__uint16_t)((((ahd)->tags[(0x06) >> 8])->read_2 (((ahd)->bshs[(0x06) >> 8]), ((0x06) & 0xFF)))))); |
10320 | } |
10321 | |
10322 | void |
10323 | ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value) |
10324 | { |
10325 | ahd_outw_atomic(ahd, HNSCB_QOFF, value)(((ahd)->tags[(0x06) >> 8])->write_2(((ahd)->bshs [(0x06) >> 8]), ((0x06 & 0xFF)), (((__uint16_t)(value ))))); |
10326 | } |
10327 | |
10328 | u_int |
10329 | ahd_get_hescb_qoff(struct ahd_softc *ahd) |
10330 | { |
10331 | return (ahd_inb(ahd, HESCB_QOFF)(((ahd)->tags[(0x08) >> 8])->read_1(((ahd)->bshs [(0x08) >> 8]), ((0x08) & 0xFF)))); |
10332 | } |
10333 | |
10334 | void |
10335 | ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value) |
10336 | { |
10337 | ahd_outb(ahd, HESCB_QOFF, value)(((ahd)->tags[(0x08) >> 8])->write_1(((ahd)->bshs [(0x08) >> 8]), ((0x08) & 0xFF), (value))); |
10338 | } |
10339 | |
10340 | u_int |
10341 | ahd_get_snscb_qoff(struct ahd_softc *ahd) |
10342 | { |
10343 | u_int oldvalue; |
10344 | |
10345 | AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK)ahd_assert_modes(ahd, (0x01 << (AHD_MODE_CCHAN)), (0x01 << (AHD_MODE_CCHAN)), "/usr/src/sys/dev/ic/aic79xx.c", 10345);; |
10346 | oldvalue = ahd_inw(ahd, SNSCB_QOFF0x10); |
10347 | ahd_outw(ahd, SNSCB_QOFF0x10, oldvalue); |
10348 | return (oldvalue); |
10349 | } |
10350 | |
10351 | void |
10352 | ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value) |
10353 | { |
10354 | AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK)ahd_assert_modes(ahd, (0x01 << (AHD_MODE_CCHAN)), (0x01 << (AHD_MODE_CCHAN)), "/usr/src/sys/dev/ic/aic79xx.c", 10354);; |
10355 | ahd_outw(ahd, SNSCB_QOFF0x10, value); |
10356 | } |
10357 | |
10358 | u_int |
10359 | ahd_get_sescb_qoff(struct ahd_softc *ahd) |
10360 | { |
10361 | AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK)ahd_assert_modes(ahd, (0x01 << (AHD_MODE_CCHAN)), (0x01 << (AHD_MODE_CCHAN)), "/usr/src/sys/dev/ic/aic79xx.c", 10361);; |
10362 | return (ahd_inb(ahd, SESCB_QOFF)(((ahd)->tags[(0x12) >> 8])->read_1(((ahd)->bshs [(0x12) >> 8]), ((0x12) & 0xFF)))); |
10363 | } |
10364 | |
10365 | void |
10366 | ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value) |
10367 | { |
10368 | AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK)ahd_assert_modes(ahd, (0x01 << (AHD_MODE_CCHAN)), (0x01 << (AHD_MODE_CCHAN)), "/usr/src/sys/dev/ic/aic79xx.c", 10368);; |
10369 | ahd_outb(ahd, SESCB_QOFF, value)(((ahd)->tags[(0x12) >> 8])->write_1(((ahd)->bshs [(0x12) >> 8]), ((0x12) & 0xFF), (value))); |
10370 | } |
10371 | |
10372 | u_int |
10373 | ahd_get_sdscb_qoff(struct ahd_softc *ahd) |
10374 | { |
10375 | AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK)ahd_assert_modes(ahd, (0x01 << (AHD_MODE_CCHAN)), (0x01 << (AHD_MODE_CCHAN)), "/usr/src/sys/dev/ic/aic79xx.c", 10375);; |
10376 | return (ahd_inb(ahd, SDSCB_QOFF)(((ahd)->tags[(0x14) >> 8])->read_1(((ahd)->bshs [(0x14) >> 8]), ((0x14) & 0xFF))) | (ahd_inb(ahd, SDSCB_QOFF + 1)(((ahd)->tags[(0x14 + 1) >> 8])->read_1(((ahd)-> bshs[(0x14 + 1) >> 8]), ((0x14 + 1) & 0xFF))) << 8)); |
10377 | } |
10378 | |
10379 | void |
10380 | ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value) |
10381 | { |
10382 | AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK)ahd_assert_modes(ahd, (0x01 << (AHD_MODE_CCHAN)), (0x01 << (AHD_MODE_CCHAN)), "/usr/src/sys/dev/ic/aic79xx.c", 10382);; |
10383 | ahd_outb(ahd, SDSCB_QOFF, value & 0xFF)(((ahd)->tags[(0x14) >> 8])->write_1(((ahd)->bshs [(0x14) >> 8]), ((0x14) & 0xFF), (value & 0xFF) )); |
10384 | ahd_outb(ahd, SDSCB_QOFF+1, (value >> 8) & 0xFF)(((ahd)->tags[(0x14 +1) >> 8])->write_1(((ahd)-> bshs[(0x14 +1) >> 8]), ((0x14 +1) & 0xFF), ((value >> 8) & 0xFF))); |
10385 | } |
10386 | |
10387 | u_int |
10388 | ahd_inb_scbram(struct ahd_softc *ahd, u_int offset) |
10389 | { |
10390 | u_int value; |
10391 | |
10392 | /* |
10393 | * Workaround PCI-X Rev A. hardware bug. |
10394 | * After a host read of SCB memory, the chip |
10395 | * may become confused into thinking prefetch |
10396 | * was required. This starts the discard timer |
10397 | * running and can cause an unexpected discard |
10398 | * timer interrupt. The work around is to read |
10399 | * a normal register prior to the exhaustion of |
10400 | * the discard timer. The mode pointer register |
10401 | * has no side effects and so serves well for |
10402 | * this purpose. |
10403 | * |
10404 | * Razor #528 |
10405 | */ |
10406 | value = ahd_inb(ahd, offset)(((ahd)->tags[(offset) >> 8])->read_1(((ahd)-> bshs[(offset) >> 8]), ((offset) & 0xFF))); |
10407 | if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0) |
10408 | ahd_inb(ahd, MODE_PTR)(((ahd)->tags[(0x00) >> 8])->read_1(((ahd)->bshs [(0x00) >> 8]), ((0x00) & 0xFF))); |
10409 | return (value); |
10410 | } |
10411 | |
10412 | u_int |
10413 | ahd_inw_scbram(struct ahd_softc *ahd, u_int offset) |
10414 | { |
10415 | return (ahd_inb_scbram(ahd, offset) |
10416 | | (ahd_inb_scbram(ahd, offset+1) << 8)); |
10417 | } |
10418 | |
10419 | uint32_t |
10420 | ahd_inl_scbram(struct ahd_softc *ahd, u_int offset) |
10421 | { |
10422 | return (ahd_inw_scbram(ahd, offset) |
10423 | | (ahd_inw_scbram(ahd, offset+2) << 16)); |
10424 | } |
10425 | |
10426 | uint64_t |
10427 | ahd_inq_scbram(struct ahd_softc *ahd, u_int offset) |
10428 | { |
10429 | return (ahd_inl_scbram(ahd, offset) |
10430 | | ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32); |
10431 | } |
10432 | |
10433 | struct scb * |
10434 | ahd_lookup_scb(struct ahd_softc *ahd, u_int tag) |
10435 | { |
10436 | struct scb* scb; |
10437 | |
10438 | if (tag >= AHD_SCB_MAX512) |
10439 | return (NULL((void *)0)); |
10440 | scb = ahd->scb_data.scbindex[tag]; |
10441 | if (scb != NULL((void *)0)) |
10442 | ahd_sync_scb(ahd, scb, |
10443 | BUS_DMASYNC_POSTREAD0x02|BUS_DMASYNC_POSTWRITE0x08); |
10444 | return (scb); |
10445 | } |
10446 | |
10447 | void |
10448 | ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) |
10449 | { |
10450 | struct hardware_scb *q_hscb; |
10451 | struct map_node *q_hscb_map; |
10452 | uint32_t saved_hscb_busaddr; |
10453 | |
10454 | /* |
10455 | * Our queuing method is a bit tricky. The card |
10456 | * knows in advance which HSCB (by address) to download, |
10457 | * and we can't disappoint it. To achieve this, the next |
10458 | * HSCB to download is saved off in ahd->next_queued_hscb. |
10459 | * When we are called to queue "an arbitrary scb", |
10460 | * we copy the contents of the incoming HSCB to the one |
10461 | * the sequencer knows about, swap HSCB pointers and |
10462 | * finally assign the SCB to the tag indexed location |
10463 | * in the scb_array. This makes sure that we can still |
10464 | * locate the correct SCB by SCB_TAG. |
10465 | */ |
10466 | q_hscb = ahd->next_queued_hscb; |
10467 | q_hscb_map = ahd->next_queued_hscb_map; |
10468 | saved_hscb_busaddr = q_hscb->hscb_busaddr; |
10469 | memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb))__builtin_memcpy((q_hscb), (scb->hscb), (sizeof(*scb->hscb ))); |
10470 | q_hscb->hscb_busaddr = saved_hscb_busaddr; |
10471 | q_hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr; |
10472 | |
10473 | /* Now swap HSCB pointers. */ |
10474 | ahd->next_queued_hscb = scb->hscb; |
10475 | ahd->next_queued_hscb_map = scb->hscb_map; |
10476 | scb->hscb = q_hscb; |
10477 | scb->hscb_map = q_hscb_map; |
10478 | |
10479 | /* Now define the mapping from tag to SCB in the scbindex */ |
10480 | ahd->scb_data.scbindex[SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag))] = scb; |
10481 | } |
10482 | |
10483 | /* |
10484 | * Tell the sequencer about a new transaction to execute. |
10485 | */ |
10486 | void |
10487 | ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb) |
10488 | { |
10489 | ahd_swap_with_next_hscb(ahd, scb); |
10490 | |
10491 | if (SCBID_IS_NULL(SCB_GET_TAG(scb))(((((__uint16_t)(scb->hscb->tag))) & 0xFF00 ) == 0xFF00 )) |
10492 | panic("Attempt to queue invalid SCB tag %x", |
10493 | SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag))); |
10494 | |
10495 | /* |
10496 | * Keep a history of SCBs we've downloaded in the qinfifo. |
10497 | */ |
10498 | ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)((ahd->qinfifonext) & (512 -1))] = SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)); |
10499 | ahd->qinfifonext++; |
10500 | |
10501 | if (scb->sg_count != 0) |
10502 | ahd_setup_data_scb(ahd, scb); |
10503 | else |
10504 | ahd_setup_noxfer_scb(ahd, scb); |
10505 | ahd_setup_scb_common(ahd, scb); |
10506 | |
10507 | /* |
10508 | * Make sure our data is consistent from the |
10509 | * perspective of the adapter. |
10510 | */ |
10511 | ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD0x01|BUS_DMASYNC_PREWRITE0x04); |
10512 | |
10513 | #ifdef AHD_DEBUG |
10514 | if ((ahd_debug & AHD_SHOW_QUEUE) != 0) { |
10515 | uint64_t host_dataptr; |
10516 | |
10517 | host_dataptr = aic_le64toh(scb->hscb->dataptr)((__uint64_t)(scb->hscb->dataptr)); |
10518 | printf("%s: Queueing SCB %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n", |
10519 | ahd_name(ahd), |
10520 | SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)), scb->hscb->scsiid, |
10521 | aic_le32toh(scb->hscb->hscb_busaddr)((__uint32_t)(scb->hscb->hscb_busaddr)), |
10522 | (u_int)((host_dataptr >> 32) & 0xFFFFFFFF), |
10523 | (u_int)(host_dataptr & 0xFFFFFFFF), |
10524 | aic_le32toh(scb->hscb->datacnt)((__uint32_t)(scb->hscb->datacnt))); |
10525 | } |
10526 | #endif |
10527 | /* Tell the adapter about the newly queued SCB */ |
10528 | ahd_set_hnscb_qoff(ahd, ahd->qinfifonext); |
10529 | } |
10530 | |
10531 | uint8_t * |
10532 | ahd_get_sense_buf(struct ahd_softc *ahd, struct scb *scb) |
10533 | { |
10534 | return (scb->sense_data); |
10535 | } |
10536 | |
10537 | uint32_t |
10538 | ahd_get_sense_bufaddr(struct ahd_softc *ahd, struct scb *scb) |
10539 | { |
10540 | return (scb->sense_busaddr); |
10541 | } |
10542 | |
10543 | void |
10544 | ahd_sync_qoutfifo(struct ahd_softc *ahd, int op) |
10545 | { |
10546 | ahd_dmamap_sync(ahd, ahd->parent_dmat, ahd->shared_data_map.dmamap,(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (ahd->shared_data_map.dmamap), (0), (512 * sizeof(struct ahd_completion)), (op)) |
10547 | /*offset*/0,(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (ahd->shared_data_map.dmamap), (0), (512 * sizeof(struct ahd_completion)), (op)) |
10548 | /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op)(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (ahd->shared_data_map.dmamap), (0), (512 * sizeof(struct ahd_completion)), (op)); |
10549 | } |
10550 | |
10551 | void |
10552 | ahd_sync_tqinfifo(struct ahd_softc *ahd, int op) |
10553 | { |
10554 | #ifdef AHD_TARGET_MODE |
10555 | if ((ahd->flags & AHD_TARGETROLE) != 0) { |
10556 | ahd_dmamap_sync(ahd, ahd->parent_dmat,(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (ahd->shared_data_map.dmamap), (ahd_targetcmd_offset(ahd , 0)), (sizeof(struct target_cmd) * 256), (op)) |
10557 | ahd->shared_data_map.dmamap,(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (ahd->shared_data_map.dmamap), (ahd_targetcmd_offset(ahd , 0)), (sizeof(struct target_cmd) * 256), (op)) |
10558 | ahd_targetcmd_offset(ahd, 0),(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (ahd->shared_data_map.dmamap), (ahd_targetcmd_offset(ahd , 0)), (sizeof(struct target_cmd) * 256), (op)) |
10559 | sizeof(struct target_cmd) * AHD_TMODE_CMDS,(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (ahd->shared_data_map.dmamap), (ahd_targetcmd_offset(ahd , 0)), (sizeof(struct target_cmd) * 256), (op)) |
10560 | op)(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (ahd->shared_data_map.dmamap), (ahd_targetcmd_offset(ahd , 0)), (sizeof(struct target_cmd) * 256), (op)); |
10561 | } |
10562 | #endif |
10563 | } |
10564 | |
10565 | /* |
10566 | * See if the firmware has posted any completed commands |
10567 | * into our in-core command complete fifos. |
10568 | */ |
10569 | #define AHD_RUN_QOUTFIFO0x1 0x1 |
10570 | #define AHD_RUN_TQINFIFO0x2 0x2 |
10571 | u_int |
10572 | ahd_check_cmdcmpltqueues(struct ahd_softc *ahd) |
10573 | { |
10574 | u_int retval; |
10575 | |
10576 | retval = 0; |
10577 | ahd_dmamap_sync(ahd, ahd->parent_dmat, ahd->shared_data_map.dmamap,(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (ahd->shared_data_map.dmamap), (ahd->qoutfifonext * sizeof (*ahd->qoutfifo)), (sizeof(*ahd->qoutfifo)), (0x02)) |
10578 | /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo),(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (ahd->shared_data_map.dmamap), (ahd->qoutfifonext * sizeof (*ahd->qoutfifo)), (sizeof(*ahd->qoutfifo)), (0x02)) |
10579 | /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD)(*(ahd->parent_dmat)->_dmamap_sync)((ahd->parent_dmat ), (ahd->shared_data_map.dmamap), (ahd->qoutfifonext * sizeof (*ahd->qoutfifo)), (sizeof(*ahd->qoutfifo)), (0x02)); |
10580 | if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag |
10581 | == ahd->qoutfifonext_valid_tag) |
10582 | retval |= AHD_RUN_QOUTFIFO0x1; |
10583 | #ifdef AHD_TARGET_MODE |
10584 | if ((ahd->flags & AHD_TARGETROLE) != 0 |
10585 | && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) { |
10586 | ahd_dmamap_sync(ahd, ahd->parent_dmat |
10587 | ahd->shared_data_map.dmamap, |
10588 | ahd_targetcmd_offset(ahd, ahd->tqinfifofnext), |
10589 | /*len*/sizeof(struct target_cmd), |
10590 | BUS_DMASYNC_POSTREAD); |
10591 | if (ahd->targetcmds[ahd->tqinfifonext].cmd_valid != 0) |
10592 | retval |= AHD_RUN_TQINFIFO0x2; |
10593 | } |
10594 | #endif |
10595 | return (retval); |
10596 | } |
10597 | |
10598 | /* |
10599 | * Catch an interrupt from the adapter |
10600 | */ |
10601 | int |
10602 | ahd_intr(struct ahd_softc *ahd) |
10603 | { |
10604 | u_int intstat; |
10605 | |
10606 | if ((ahd->pause & INTEN0x02) == 0) { |
10607 | /* |
10608 | * Our interrupt is not enabled on the chip |
10609 | * and may be disabled for re-entrancy reasons, |
10610 | * so just return. This is likely just a shared |
10611 | * interrupt. |
10612 | */ |
10613 | return (0); |
10614 | } |
10615 | |
10616 | /* |
10617 | * Instead of directly reading the interrupt status register, |
10618 | * infer the cause of the interrupt by checking our in-core |
10619 | * completion queues. This avoids a costly PCI bus read in |
10620 | * most cases. |
10621 | */ |
10622 | if ((ahd->flags & AHD_ALL_INTERRUPTS) == 0 |
10623 | && (ahd_check_cmdcmpltqueues(ahd) != 0)) |
10624 | intstat = CMDCMPLT0x02; |
10625 | else |
10626 | intstat = ahd_inb(ahd, INTSTAT)(((ahd)->tags[(0x01) >> 8])->read_1(((ahd)->bshs [(0x01) >> 8]), ((0x01) & 0xFF))); |
10627 | |
10628 | if ((intstat & INT_PEND0xff) == 0) |
10629 | return (0); |
10630 | |
10631 | if (intstat & CMDCMPLT0x02) { |
10632 | ahd_outb(ahd, CLRINT, CLRCMDINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x02))); |
10633 | |
10634 | /* |
10635 | * Ensure that the chip sees that we've cleared |
10636 | * this interrupt before we walk the output fifo. |
10637 | * Otherwise, we may, due to posted bus writes, |
10638 | * clear the interrupt after we finish the scan, |
10639 | * and after the sequencer has added new entries |
10640 | * and asserted the interrupt again. |
10641 | */ |
10642 | if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) { |
10643 | if (ahd_is_paused(ahd)) { |
10644 | /* |
10645 | * Potentially lost SEQINT. |
10646 | * If SEQINTCODE is non-zero, |
10647 | * simulate the SEQINT. |
10648 | */ |
10649 | if (ahd_inb(ahd, SEQINTCODE)(((ahd)->tags[(0x02) >> 8])->read_1(((ahd)->bshs [(0x02) >> 8]), ((0x02) & 0xFF))) != NO_SEQINT0x00) |
10650 | intstat |= SEQINT0x04; |
10651 | } |
10652 | } else { |
10653 | ahd_flush_device_writes(ahd); |
10654 | } |
10655 | ahd_run_qoutfifo(ahd); |
10656 | ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]++; |
10657 | ahd->cmdcmplt_total++; |
10658 | #ifdef AHD_TARGET_MODE |
10659 | if ((ahd->flags & AHD_TARGETROLE) != 0) |
10660 | ahd_run_tqinfifo(ahd, /*paused*/FALSE0); |
10661 | #endif |
10662 | } |
10663 | |
10664 | /* |
10665 | * Handle statuses that may invalidate our cached |
10666 | * copy of INTSTAT separately. |
10667 | */ |
10668 | if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) { |
10669 | /* Hot eject. Do nothing */ |
10670 | } else if (intstat & HWERRINT0x80) { |
10671 | ahd_handle_hwerrint(ahd); |
10672 | } else if ((intstat & (PCIINT0x10|SPLTINT0x01)) != 0) { |
10673 | ahd->bus_intr(ahd); |
10674 | } else { |
10675 | |
10676 | if ((intstat & SEQINT0x04) != 0) |
10677 | ahd_handle_seqint(ahd, intstat); |
10678 | |
10679 | if ((intstat & SCSIINT0x08) != 0) |
10680 | ahd_handle_scsiint(ahd, intstat); |
10681 | } |
10682 | return (1); |
10683 | } |
10684 | |
10685 | void |
10686 | ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl) |
10687 | { |
10688 | ahd_busy_tcl(ahd, tcl, SCB_LIST_NULL0xFF00); |
10689 | } |