File: | dev/ic/aic79xx.c |
Warning: | line 6986, column 11 Access to field 'hscb' results in a dereference of a null pointer (loaded from variable 'scb') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: aic79xx.c,v 1.67 2022/01/09 05:42:38 jsg Exp $ */ | |||
2 | ||||
3 | /* | |||
4 | * Copyright (c) 2004 Milos Urbanek, Kenneth R. Westerback & Marco Peereboom | |||
5 | * All rights reserved. | |||
6 | * | |||
7 | * Redistribution and use in source and binary forms, with or without | |||
8 | * modification, are permitted provided that the following conditions | |||
9 | * are met: | |||
10 | * 1. Redistributions of source code must retain the above copyright | |||
11 | * notice, this list of conditions and the following disclaimer. | |||
12 | * 2. Redistributions in binary form must reproduce the above copyright | |||
13 | * notice, this list of conditions and the following disclaimer in the | |||
14 | * documentation and/or other materials provided with the distribution. | |||
15 | * | |||
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND | |||
17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR | |||
20 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
26 | * SUCH DAMAGE. | |||
27 | * | |||
28 | */ | |||
29 | ||||
30 | /* | |||
31 | * Core routines and tables shareable across OS platforms. | |||
32 | * | |||
33 | * Copyright (c) 1994-2002, 2004 Justin T. Gibbs. | |||
34 | * Copyright (c) 2000-2003 Adaptec Inc. | |||
35 | * All rights reserved. | |||
36 | * | |||
37 | * Redistribution and use in source and binary forms, with or without | |||
38 | * modification, are permitted provided that the following conditions | |||
39 | * are met: | |||
40 | * 1. Redistributions of source code must retain the above copyright | |||
41 | * notice, this list of conditions, and the following disclaimer, | |||
42 | * without modification. | |||
43 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | |||
44 | * substantially similar to the "NO WARRANTY" disclaimer below | |||
45 | * ("Disclaimer") and any redistribution must be conditioned upon | |||
46 | * including a substantially similar Disclaimer requirement for further | |||
47 | * binary redistribution. | |||
48 | * 3. Neither the names of the above-listed copyright holders nor the names | |||
49 | * of any contributors may be used to endorse or promote products derived | |||
50 | * from this software without specific prior written permission. | |||
51 | * | |||
52 | * Alternatively, this software may be distributed under the terms of the | |||
53 | * GNU General Public License ("GPL") version 2 as published by the Free | |||
54 | * Software Foundation. | |||
55 | * | |||
56 | * NO WARRANTY | |||
57 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |||
58 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |||
59 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | |||
60 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |||
61 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
62 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
63 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
64 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |||
65 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | |||
66 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |||
67 | * POSSIBILITY OF SUCH DAMAGES. | |||
68 | * | |||
69 | * Id: //depot/aic7xxx/aic7xxx/aic79xx.c#246 | |||
70 | * | |||
71 | * FreeBSD: src/sys/dev/aic7xxx/aic79xx.c,v 1.33 2004/11/18 20:22:30 gibbs Exp | |||
72 | */ | |||
73 | ||||
74 | #include <dev/ic/aic79xx_openbsd.h> | |||
75 | #include <dev/ic/aic79xx_inline.h> | |||
76 | #include <dev/ic/aic79xx.h> | |||
77 | ||||
78 | #include <dev/microcode/aic7xxx/aicasm_insformat.h> | |||
79 | ||||
80 | /******************************** Globals *************************************/ | |||
81 | struct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq){ ((void *)0), &(ahd_tailq).tqh_first }; | |||
82 | uint32_t ahd_attach_to_HostRAID_controllers = 1; | |||
83 | ||||
84 | /***************************** Lookup Tables **********************************/ | |||
85 | char *ahd_chip_names[] = | |||
86 | { | |||
87 | "NONE", | |||
88 | "aic7901", | |||
89 | "aic7902", | |||
90 | "aic7901A" | |||
91 | }; | |||
92 | ||||
93 | /* | |||
94 | * Hardware error codes. | |||
95 | */ | |||
96 | struct ahd_hard_error_entry { | |||
97 | uint8_t errno; | |||
98 | char *errmesg; | |||
99 | }; | |||
100 | ||||
101 | static struct ahd_hard_error_entry ahd_hard_errors[] = { | |||
102 | { DSCTMOUT0x02, "Discard Timer has timed out" }, | |||
103 | { ILLOPCODE0x04, "Illegal Opcode in sequencer program" }, | |||
104 | { SQPARERR0x08, "Sequencer Parity Error" }, | |||
105 | { DPARERR0x10, "Data-path Parity Error" }, | |||
106 | { MPARERR0x20, "Scratch or SCB Memory Parity Error" }, | |||
107 | { CIOPARERR0x80, "CIOBUS Parity Error" }, | |||
108 | }; | |||
109 | static const u_int num_errors = NUM_ELEMENTS(ahd_hard_errors)(sizeof(ahd_hard_errors) / sizeof(*ahd_hard_errors)); | |||
110 | ||||
111 | static struct ahd_phase_table_entry ahd_phase_table[] = | |||
112 | { | |||
113 | { P_DATAOUT0x00, MSG_NOOP0x08, "in Data-out phase" }, | |||
114 | { P_DATAIN0x40, MSG_INITIATOR_DET_ERR0x05, "in Data-in phase" }, | |||
115 | { P_DATAOUT_DT0x20, MSG_NOOP0x08, "in DT Data-out phase" }, | |||
116 | { P_DATAIN_DT0x60, MSG_INITIATOR_DET_ERR0x05, "in DT Data-in phase" }, | |||
117 | { P_COMMAND0x80, MSG_NOOP0x08, "in Command phase" }, | |||
118 | { P_MESGOUT0xa0, MSG_NOOP0x08, "in Message-out phase" }, | |||
119 | { P_STATUS0xc0, MSG_INITIATOR_DET_ERR0x05, "in Status phase" }, | |||
120 | { P_MESGIN0xe0, MSG_PARITY_ERROR0x09, "in Message-in phase" }, | |||
121 | { P_BUSFREE0x01, MSG_NOOP0x08, "while idle" }, | |||
122 | { 0, MSG_NOOP0x08, "in unknown phase" } | |||
123 | }; | |||
124 | ||||
125 | /* | |||
126 | * In most cases we only wish to iterate over real phases, so | |||
127 | * exclude the last element from the count. | |||
128 | */ | |||
129 | static const u_int num_phases = NUM_ELEMENTS(ahd_phase_table)(sizeof(ahd_phase_table) / sizeof(*ahd_phase_table)) - 1; | |||
130 | ||||
131 | /* Our Sequencer Program */ | |||
132 | #include <dev/microcode/aic7xxx/aic79xx_seq.h> | |||
133 | ||||
134 | /**************************** Function Declarations ***************************/ | |||
135 | void ahd_handle_transmission_error(struct ahd_softc *ahd); | |||
136 | void ahd_handle_lqiphase_error(struct ahd_softc *ahd, | |||
137 | u_int lqistat1); | |||
138 | int ahd_handle_pkt_busfree(struct ahd_softc *ahd, | |||
139 | u_int busfreetime); | |||
140 | int ahd_handle_nonpkt_busfree(struct ahd_softc *ahd); | |||
141 | void ahd_handle_proto_violation(struct ahd_softc *ahd); | |||
142 | void ahd_force_renegotiation(struct ahd_softc *ahd, | |||
143 | struct ahd_devinfo *devinfo); | |||
144 | ||||
145 | struct ahd_tmode_tstate* | |||
146 | ahd_alloc_tstate(struct ahd_softc *ahd, | |||
147 | u_int scsi_id, char channel); | |||
148 | #ifdef AHD_TARGET_MODE | |||
149 | void ahd_free_tstate(struct ahd_softc *ahd, | |||
150 | u_int scsi_id, char channel, int force); | |||
151 | #endif | |||
152 | void ahd_devlimited_syncrate(struct ahd_softc *ahd, | |||
153 | struct ahd_initiator_tinfo *, | |||
154 | u_int *period, | |||
155 | u_int *ppr_options, | |||
156 | role_t role); | |||
157 | void ahd_update_neg_table(struct ahd_softc *ahd, | |||
158 | struct ahd_devinfo *devinfo, | |||
159 | struct ahd_transinfo *tinfo); | |||
160 | void ahd_update_pending_scbs(struct ahd_softc *ahd); | |||
161 | void ahd_fetch_devinfo(struct ahd_softc *ahd, | |||
162 | struct ahd_devinfo *devinfo); | |||
163 | void ahd_scb_devinfo(struct ahd_softc *ahd, | |||
164 | struct ahd_devinfo *devinfo, | |||
165 | struct scb *scb); | |||
166 | void ahd_setup_initiator_msgout(struct ahd_softc *ahd, | |||
167 | struct ahd_devinfo *devinfo, | |||
168 | struct scb *scb); | |||
169 | void ahd_build_transfer_msg(struct ahd_softc *ahd, | |||
170 | struct ahd_devinfo *devinfo); | |||
171 | void ahd_construct_sdtr(struct ahd_softc *ahd, | |||
172 | struct ahd_devinfo *devinfo, | |||
173 | u_int period, u_int offset); | |||
174 | void ahd_construct_wdtr(struct ahd_softc *ahd, | |||
175 | struct ahd_devinfo *devinfo, | |||
176 | u_int bus_width); | |||
177 | void ahd_construct_ppr(struct ahd_softc *ahd, | |||
178 | struct ahd_devinfo *devinfo, | |||
179 | u_int period, u_int offset, | |||
180 | u_int bus_width, u_int ppr_options); | |||
181 | void ahd_clear_msg_state(struct ahd_softc *ahd); | |||
182 | void ahd_handle_message_phase(struct ahd_softc *ahd); | |||
183 | typedef enum { | |||
184 | AHDMSG_1B, | |||
185 | AHDMSG_2B, | |||
186 | AHDMSG_EXT | |||
187 | } ahd_msgtype; | |||
188 | int ahd_sent_msg(struct ahd_softc *ahd, ahd_msgtype type, | |||
189 | u_int msgval, int full); | |||
190 | int ahd_parse_msg(struct ahd_softc *ahd, | |||
191 | struct ahd_devinfo *devinfo); | |||
192 | int ahd_handle_msg_reject(struct ahd_softc *ahd, | |||
193 | struct ahd_devinfo *devinfo); | |||
194 | void ahd_handle_ign_wide_residue(struct ahd_softc *ahd, | |||
195 | struct ahd_devinfo *devinfo); | |||
196 | void ahd_reinitialize_dataptrs(struct ahd_softc *ahd); | |||
197 | void ahd_handle_devreset(struct ahd_softc *ahd, | |||
198 | struct ahd_devinfo *devinfo, | |||
199 | u_int lun, cam_status status, | |||
200 | char *message, int verbose_level); | |||
201 | #if AHD_TARGET_MODE | |||
202 | void ahd_setup_target_msgin(struct ahd_softc *ahd, | |||
203 | struct ahd_devinfo *devinfo, | |||
204 | struct scb *scb); | |||
205 | #endif | |||
206 | ||||
207 | u_int ahd_sglist_size(struct ahd_softc *ahd); | |||
208 | u_int ahd_sglist_allocsize(struct ahd_softc *ahd); | |||
209 | void ahd_initialize_hscbs(struct ahd_softc *ahd); | |||
210 | int ahd_init_scbdata(struct ahd_softc *ahd); | |||
211 | struct scb * ahd_find_scb_by_tag(struct ahd_softc *, u_int); | |||
212 | void ahd_fini_scbdata(struct ahd_softc *ahd); | |||
213 | void ahd_setup_iocell_workaround(struct ahd_softc *ahd); | |||
214 | void ahd_iocell_first_selection(struct ahd_softc *ahd); | |||
215 | void ahd_chip_init(struct ahd_softc *ahd); | |||
216 | void ahd_qinfifo_requeue(struct ahd_softc *ahd, | |||
217 | struct scb *prev_scb, | |||
218 | struct scb *scb); | |||
219 | int ahd_qinfifo_count(struct ahd_softc *ahd); | |||
220 | int ahd_search_scb_list(struct ahd_softc *ahd, int target, | |||
221 | char channel, int lun, u_int tag, | |||
222 | role_t role, uint32_t status, | |||
223 | ahd_search_action action, | |||
224 | u_int *list_head, u_int *list_tail, | |||
225 | u_int tid); | |||
226 | void ahd_stitch_tid_list(struct ahd_softc *ahd, | |||
227 | u_int tid_prev, u_int tid_cur, | |||
228 | u_int tid_next); | |||
229 | void ahd_add_scb_to_free_list(struct ahd_softc *ahd, | |||
230 | u_int scbid); | |||
231 | u_int ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid, | |||
232 | u_int prev, u_int next, u_int tid); | |||
233 | void ahd_reset_current_bus(struct ahd_softc *ahd); | |||
234 | ahd_callback_t ahd_reset_poll; | |||
235 | ahd_callback_t ahd_stat_timer; | |||
236 | #ifdef AHD_DUMP_SEQ | |||
237 | void ahd_dumpseq(struct ahd_softc *ahd); | |||
238 | #endif | |||
239 | void ahd_loadseq(struct ahd_softc *ahd); | |||
240 | int ahd_check_patch(struct ahd_softc *ahd, | |||
241 | const struct patch **start_patch, | |||
242 | u_int start_instr, u_int *skip_addr); | |||
243 | u_int ahd_resolve_seqaddr(struct ahd_softc *ahd, | |||
244 | u_int address); | |||
245 | void ahd_download_instr(struct ahd_softc *ahd, | |||
246 | u_int instrptr, uint8_t *dconsts); | |||
247 | int ahd_probe_stack_size(struct ahd_softc *ahd); | |||
248 | int ahd_scb_active_in_fifo(struct ahd_softc *ahd, | |||
249 | struct scb *scb); | |||
250 | void ahd_run_data_fifo(struct ahd_softc *ahd, | |||
251 | struct scb *scb); | |||
252 | ||||
253 | #ifdef AHD_TARGET_MODE | |||
254 | void ahd_queue_lstate_event(struct ahd_softc *ahd, | |||
255 | struct ahd_tmode_lstate *lstate, | |||
256 | u_int initiator_id, | |||
257 | u_int event_type, | |||
258 | u_int event_arg); | |||
259 | void ahd_update_scsiid(struct ahd_softc *ahd, | |||
260 | u_int targid_mask); | |||
261 | int ahd_handle_target_cmd(struct ahd_softc *ahd, | |||
262 | struct target_cmd *cmd); | |||
263 | #endif | |||
264 | ||||
265 | /************************** Added for porting to NetBSD ***********************/ | |||
266 | int ahd_createdmamem(struct ahd_softc *, size_t, struct map_node *, | |||
267 | const char *); | |||
268 | ||||
269 | void ahd_freedmamem(struct ahd_softc *, struct map_node *); | |||
270 | ||||
271 | /******************************** Private Inlines *****************************/ | |||
272 | int ahd_currently_packetized(struct ahd_softc *ahd); | |||
273 | int ahd_set_active_fifo(struct ahd_softc *ahd); | |||
274 | ||||
275 | static inline void | |||
276 | ahd_assert_atn(struct ahd_softc *ahd) | |||
277 | { | |||
278 | ahd_outb(ahd, SCSISIGO, ATNO)(((ahd)->tags[(0x40) >> 8])->write_1(((ahd)->bshs [(0x40) >> 8]), ((0x40) & 0xFF), (0x10))); | |||
279 | } | |||
280 | ||||
281 | /* | |||
282 | * Determine if the current connection has a packetized | |||
283 | * agreement. This does not necessarily mean that we | |||
284 | * are currently in a packetized transfer. We could | |||
285 | * just as easily be sending or receiving a message. | |||
286 | */ | |||
287 | int | |||
288 | ahd_currently_packetized(struct ahd_softc *ahd) | |||
289 | { | |||
290 | ahd_mode_state saved_modes; | |||
291 | int packetized; | |||
292 | ||||
293 | saved_modes = ahd_save_modes(ahd); | |||
294 | if ((ahd->bugs & AHD_PKTIZED_STATUS_BUG) != 0) { | |||
295 | /* | |||
296 | * The packetized bit refers to the last | |||
297 | * connection, not the current one. Check | |||
298 | * for non-zero LQISTATE instead. | |||
299 | */ | |||
300 | ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); | |||
301 | packetized = ahd_inb(ahd, LQISTATE)(((ahd)->tags[(0x4e) >> 8])->read_1(((ahd)->bshs [(0x4e) >> 8]), ((0x4e) & 0xFF))) != 0; | |||
302 | } else { | |||
303 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | |||
304 | packetized = ahd_inb(ahd, LQISTAT2)(((ahd)->tags[(0x52) >> 8])->read_1(((ahd)->bshs [(0x52) >> 8]), ((0x52) & 0xFF))) & PACKETIZED0x80; | |||
305 | } | |||
306 | ahd_restore_modes(ahd, saved_modes); | |||
307 | return (packetized); | |||
308 | } | |||
309 | ||||
310 | int | |||
311 | ahd_set_active_fifo(struct ahd_softc *ahd) | |||
312 | { | |||
313 | u_int active_fifo; | |||
314 | ||||
315 | AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK)ahd_assert_modes(ahd, (0x01 << (AHD_MODE_SCSI)), (0x01 << (AHD_MODE_SCSI)), "/usr/src/sys/dev/ic/aic79xx.c", 315);; | |||
316 | active_fifo = ahd_inb(ahd, DFFSTAT)(((ahd)->tags[(0x3f) >> 8])->read_1(((ahd)->bshs [(0x3f) >> 8]), ((0x3f) & 0xFF))) & CURRFIFO0x03; | |||
317 | switch (active_fifo) { | |||
318 | case 0: | |||
319 | case 1: | |||
320 | ahd_set_modes(ahd, active_fifo, active_fifo); | |||
321 | return (1); | |||
322 | default: | |||
323 | return (0); | |||
324 | } | |||
325 | } | |||
326 | ||||
327 | /************************* Sequencer Execution Control ************************/ | |||
328 | /* | |||
329 | * Restart the sequencer program from address zero | |||
330 | */ | |||
331 | void | |||
332 | ahd_restart(struct ahd_softc *ahd) | |||
333 | { | |||
334 | ||||
335 | ahd_pause(ahd); | |||
336 | ||||
337 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | |||
338 | ||||
339 | /* No more pending messages */ | |||
340 | ahd_clear_msg_state(ahd); | |||
341 | ahd_outb(ahd, SCSISIGO, 0)(((ahd)->tags[(0x40) >> 8])->write_1(((ahd)->bshs [(0x40) >> 8]), ((0x40) & 0xFF), (0))); /* De-assert BSY */ | |||
342 | ahd_outb(ahd, MSG_OUT, MSG_NOOP)(((ahd)->tags[(0x137) >> 8])->write_1(((ahd)-> bshs[(0x137) >> 8]), ((0x137) & 0xFF), (0x08))); /* No message to send */ | |||
343 | ahd_outb(ahd, SXFRCTL1, ahd_inb(ahd, SXFRCTL1) & ~BITBUCKET)(((ahd)->tags[(0x3d) >> 8])->write_1(((ahd)->bshs [(0x3d) >> 8]), ((0x3d) & 0xFF), ((((ahd)->tags[ (0x3d) >> 8])->read_1(((ahd)->bshs[(0x3d) >> 8]), ((0x3d) & 0xFF))) & ~0x80))); | |||
344 | ahd_outb(ahd, SEQINTCTL, 0)(((ahd)->tags[(0xd9) >> 8])->write_1(((ahd)->bshs [(0xd9) >> 8]), ((0xd9) & 0xFF), (0))); | |||
345 | ahd_outb(ahd, LASTPHASE, P_BUSFREE)(((ahd)->tags[(0x13c) >> 8])->write_1(((ahd)-> bshs[(0x13c) >> 8]), ((0x13c) & 0xFF), (0x01))); | |||
346 | ahd_outb(ahd, SEQ_FLAGS, 0)(((ahd)->tags[(0x139) >> 8])->write_1(((ahd)-> bshs[(0x139) >> 8]), ((0x139) & 0xFF), (0))); | |||
347 | ahd_outb(ahd, SAVED_SCSIID, 0xFF)(((ahd)->tags[(0x13a) >> 8])->write_1(((ahd)-> bshs[(0x13a) >> 8]), ((0x13a) & 0xFF), (0xFF))); | |||
348 | ahd_outb(ahd, SAVED_LUN, 0xFF)(((ahd)->tags[(0x13b) >> 8])->write_1(((ahd)-> bshs[(0x13b) >> 8]), ((0x13b) & 0xFF), (0xFF))); | |||
349 | ||||
350 | /* | |||
351 | * Ensure that the sequencer's idea of TQINPOS | |||
352 | * matches our own. The sequencer increments TQINPOS | |||
353 | * only after it sees a DMA complete and a reset could | |||
354 | * occur before the increment leaving the kernel to believe | |||
355 | * the command arrived but the sequencer to not. | |||
356 | */ | |||
357 | ahd_outb(ahd, TQINPOS, ahd->tqinfifonext)(((ahd)->tags[(0x13f) >> 8])->write_1(((ahd)-> bshs[(0x13f) >> 8]), ((0x13f) & 0xFF), (ahd->tqinfifonext ))); | |||
358 | ||||
359 | /* Always allow reselection */ | |||
360 | ahd_outb(ahd, SCSISEQ1,(((ahd)->tags[(0x3b) >> 8])->write_1(((ahd)->bshs [(0x3b) >> 8]), ((0x3b) & 0xFF), ((((ahd)->tags[ (0x14b) >> 8])->read_1(((ahd)->bshs[(0x14b) >> 8]), ((0x14b) & 0xFF))) & (0x20|0x10|0x02)))) | |||
361 | ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP))(((ahd)->tags[(0x3b) >> 8])->write_1(((ahd)->bshs [(0x3b) >> 8]), ((0x3b) & 0xFF), ((((ahd)->tags[ (0x14b) >> 8])->read_1(((ahd)->bshs[(0x14b) >> 8]), ((0x14b) & 0xFF))) & (0x20|0x10|0x02)))); | |||
362 | ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); | |||
363 | ||||
364 | /* | |||
365 | * Clear any pending sequencer interrupt. It is no | |||
366 | * longer relevant since we're resetting the Program | |||
367 | * Counter. | |||
368 | */ | |||
369 | ahd_outb(ahd, CLRINT, CLRSEQINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x04))); | |||
370 | ||||
371 | ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET)(((ahd)->tags[(0xd6) >> 8])->write_1(((ahd)->bshs [(0xd6) >> 8]), ((0xd6) & 0xFF), (0x10|0x02))); | |||
372 | ahd_unpause(ahd); | |||
373 | } | |||
374 | ||||
375 | void | |||
376 | ahd_clear_fifo(struct ahd_softc *ahd, u_int fifo) | |||
377 | { | |||
378 | ahd_mode_state saved_modes; | |||
379 | ||||
380 | #ifdef AHD_DEBUG | |||
381 | if ((ahd_debug & AHD_SHOW_FIFOS) != 0) | |||
382 | printf("%s: Clearing FIFO %d\n", ahd_name(ahd), fifo); | |||
383 | #endif | |||
384 | saved_modes = ahd_save_modes(ahd); | |||
385 | ahd_set_modes(ahd, fifo, fifo); | |||
386 | ahd_outb(ahd, DFFSXFRCTL, RSTCHN|CLRSHCNT)(((ahd)->tags[(0x5a) >> 8])->write_1(((ahd)->bshs [(0x5a) >> 8]), ((0x5a) & 0xFF), (0x01|0x04))); | |||
387 | if ((ahd_inb(ahd, SG_STATE)(((ahd)->tags[(0xa6) >> 8])->read_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF))) & FETCH_INPROG0x04) != 0) | |||
388 | ahd_outb(ahd, CCSGCTL, CCSGRESET)(((ahd)->tags[(0xad) >> 8])->write_1(((ahd)->bshs [(0xad) >> 8]), ((0xad) & 0xFF), (0x01))); | |||
389 | ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR)(((ahd)->tags[(0xf8 + 1) >> 8])->write_1(((ahd)-> bshs[(0xf8 + 1) >> 8]), ((0xf8 + 1) & 0xFF), (0x80) )); | |||
390 | ahd_outb(ahd, SG_STATE, 0)(((ahd)->tags[(0xa6) >> 8])->write_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF), (0))); | |||
391 | ahd_restore_modes(ahd, saved_modes); | |||
392 | } | |||
393 | ||||
394 | /************************* Input/Output Queues ********************************/ | |||
395 | /* | |||
396 | * Flush and completed commands that are sitting in the command | |||
397 | * complete queues down on the chip but have yet to be dma'ed back up. | |||
398 | */ | |||
399 | void | |||
400 | ahd_flush_qoutfifo(struct ahd_softc *ahd) | |||
401 | { | |||
402 | struct scb *scb; | |||
403 | ahd_mode_state saved_modes; | |||
404 | u_int saved_scbptr; | |||
405 | u_int ccscbctl; | |||
406 | u_int scbid; | |||
407 | u_int next_scbid; | |||
408 | ||||
409 | saved_modes = ahd_save_modes(ahd); | |||
410 | ||||
411 | /* | |||
412 | * Flush the good status FIFO for completed packetized commands. | |||
413 | */ | |||
414 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | |||
415 | saved_scbptr = ahd_get_scbptr(ahd); | |||
416 | while ((ahd_inb(ahd, LQISTAT2)(((ahd)->tags[(0x52) >> 8])->read_1(((ahd)->bshs [(0x52) >> 8]), ((0x52) & 0xFF))) & LQIGSAVAIL0x01) != 0) { | |||
417 | u_int fifo_mode; | |||
418 | u_int i; | |||
419 | ||||
420 | scbid = ahd_inw(ahd, GSFIFO0x58); | |||
421 | scb = ahd_lookup_scb(ahd, scbid); | |||
422 | if (scb == NULL((void *)0)) { | |||
423 | printf("%s: Warning - GSFIFO SCB %d invalid\n", | |||
424 | ahd_name(ahd), scbid); | |||
425 | continue; | |||
426 | } | |||
427 | /* | |||
428 | * Determine if this transaction is still active in | |||
429 | * any FIFO. If it is, we must flush that FIFO to | |||
430 | * the host before completing the command. | |||
431 | */ | |||
432 | fifo_mode = 0; | |||
433 | rescan_fifos: | |||
434 | for (i = 0; i < 2; i++) { | |||
435 | /* Toggle to the other mode. */ | |||
436 | fifo_mode ^= 1; | |||
437 | ahd_set_modes(ahd, fifo_mode, fifo_mode); | |||
438 | ||||
439 | if (ahd_scb_active_in_fifo(ahd, scb) == 0) | |||
440 | continue; | |||
441 | ||||
442 | ahd_run_data_fifo(ahd, scb); | |||
443 | ||||
444 | /* | |||
445 | * Running this FIFO may cause a CFG4DATA for | |||
446 | * this same transaction to assert in the other | |||
447 | * FIFO or a new snapshot SAVEPTRS interrupt | |||
448 | * in this FIFO. Even running a FIFO may not | |||
449 | * clear the transaction if we are still waiting | |||
450 | * for data to drain to the host. We must loop | |||
451 | * until the transaction is not active in either | |||
452 | * FIFO just to be sure. Reset our loop counter | |||
453 | * so we will visit both FIFOs again before | |||
454 | * declaring this transaction finished. We | |||
455 | * also delay a bit so that status has a chance | |||
456 | * to change before we look at this FIFO again. | |||
457 | */ | |||
458 | aic_delay(200)(*delay_func)(200); | |||
459 | goto rescan_fifos; | |||
460 | } | |||
461 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | |||
462 | ahd_set_scbptr(ahd, scbid); | |||
463 | if ((ahd_inb_scbram(ahd, SCB_SGPTR0x1a4) & SG_LIST_NULL0x01) == 0 | |||
464 | && ((ahd_inb_scbram(ahd, SCB_SGPTR0x1a4) & SG_FULL_RESID0x02) != 0 | |||
465 | || (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR0x184) | |||
466 | & SG_LIST_NULL0x01) != 0)) { | |||
467 | u_int comp_head; | |||
468 | ||||
469 | /* | |||
470 | * The transfer completed with a residual. | |||
471 | * Place this SCB on the complete DMA list | |||
472 | * so that we update our in-core copy of the | |||
473 | * SCB before completing the command. | |||
474 | */ | |||
475 | ahd_outb(ahd, SCB_SCSI_STATUS, 0)(((ahd)->tags[(0x188) >> 8])->write_1(((ahd)-> bshs[(0x188) >> 8]), ((0x188) & 0xFF), (0))); | |||
476 | ahd_outb(ahd, SCB_SGPTR,(((ahd)->tags[(0x1a4) >> 8])->write_1(((ahd)-> bshs[(0x1a4) >> 8]), ((0x1a4) & 0xFF), (ahd_inb_scbram (ahd, 0x1a4) | 0x04))) | |||
477 | ahd_inb_scbram(ahd, SCB_SGPTR)(((ahd)->tags[(0x1a4) >> 8])->write_1(((ahd)-> bshs[(0x1a4) >> 8]), ((0x1a4) & 0xFF), (ahd_inb_scbram (ahd, 0x1a4) | 0x04))) | |||
478 | | SG_STATUS_VALID)(((ahd)->tags[(0x1a4) >> 8])->write_1(((ahd)-> bshs[(0x1a4) >> 8]), ((0x1a4) & 0xFF), (ahd_inb_scbram (ahd, 0x1a4) | 0x04))); | |||
479 | ahd_outw(ahd, SCB_TAG0x190, scbid); | |||
480 | ahd_outw(ahd, SCB_NEXT_COMPLETE0x18c, SCB_LIST_NULL0xFF00); | |||
481 | comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD0x12c); | |||
482 | if (SCBID_IS_NULL(comp_head)(((comp_head) & 0xFF00 ) == 0xFF00)) { | |||
483 | ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD0x12c, scbid); | |||
484 | ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL0x12e, scbid); | |||
485 | } else { | |||
486 | u_int tail; | |||
487 | ||||
488 | tail = ahd_inw(ahd, COMPLETE_DMA_SCB_TAIL0x12e); | |||
489 | ahd_set_scbptr(ahd, tail); | |||
490 | ahd_outw(ahd, SCB_NEXT_COMPLETE0x18c, scbid); | |||
491 | ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL0x12e, scbid); | |||
492 | ahd_set_scbptr(ahd, scbid); | |||
493 | } | |||
494 | } else | |||
495 | ahd_complete_scb(ahd, scb); | |||
496 | } | |||
497 | ahd_set_scbptr(ahd, saved_scbptr); | |||
498 | ||||
499 | /* | |||
500 | * Setup for command channel portion of flush. | |||
501 | */ | |||
502 | ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); | |||
503 | ||||
504 | /* | |||
505 | * Wait for any inprogress DMA to complete and clear DMA state | |||
506 | * if this if for an SCB in the qinfifo. | |||
507 | */ | |||
508 | while (((ccscbctl = ahd_inb(ahd, CCSCBCTL)(((ahd)->tags[(0xad) >> 8])->read_1(((ahd)->bshs [(0xad) >> 8]), ((0xad) & 0xFF)))) & (CCARREN0x10|CCSCBEN0x08)) != 0) { | |||
509 | ||||
510 | if ((ccscbctl & (CCSCBDIR0x04|CCARREN0x10)) == (CCSCBDIR0x04|CCARREN0x10)) { | |||
511 | if ((ccscbctl & ARRDONE0x40) != 0) | |||
512 | break; | |||
513 | } else if ((ccscbctl & CCSCBDONE0x80) != 0) | |||
514 | break; | |||
515 | aic_delay(200)(*delay_func)(200); | |||
516 | } | |||
517 | /* | |||
518 | * We leave the sequencer to cleanup in the case of DMA's to | |||
519 | * update the qoutfifo. In all other cases (DMA's to the | |||
520 | * chip or a push of an SCB from the COMPLETE_DMA_SCB list), | |||
521 | * we disable the DMA engine so that the sequencer will not | |||
522 | * attempt to handle the DMA completion. | |||
523 | */ | |||
524 | if ((ccscbctl & CCSCBDIR0x04) != 0 || (ccscbctl & ARRDONE0x40) != 0) | |||
525 | ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN))(((ahd)->tags[(0xad) >> 8])->write_1(((ahd)->bshs [(0xad) >> 8]), ((0xad) & 0xFF), (ccscbctl & ~( 0x10|0x08)))); | |||
526 | ||||
527 | /* | |||
528 | * Complete any SCBs that just finished | |||
529 | * being DMA'ed into the qoutfifo. | |||
530 | */ | |||
531 | ahd_run_qoutfifo(ahd); | |||
532 | ||||
533 | saved_scbptr = ahd_get_scbptr(ahd); | |||
534 | /* | |||
535 | * Manually update/complete any completed SCBs that are waiting to be | |||
536 | * DMA'ed back up to the host. | |||
537 | */ | |||
538 | scbid = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD0x12c); | |||
539 | while (!SCBID_IS_NULL(scbid)(((scbid) & 0xFF00 ) == 0xFF00)) { | |||
540 | uint8_t *hscb_ptr; | |||
541 | u_int i; | |||
542 | ||||
543 | ahd_set_scbptr(ahd, scbid); | |||
544 | next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE0x18c); | |||
545 | scb = ahd_lookup_scb(ahd, scbid); | |||
546 | if (scb == NULL((void *)0)) { | |||
547 | printf("%s: Warning - DMA-up and complete " | |||
548 | "SCB %d invalid\n", ahd_name(ahd), scbid); | |||
549 | continue; | |||
550 | } | |||
551 | hscb_ptr = (uint8_t *)scb->hscb; | |||
552 | for (i = 0; i < sizeof(struct hardware_scb); i++) | |||
553 | *hscb_ptr++ = ahd_inb_scbram(ahd, SCB_BASE0x180 + i); | |||
554 | ||||
555 | ahd_complete_scb(ahd, scb); | |||
556 | scbid = next_scbid; | |||
557 | } | |||
558 | ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD0x12c, SCB_LIST_NULL0xFF00); | |||
559 | ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL0x12e, SCB_LIST_NULL0xFF00); | |||
560 | ||||
561 | scbid = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD0x130); | |||
562 | while (!SCBID_IS_NULL(scbid)(((scbid) & 0xFF00 ) == 0xFF00)) { | |||
563 | ||||
564 | ahd_set_scbptr(ahd, scbid); | |||
565 | next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE0x18c); | |||
566 | scb = ahd_lookup_scb(ahd, scbid); | |||
567 | if (scb == NULL((void *)0)) { | |||
568 | printf("%s: Warning - Complete Qfrz SCB %d invalid\n", | |||
569 | ahd_name(ahd), scbid); | |||
570 | continue; | |||
571 | } | |||
572 | ||||
573 | ahd_complete_scb(ahd, scb); | |||
574 | scbid = next_scbid; | |||
575 | } | |||
576 | ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD0x130, SCB_LIST_NULL0xFF00); | |||
577 | ||||
578 | scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD0x128); | |||
579 | while (!SCBID_IS_NULL(scbid)(((scbid) & 0xFF00 ) == 0xFF00)) { | |||
580 | ||||
581 | ahd_set_scbptr(ahd, scbid); | |||
582 | next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE0x18c); | |||
583 | scb = ahd_lookup_scb(ahd, scbid); | |||
584 | if (scb == NULL((void *)0)) { | |||
585 | printf("%s: Warning - Complete SCB %d invalid\n", | |||
586 | ahd_name(ahd), scbid); | |||
587 | continue; | |||
588 | } | |||
589 | ||||
590 | ahd_complete_scb(ahd, scb); | |||
591 | scbid = next_scbid; | |||
592 | } | |||
593 | ahd_outw(ahd, COMPLETE_SCB_HEAD0x128, SCB_LIST_NULL0xFF00); | |||
594 | ||||
595 | /* | |||
596 | * Restore state. | |||
597 | */ | |||
598 | ahd_set_scbptr(ahd, saved_scbptr); | |||
599 | ahd_restore_modes(ahd, saved_modes); | |||
600 | ahd->flags |= AHD_UPDATE_PEND_CMDS; | |||
601 | } | |||
602 | ||||
603 | /* | |||
604 | * Determine if an SCB for a packetized transaction | |||
605 | * is active in a FIFO. | |||
606 | */ | |||
607 | int | |||
608 | ahd_scb_active_in_fifo(struct ahd_softc *ahd, struct scb *scb) | |||
609 | { | |||
610 | ||||
611 | /* | |||
612 | * The FIFO is only active for our transaction if | |||
613 | * the SCBPTR matches the SCB's ID and the firmware | |||
614 | * has installed a handler for the FIFO or we have | |||
615 | * a pending SAVEPTRS or CFG4DATA interrupt. | |||
616 | */ | |||
617 | if (ahd_get_scbptr(ahd) != SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)) | |||
618 | || ((ahd_inb(ahd, LONGJMP_ADDR+1)(((ahd)->tags[(0xf8 +1) >> 8])->read_1(((ahd)-> bshs[(0xf8 +1) >> 8]), ((0xf8 +1) & 0xFF))) & INVALID_ADDR0x80) != 0 | |||
619 | && (ahd_inb(ahd, SEQINTSRC)(((ahd)->tags[(0x5b) >> 8])->read_1(((ahd)->bshs [(0x5b) >> 8]), ((0x5b) & 0xFF))) & (CFG4DATA0x10|SAVEPTRS0x20)) == 0)) | |||
620 | return (0); | |||
621 | ||||
622 | return (1); | |||
623 | } | |||
624 | ||||
625 | /* | |||
626 | * Run a data fifo to completion for a transaction we know | |||
627 | * has completed across the SCSI bus (good status has been | |||
628 | * received). We are already set to the correct FIFO mode | |||
629 | * on entry to this routine. | |||
630 | * | |||
631 | * This function attempts to operate exactly as the firmware | |||
632 | * would when running this FIFO. Care must be taken to update | |||
633 | * this routine any time the firmware's FIFO algorithm is | |||
634 | * changed. | |||
635 | */ | |||
636 | void | |||
637 | ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb) | |||
638 | { | |||
639 | u_int seqintsrc; | |||
640 | ||||
641 | seqintsrc = ahd_inb(ahd, SEQINTSRC)(((ahd)->tags[(0x5b) >> 8])->read_1(((ahd)->bshs [(0x5b) >> 8]), ((0x5b) & 0xFF))); | |||
642 | if ((seqintsrc & CFG4DATA0x10) != 0) { | |||
643 | uint32_t datacnt; | |||
644 | uint32_t sgptr; | |||
645 | ||||
646 | /* | |||
647 | * Clear full residual flag. | |||
648 | */ | |||
649 | sgptr = ahd_inl_scbram(ahd, SCB_SGPTR0x1a4) & ~SG_FULL_RESID0x02; | |||
650 | ahd_outb(ahd, SCB_SGPTR, sgptr)(((ahd)->tags[(0x1a4) >> 8])->write_1(((ahd)-> bshs[(0x1a4) >> 8]), ((0x1a4) & 0xFF), (sgptr))); | |||
651 | ||||
652 | /* | |||
653 | * Load datacnt and address. | |||
654 | */ | |||
655 | datacnt = ahd_inl_scbram(ahd, SCB_DATACNT0x1a0); | |||
656 | if ((datacnt & AHD_DMA_LAST_SEG0x80000000) != 0) { | |||
657 | sgptr |= LAST_SEG0x02; | |||
658 | ahd_outb(ahd, SG_STATE, 0)(((ahd)->tags[(0xa6) >> 8])->write_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF), (0))); | |||
659 | } else | |||
660 | ahd_outb(ahd, SG_STATE, LOADING_NEEDED)(((ahd)->tags[(0xa6) >> 8])->write_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF), (0x02))); | |||
661 | ahd_outq(ahd, HADDR0x70, ahd_inq_scbram(ahd, SCB_DATAPTR0x198)); | |||
662 | ahd_outl(ahd, HCNT0x78, datacnt & AHD_SG_LEN_MASK0x00FFFFFF); | |||
663 | ahd_outb(ahd, SG_CACHE_PRE, sgptr)(((ahd)->tags[(0x1b) >> 8])->write_1(((ahd)->bshs [(0x1b) >> 8]), ((0x1b) & 0xFF), (sgptr))); | |||
664 | ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN)(((ahd)->tags[(0x19) >> 8])->write_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF), (0x80|0x20|0x08))); | |||
665 | ||||
666 | /* | |||
667 | * Initialize Residual Fields. | |||
668 | */ | |||
669 | ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24)(((ahd)->tags[(0x180 +3) >> 8])->write_1(((ahd)-> bshs[(0x180 +3) >> 8]), ((0x180 +3) & 0xFF), (datacnt >> 24))); | |||
670 | ahd_outl(ahd, SCB_RESIDUAL_SGPTR0x184, sgptr & SG_PTR_MASK0xFFFFFFF8); | |||
671 | ||||
672 | /* | |||
673 | * Mark the SCB as having a FIFO in use. | |||
674 | */ | |||
675 | ahd_outb(ahd, SCB_FIFO_USE_COUNT,(((ahd)->tags[(0x190) >> 8])->write_1(((ahd)-> bshs[(0x190) >> 8]), ((0x190) & 0xFF), (ahd_inb_scbram (ahd, 0x190) + 1))) | |||
676 | ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1)(((ahd)->tags[(0x190) >> 8])->write_1(((ahd)-> bshs[(0x190) >> 8]), ((0x190) & 0xFF), (ahd_inb_scbram (ahd, 0x190) + 1))); | |||
677 | ||||
678 | /* | |||
679 | * Install a "fake" handler for this FIFO. | |||
680 | */ | |||
681 | ahd_outw(ahd, LONGJMP_ADDR0xf8, 0); | |||
682 | ||||
683 | /* | |||
684 | * Notify the hardware that we have satisfied | |||
685 | * this sequencer interrupt. | |||
686 | */ | |||
687 | ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA)(((ahd)->tags[(0x5b) >> 8])->write_1(((ahd)->bshs [(0x5b) >> 8]), ((0x5b) & 0xFF), (0x10))); | |||
688 | } else if ((seqintsrc & SAVEPTRS0x20) != 0) { | |||
689 | uint32_t sgptr; | |||
690 | uint32_t resid; | |||
691 | ||||
692 | if ((ahd_inb(ahd, LONGJMP_ADDR+1)(((ahd)->tags[(0xf8 +1) >> 8])->read_1(((ahd)-> bshs[(0xf8 +1) >> 8]), ((0xf8 +1) & 0xFF)))&INVALID_ADDR0x80) != 0) { | |||
693 | /* | |||
694 | * Snapshot Save Pointers. All that | |||
695 | * is necessary to clear the snapshot | |||
696 | * is a CLRCHN. | |||
697 | */ | |||
698 | goto clrchn; | |||
699 | } | |||
700 | ||||
701 | /* | |||
702 | * Disable S/G fetch so the DMA engine | |||
703 | * is available to future users. | |||
704 | */ | |||
705 | if ((ahd_inb(ahd, SG_STATE)(((ahd)->tags[(0xa6) >> 8])->read_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF))) & FETCH_INPROG0x04) != 0) | |||
706 | ahd_outb(ahd, CCSGCTL, 0)(((ahd)->tags[(0xad) >> 8])->write_1(((ahd)->bshs [(0xad) >> 8]), ((0xad) & 0xFF), (0))); | |||
707 | ahd_outb(ahd, SG_STATE, 0)(((ahd)->tags[(0xa6) >> 8])->write_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF), (0))); | |||
708 | ||||
709 | /* | |||
710 | * Flush the data FIFO. Strictly only | |||
711 | * necessary for Rev A parts. | |||
712 | */ | |||
713 | ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH)(((ahd)->tags[(0x19) >> 8])->write_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF), ((((ahd)->tags[ (0x19) >> 8])->read_1(((ahd)->bshs[(0x19) >> 8]), ((0x19) & 0xFF))) | 0x02))); | |||
714 | ||||
715 | /* | |||
716 | * Calculate residual. | |||
717 | */ | |||
718 | sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR0x184); | |||
719 | resid = ahd_inl(ahd, SHCNT0x68); | |||
720 | resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT0x180+3) << 24; | |||
721 | ahd_outl(ahd, SCB_RESIDUAL_DATACNT0x180, resid); | |||
722 | if ((ahd_inb(ahd, SG_CACHE_SHADOW)(((ahd)->tags[(0x1b) >> 8])->read_1(((ahd)->bshs [(0x1b) >> 8]), ((0x1b) & 0xFF))) & LAST_SEG0x02) == 0) { | |||
723 | /* | |||
724 | * Must back up to the correct S/G element. | |||
725 | * Typically this just means resetting our | |||
726 | * low byte to the offset in the SG_CACHE, | |||
727 | * but if we wrapped, we have to correct | |||
728 | * the other bytes of the sgptr too. | |||
729 | */ | |||
730 | if ((ahd_inb(ahd, SG_CACHE_SHADOW)(((ahd)->tags[(0x1b) >> 8])->read_1(((ahd)->bshs [(0x1b) >> 8]), ((0x1b) & 0xFF))) & 0x80) != 0 | |||
731 | && (sgptr & 0x80) == 0) | |||
732 | sgptr -= 0x100; | |||
733 | sgptr &= ~0xFF; | |||
734 | sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)(((ahd)->tags[(0x1b) >> 8])->read_1(((ahd)->bshs [(0x1b) >> 8]), ((0x1b) & 0xFF))) | |||
735 | & SG_ADDR_MASK0xf8; | |||
736 | ahd_outl(ahd, SCB_RESIDUAL_SGPTR0x184, sgptr); | |||
737 | ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0)(((ahd)->tags[(0x180 + 3) >> 8])->write_1(((ahd)-> bshs[(0x180 + 3) >> 8]), ((0x180 + 3) & 0xFF), (0)) ); | |||
738 | } else if ((resid & AHD_SG_LEN_MASK0x00FFFFFF) == 0) { | |||
739 | ahd_outb(ahd, SCB_RESIDUAL_SGPTR,(((ahd)->tags[(0x184) >> 8])->write_1(((ahd)-> bshs[(0x184) >> 8]), ((0x184) & 0xFF), (sgptr | 0x01 ))) | |||
740 | sgptr | SG_LIST_NULL)(((ahd)->tags[(0x184) >> 8])->write_1(((ahd)-> bshs[(0x184) >> 8]), ((0x184) & 0xFF), (sgptr | 0x01 ))); | |||
741 | } | |||
742 | /* | |||
743 | * Save Pointers. | |||
744 | */ | |||
745 | ahd_outq(ahd, SCB_DATAPTR0x198, ahd_inq(ahd, SHADDR0x60)); | |||
746 | ahd_outl(ahd, SCB_DATACNT0x1a0, resid); | |||
747 | ahd_outl(ahd, SCB_SGPTR0x1a4, sgptr); | |||
748 | ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS)(((ahd)->tags[(0x5b) >> 8])->write_1(((ahd)->bshs [(0x5b) >> 8]), ((0x5b) & 0xFF), (0x20))); | |||
749 | ahd_outb(ahd, SEQIMODE,(((ahd)->tags[(0x5c) >> 8])->write_1(((ahd)->bshs [(0x5c) >> 8]), ((0x5c) & 0xFF), ((((ahd)->tags[ (0x5c) >> 8])->read_1(((ahd)->bshs[(0x5c) >> 8]), ((0x5c) & 0xFF))) | 0x20))) | |||
750 | ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS)(((ahd)->tags[(0x5c) >> 8])->write_1(((ahd)->bshs [(0x5c) >> 8]), ((0x5c) & 0xFF), ((((ahd)->tags[ (0x5c) >> 8])->read_1(((ahd)->bshs[(0x5c) >> 8]), ((0x5c) & 0xFF))) | 0x20))); | |||
751 | /* | |||
752 | * If the data is to the SCSI bus, we are | |||
753 | * done, otherwise wait for FIFOEMP. | |||
754 | */ | |||
755 | if ((ahd_inb(ahd, DFCNTRL)(((ahd)->tags[(0x19) >> 8])->read_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF))) & DIRECTION0x04) != 0) | |||
756 | goto clrchn; | |||
757 | } else if ((ahd_inb(ahd, SG_STATE)(((ahd)->tags[(0xa6) >> 8])->read_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF))) & LOADING_NEEDED0x02) != 0) { | |||
758 | uint32_t sgptr; | |||
759 | uint64_t data_addr; | |||
760 | uint32_t data_len; | |||
761 | u_int dfcntrl; | |||
762 | ||||
763 | /* | |||
764 | * Disable S/G fetch so the DMA engine | |||
765 | * is available to future users. We won't | |||
766 | * be using the DMA engine to load segments. | |||
767 | */ | |||
768 | if ((ahd_inb(ahd, SG_STATE)(((ahd)->tags[(0xa6) >> 8])->read_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF))) & FETCH_INPROG0x04) != 0) { | |||
769 | ahd_outb(ahd, CCSGCTL, 0)(((ahd)->tags[(0xad) >> 8])->write_1(((ahd)->bshs [(0xad) >> 8]), ((0xad) & 0xFF), (0))); | |||
770 | ahd_outb(ahd, SG_STATE, LOADING_NEEDED)(((ahd)->tags[(0xa6) >> 8])->write_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF), (0x02))); | |||
771 | } | |||
772 | ||||
773 | /* | |||
774 | * Wait for the DMA engine to notice that the | |||
775 | * host transfer is enabled and that there is | |||
776 | * space in the S/G FIFO for new segments before | |||
777 | * loading more segments. | |||
778 | */ | |||
779 | if ((ahd_inb(ahd, DFSTATUS)(((ahd)->tags[(0x1a) >> 8])->read_1(((ahd)->bshs [(0x1a) >> 8]), ((0x1a) & 0xFF))) & PRELOAD_AVAIL0x80) != 0 | |||
780 | && (ahd_inb(ahd, DFCNTRL)(((ahd)->tags[(0x19) >> 8])->read_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF))) & HDMAENACK0x08) != 0) { | |||
781 | ||||
782 | /* | |||
783 | * Determine the offset of the next S/G | |||
784 | * element to load. | |||
785 | */ | |||
786 | sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR0x184); | |||
787 | sgptr &= SG_PTR_MASK0xFFFFFFF8; | |||
788 | if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) { | |||
789 | struct ahd_dma64_seg *sg; | |||
790 | ||||
791 | sg = ahd_sg_bus_to_virt(ahd, scb, sgptr); | |||
792 | data_addr = sg->addr; | |||
793 | data_len = sg->len; | |||
794 | sgptr += sizeof(*sg); | |||
795 | } else { | |||
796 | struct ahd_dma_seg *sg; | |||
797 | ||||
798 | sg = ahd_sg_bus_to_virt(ahd, scb, sgptr); | |||
799 | data_addr = sg->len & AHD_SG_HIGH_ADDR_MASK0x7F000000; | |||
800 | data_addr <<= 8; | |||
801 | data_addr |= sg->addr; | |||
802 | data_len = sg->len; | |||
803 | sgptr += sizeof(*sg); | |||
804 | } | |||
805 | ||||
806 | /* | |||
807 | * Update residual information. | |||
808 | */ | |||
809 | ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, data_len >> 24)(((ahd)->tags[(0x180 +3) >> 8])->write_1(((ahd)-> bshs[(0x180 +3) >> 8]), ((0x180 +3) & 0xFF), (data_len >> 24))); | |||
810 | ahd_outl(ahd, SCB_RESIDUAL_SGPTR0x184, sgptr); | |||
811 | ||||
812 | /* | |||
813 | * Load the S/G. | |||
814 | */ | |||
815 | if (data_len & AHD_DMA_LAST_SEG0x80000000) { | |||
816 | sgptr |= LAST_SEG0x02; | |||
817 | ahd_outb(ahd, SG_STATE, 0)(((ahd)->tags[(0xa6) >> 8])->write_1(((ahd)->bshs [(0xa6) >> 8]), ((0xa6) & 0xFF), (0))); | |||
818 | } | |||
819 | ahd_outq(ahd, HADDR0x70, data_addr); | |||
820 | ahd_outl(ahd, HCNT0x78, data_len & AHD_SG_LEN_MASK0x00FFFFFF); | |||
821 | ahd_outb(ahd, SG_CACHE_PRE, sgptr & 0xFF)(((ahd)->tags[(0x1b) >> 8])->write_1(((ahd)->bshs [(0x1b) >> 8]), ((0x1b) & 0xFF), (sgptr & 0xFF) )); | |||
822 | ||||
823 | /* | |||
824 | * Advertise the segment to the hardware. | |||
825 | */ | |||
826 | dfcntrl = ahd_inb(ahd, DFCNTRL)(((ahd)->tags[(0x19) >> 8])->read_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF)))|PRELOADEN0x80|HDMAEN0x08; | |||
827 | if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) { | |||
828 | /* | |||
829 | * Use SCSIENWRDIS so that SCSIEN | |||
830 | * is never modified by this | |||
831 | * operation. | |||
832 | */ | |||
833 | dfcntrl |= SCSIENWRDIS0x40; | |||
834 | } | |||
835 | ahd_outb(ahd, DFCNTRL, dfcntrl)(((ahd)->tags[(0x19) >> 8])->write_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF), (dfcntrl))); | |||
836 | } | |||
837 | } else if ((ahd_inb(ahd, SG_CACHE_SHADOW)(((ahd)->tags[(0x1b) >> 8])->read_1(((ahd)->bshs [(0x1b) >> 8]), ((0x1b) & 0xFF))) & LAST_SEG_DONE0x01) != 0) { | |||
838 | ||||
839 | /* | |||
840 | * Transfer completed to the end of SG list | |||
841 | * and has flushed to the host. | |||
842 | */ | |||
843 | ahd_outb(ahd, SCB_SGPTR,(((ahd)->tags[(0x1a4) >> 8])->write_1(((ahd)-> bshs[(0x1a4) >> 8]), ((0x1a4) & 0xFF), (ahd_inb_scbram (ahd, 0x1a4) | 0x01))) | |||
844 | ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL)(((ahd)->tags[(0x1a4) >> 8])->write_1(((ahd)-> bshs[(0x1a4) >> 8]), ((0x1a4) & 0xFF), (ahd_inb_scbram (ahd, 0x1a4) | 0x01))); | |||
845 | goto clrchn; | |||
846 | } else if ((ahd_inb(ahd, DFSTATUS)(((ahd)->tags[(0x1a) >> 8])->read_1(((ahd)->bshs [(0x1a) >> 8]), ((0x1a) & 0xFF))) & FIFOEMP0x01) != 0) { | |||
847 | clrchn: | |||
848 | /* | |||
849 | * Clear any handler for this FIFO, decrement | |||
850 | * the FIFO use count for the SCB, and release | |||
851 | * the FIFO. | |||
852 | */ | |||
853 | ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR)(((ahd)->tags[(0xf8 + 1) >> 8])->write_1(((ahd)-> bshs[(0xf8 + 1) >> 8]), ((0xf8 + 1) & 0xFF), (0x80) )); | |||
854 | ahd_outb(ahd, SCB_FIFO_USE_COUNT,(((ahd)->tags[(0x190) >> 8])->write_1(((ahd)-> bshs[(0x190) >> 8]), ((0x190) & 0xFF), (ahd_inb_scbram (ahd, 0x190) - 1))) | |||
855 | ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1)(((ahd)->tags[(0x190) >> 8])->write_1(((ahd)-> bshs[(0x190) >> 8]), ((0x190) & 0xFF), (ahd_inb_scbram (ahd, 0x190) - 1))); | |||
856 | ahd_outb(ahd, DFFSXFRCTL, CLRCHN)(((ahd)->tags[(0x5a) >> 8])->write_1(((ahd)->bshs [(0x5a) >> 8]), ((0x5a) & 0xFF), (0x02))); | |||
857 | } | |||
858 | } | |||
859 | ||||
860 | /* | |||
861 | * Look for entries in the QoutFIFO that have completed. | |||
862 | * The valid_tag completion field indicates the validity | |||
863 | * of the entry - the valid value toggles each time through | |||
864 | * the queue. We use the sg_status field in the completion | |||
865 | * entry to avoid referencing the hscb if the completion | |||
866 | * occurred with no errors and no residual. sg_status is | |||
867 | * a copy of the first byte (little endian) of the sgptr | |||
868 | * hscb field. | |||
869 | */ | |||
870 | void | |||
871 | ahd_run_qoutfifo(struct ahd_softc *ahd) | |||
872 | { | |||
873 | struct ahd_completion *completion; | |||
874 | struct scb *scb; | |||
875 | u_int scb_index; | |||
876 | ||||
877 | if ((ahd->flags & AHD_RUNNING_QOUTFIFO) != 0) | |||
878 | panic("ahd_run_qoutfifo recursion"); | |||
879 | ahd->flags |= AHD_RUNNING_QOUTFIFO; | |||
880 | ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD0x02); | |||
881 | for (;;) { | |||
882 | completion = &ahd->qoutfifo[ahd->qoutfifonext]; | |||
883 | ||||
884 | if (completion->valid_tag != ahd->qoutfifonext_valid_tag) | |||
885 | break; | |||
886 | ||||
887 | scb_index = aic_le16toh(completion->tag)((__uint16_t)(completion->tag)); | |||
888 | scb = ahd_lookup_scb(ahd, scb_index); | |||
889 | if (scb == NULL((void *)0)) { | |||
890 | printf("%s: WARNING no command for scb %d " | |||
891 | "(cmdcmplt)\nQOUTPOS = %d\n", | |||
892 | ahd_name(ahd), scb_index, | |||
893 | ahd->qoutfifonext); | |||
894 | ahd_dump_card_state(ahd); | |||
895 | } else if ((completion->sg_status & SG_STATUS_VALID0x04) != 0) { | |||
896 | ahd_handle_scb_status(ahd, scb); | |||
897 | } else { | |||
898 | ahd_done(ahd, scb); | |||
899 | } | |||
900 | ||||
901 | ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE512-1); | |||
902 | if (ahd->qoutfifonext == 0) | |||
903 | ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID0x80; | |||
904 | } | |||
905 | ahd->flags &= ~AHD_RUNNING_QOUTFIFO; | |||
906 | } | |||
907 | ||||
908 | /************************* Interrupt Handling *********************************/ | |||
909 | void | |||
910 | ahd_handle_hwerrint(struct ahd_softc *ahd) | |||
911 | { | |||
912 | /* | |||
913 | * Some catastrophic hardware error has occurred. | |||
914 | * Print it for the user and disable the controller. | |||
915 | */ | |||
916 | int i; | |||
917 | int error; | |||
918 | ||||
919 | error = ahd_inb(ahd, ERROR)(((ahd)->tags[(0x04) >> 8])->read_1(((ahd)->bshs [(0x04) >> 8]), ((0x04) & 0xFF))); | |||
920 | for (i = 0; i < num_errors; i++) { | |||
921 | if ((error & ahd_hard_errors[i].errno) != 0) | |||
922 | printf("%s: hwerrint, %s\n", | |||
923 | ahd_name(ahd), ahd_hard_errors[i].errmesg); | |||
924 | } | |||
925 | ||||
926 | ahd_dump_card_state(ahd); | |||
927 | panic("BRKADRINT"); | |||
928 | ||||
929 | /* Tell everyone that this HBA is no longer available */ | |||
930 | ahd_abort_scbs(ahd, CAM_TARGET_WILDCARD((u_int)~0), ALL_CHANNELS'\0', | |||
931 | CAM_LUN_WILDCARD-1, SCB_LIST_NULL0xFF00, ROLE_UNKNOWN, | |||
932 | CAM_NO_HBA); | |||
933 | ||||
934 | /* Tell the system that this controller has gone away. */ | |||
935 | ahd_free(ahd); | |||
936 | } | |||
937 | ||||
938 | void | |||
939 | ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) | |||
940 | { | |||
941 | u_int seqintcode; | |||
942 | ||||
943 | /* | |||
944 | * Save the sequencer interrupt code and clear the SEQINT | |||
945 | * bit. We will unpause the sequencer, if appropriate, | |||
946 | * after servicing the request. | |||
947 | */ | |||
948 | seqintcode = ahd_inb(ahd, SEQINTCODE)(((ahd)->tags[(0x02) >> 8])->read_1(((ahd)->bshs [(0x02) >> 8]), ((0x02) & 0xFF))); | |||
949 | ahd_outb(ahd, CLRINT, CLRSEQINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x04))); | |||
950 | if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) { | |||
951 | /* | |||
952 | * Unpause the sequencer and let it clear | |||
953 | * SEQINT by writing NO_SEQINT to it. This | |||
954 | * will cause the sequencer to be paused again, | |||
955 | * which is the expected state of this routine. | |||
956 | */ | |||
957 | ahd_unpause(ahd); | |||
958 | while (!ahd_is_paused(ahd)) | |||
959 | ; | |||
960 | ahd_outb(ahd, CLRINT, CLRSEQINT)(((ahd)->tags[(0x03) >> 8])->write_1(((ahd)->bshs [(0x03) >> 8]), ((0x03) & 0xFF), (0x04))); | |||
961 | } | |||
962 | ahd_update_modes(ahd); | |||
963 | #ifdef AHD_DEBUG | |||
964 | if ((ahd_debug & AHD_SHOW_MISC) != 0) | |||
965 | printf("%s: Handle Seqint Called for code %d\n", | |||
966 | ahd_name(ahd), seqintcode); | |||
967 | #endif | |||
968 | switch (seqintcode) { | |||
969 | case ENTERING_NONPACK0x12: | |||
970 | { | |||
971 | struct scb *scb; | |||
972 | u_int scbid; | |||
973 | ||||
974 | AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),ahd_assert_modes(ahd, ~((0x01 << (AHD_MODE_UNKNOWN))|(0x01 << (AHD_MODE_CFG))), ~((0x01 << (AHD_MODE_UNKNOWN ))|(0x01 << (AHD_MODE_CFG))), "/usr/src/sys/dev/ic/aic79xx.c" , 975); | |||
975 | ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK))ahd_assert_modes(ahd, ~((0x01 << (AHD_MODE_UNKNOWN))|(0x01 << (AHD_MODE_CFG))), ~((0x01 << (AHD_MODE_UNKNOWN ))|(0x01 << (AHD_MODE_CFG))), "/usr/src/sys/dev/ic/aic79xx.c" , 975);; | |||
976 | scbid = ahd_get_scbptr(ahd); | |||
977 | scb = ahd_lookup_scb(ahd, scbid); | |||
978 | if (scb == NULL((void *)0)) { | |||
979 | /* | |||
980 | * Somehow need to know if this | |||
981 | * is from a selection or reselection. | |||
982 | * From that, we can determine target | |||
983 | * ID so we at least have an I_T nexus. | |||
984 | */ | |||
985 | } else { | |||
986 | ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid)(((ahd)->tags[(0x13a) >> 8])->write_1(((ahd)-> bshs[(0x13a) >> 8]), ((0x13a) & 0xFF), (scb->hscb ->scsiid))); | |||
987 | ahd_outb(ahd, SAVED_LUN, scb->hscb->lun)(((ahd)->tags[(0x13b) >> 8])->write_1(((ahd)-> bshs[(0x13b) >> 8]), ((0x13b) & 0xFF), (scb->hscb ->lun))); | |||
988 | ahd_outb(ahd, SEQ_FLAGS, 0x0)(((ahd)->tags[(0x139) >> 8])->write_1(((ahd)-> bshs[(0x139) >> 8]), ((0x139) & 0xFF), (0x0))); | |||
989 | } | |||
990 | if ((ahd_inb(ahd, LQISTAT2)(((ahd)->tags[(0x52) >> 8])->read_1(((ahd)->bshs [(0x52) >> 8]), ((0x52) & 0xFF))) & LQIPHASE_OUTPKT0x40) != 0 | |||
991 | && (ahd_inb(ahd, SCSISIGO)(((ahd)->tags[(0x40) >> 8])->read_1(((ahd)->bshs [(0x40) >> 8]), ((0x40) & 0xFF))) & ATNO0x10) != 0) { | |||
992 | /* | |||
993 | * Phase change after read stream with | |||
994 | * CRC error with P0 asserted on last | |||
995 | * packet. | |||
996 | */ | |||
997 | #ifdef AHD_DEBUG | |||
998 | if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) | |||
999 | printf("%s: Assuming LQIPHASE_NLQ with " | |||
1000 | "P0 assertion\n", ahd_name(ahd)); | |||
1001 | #endif | |||
1002 | } | |||
1003 | #ifdef AHD_DEBUG | |||
1004 | if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) | |||
1005 | printf("%s: Entering NONPACK\n", ahd_name(ahd)); | |||
1006 | #endif | |||
1007 | break; | |||
1008 | } | |||
1009 | case INVALID_SEQINT0x0e: | |||
1010 | printf("%s: Invalid Sequencer interrupt occurred.\n", | |||
1011 | ahd_name(ahd)); | |||
1012 | ahd_dump_card_state(ahd); | |||
1013 | ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE1); | |||
1014 | break; | |||
1015 | case STATUS_OVERRUN0x10: | |||
1016 | { | |||
1017 | struct scb *scb; | |||
1018 | u_int scbid; | |||
1019 | ||||
1020 | scbid = ahd_get_scbptr(ahd); | |||
1021 | scb = ahd_lookup_scb(ahd, scbid); | |||
1022 | if (scb != NULL((void *)0)) | |||
1023 | ahd_print_path(ahd, scb); | |||
1024 | else | |||
1025 | printf("%s: ", ahd_name(ahd)); | |||
1026 | printf("SCB %d Packetized Status Overrun", scbid); | |||
1027 | ahd_dump_card_state(ahd); | |||
1028 | ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE1); | |||
1029 | break; | |||
1030 | } | |||
1031 | case CFG4ISTAT_INTR0x0f: | |||
1032 | { | |||
1033 | struct scb *scb; | |||
1034 | u_int scbid; | |||
1035 | ||||
1036 | scbid = ahd_get_scbptr(ahd); | |||
1037 | scb = ahd_lookup_scb(ahd, scbid); | |||
1038 | if (scb == NULL((void *)0)) { | |||
1039 | ahd_dump_card_state(ahd); | |||
1040 | printf("CFG4ISTAT: Free SCB %d referenced", scbid); | |||
1041 | panic("For safety"); | |||
1042 | } | |||
1043 | ahd_outq(ahd, HADDR0x70, scb->sense_busaddr); | |||
1044 | ahd_outw(ahd, HCNT0x78, AHD_SENSE_BUFSIZE0x100); | |||
1045 | ahd_outb(ahd, HCNT + 2, 0)(((ahd)->tags[(0x78 + 2) >> 8])->write_1(((ahd)-> bshs[(0x78 + 2) >> 8]), ((0x78 + 2) & 0xFF), (0))); | |||
1046 | ahd_outb(ahd, SG_CACHE_PRE, SG_LAST_SEG)(((ahd)->tags[(0x1b) >> 8])->write_1(((ahd)->bshs [(0x1b) >> 8]), ((0x1b) & 0xFF), (0x80))); | |||
1047 | ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN)(((ahd)->tags[(0x19) >> 8])->write_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF), (0x80|0x20|0x08))); | |||
1048 | break; | |||
1049 | } | |||
1050 | case ILLEGAL_PHASE0x0d: | |||
1051 | { | |||
1052 | u_int bus_phase; | |||
1053 | ||||
1054 | bus_phase = ahd_inb(ahd, SCSISIGI)(((ahd)->tags[(0x41) >> 8])->read_1(((ahd)->bshs [(0x41) >> 8]), ((0x41) & 0xFF))) & PHASE_MASK0xe0; | |||
1055 | printf("%s: ILLEGAL_PHASE 0x%x\n", | |||
1056 | ahd_name(ahd), bus_phase); | |||
1057 | ||||
1058 | switch (bus_phase) { | |||
1059 | case P_DATAOUT0x00: | |||
1060 | case P_DATAIN0x40: | |||
1061 | case P_DATAOUT_DT0x20: | |||
1062 | case P_DATAIN_DT0x60: | |||
1063 | case P_MESGOUT0xa0: | |||
1064 | case P_STATUS0xc0: | |||
1065 | case P_MESGIN0xe0: | |||
1066 | ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE1); | |||
1067 | printf("%s: Issued Bus Reset.\n", ahd_name(ahd)); | |||
1068 | break; | |||
1069 | case P_COMMAND0x80: | |||
1070 | { | |||
1071 | struct ahd_devinfo devinfo; | |||
1072 | struct scb *scb; | |||
1073 | struct ahd_initiator_tinfo *targ_info; | |||
1074 | struct ahd_tmode_tstate *tstate; | |||
1075 | u_int scbid; | |||
1076 | ||||
1077 | /* | |||
1078 | * If a target takes us into the command phase | |||
1079 | * assume that it has been externally reset and | |||
1080 | * has thus lost our previous packetized negotiation | |||
1081 | * agreement. Since we have not sent an identify | |||
1082 | * message and may not have fully qualified the | |||
1083 | * connection, we change our command to TUR, assert | |||
1084 | * ATN and ABORT the task when we go to message in | |||
1085 | * phase. The OSM will see the REQUEUE_REQUEST | |||
1086 | * status and retry the command. | |||
1087 | */ | |||
1088 | scbid = ahd_get_scbptr(ahd); | |||
1089 | scb = ahd_lookup_scb(ahd, scbid); | |||
1090 | if (scb == NULL((void *)0)) { | |||
1091 | printf("Invalid phase with no valid SCB. " | |||
1092 | "Resetting bus.\n"); | |||
1093 | ahd_reset_channel(ahd, 'A', | |||
1094 | /*Initiate Reset*/TRUE1); | |||
1095 | break; | |||
1096 | } | |||
1097 | ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb)(((scb)->hscb->scsiid) & 0x0f), | |||
1098 | SCB_GET_TARGET(ahd, scb)((((scb)->hscb->scsiid) & 0xf0) >> 0x04), | |||
1099 | SCB_GET_LUN(scb)((scb)->hscb->lun), | |||
1100 | SCB_GET_CHANNEL(ahd, scb)('A'), | |||
1101 | ROLE_INITIATOR); | |||
1102 | targ_info = ahd_fetch_transinfo(ahd, | |||
1103 | devinfo.channel, | |||
1104 | devinfo.our_scsiid, | |||
1105 | devinfo.target, | |||
1106 | &tstate); | |||
1107 | ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT0x00, | |||
1108 | AHD_TRANS_ACTIVE0x03, /*paused*/TRUE1); | |||
1109 | ahd_set_syncrate(ahd, &devinfo, /*period*/0, | |||
1110 | /*offset*/0, /*ppr_options*/0, | |||
1111 | AHD_TRANS_ACTIVE0x03, /*paused*/TRUE1); | |||
1112 | ahd_outb(ahd, SCB_CDB_STORE, 0)(((ahd)->tags[(0x180) >> 8])->write_1(((ahd)-> bshs[(0x180) >> 8]), ((0x180) & 0xFF), (0))); | |||
1113 | ahd_outb(ahd, SCB_CDB_STORE+1, 0)(((ahd)->tags[(0x180 +1) >> 8])->write_1(((ahd)-> bshs[(0x180 +1) >> 8]), ((0x180 +1) & 0xFF), (0))); | |||
1114 | ahd_outb(ahd, SCB_CDB_STORE+2, 0)(((ahd)->tags[(0x180 +2) >> 8])->write_1(((ahd)-> bshs[(0x180 +2) >> 8]), ((0x180 +2) & 0xFF), (0))); | |||
1115 | ahd_outb(ahd, SCB_CDB_STORE+3, 0)(((ahd)->tags[(0x180 +3) >> 8])->write_1(((ahd)-> bshs[(0x180 +3) >> 8]), ((0x180 +3) & 0xFF), (0))); | |||
1116 | ahd_outb(ahd, SCB_CDB_STORE+4, 0)(((ahd)->tags[(0x180 +4) >> 8])->write_1(((ahd)-> bshs[(0x180 +4) >> 8]), ((0x180 +4) & 0xFF), (0))); | |||
1117 | ahd_outb(ahd, SCB_CDB_STORE+5, 0)(((ahd)->tags[(0x180 +5) >> 8])->write_1(((ahd)-> bshs[(0x180 +5) >> 8]), ((0x180 +5) & 0xFF), (0))); | |||
1118 | ahd_outb(ahd, SCB_CDB_LEN, 6)(((ahd)->tags[(0x196) >> 8])->write_1(((ahd)-> bshs[(0x196) >> 8]), ((0x196) & 0xFF), (6))); | |||
1119 | scb->hscb->control &= ~(TAG_ENB0x20|SCB_TAG_TYPE0x03); | |||
1120 | scb->hscb->control |= MK_MESSAGE0x10; | |||
1121 | ahd_outb(ahd, SCB_CONTROL, scb->hscb->control)(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (scb->hscb ->control))); | |||
1122 | ahd_outb(ahd, MSG_OUT, HOST_MSG)(((ahd)->tags[(0x137) >> 8])->write_1(((ahd)-> bshs[(0x137) >> 8]), ((0x137) & 0xFF), (0xff))); | |||
1123 | ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid)(((ahd)->tags[(0x13a) >> 8])->write_1(((ahd)-> bshs[(0x13a) >> 8]), ((0x13a) & 0xFF), (scb->hscb ->scsiid))); | |||
1124 | /* | |||
1125 | * The lun is 0, regardless of the SCB's lun | |||
1126 | * as we have not sent an identify message. | |||
1127 | */ | |||
1128 | ahd_outb(ahd, SAVED_LUN, 0)(((ahd)->tags[(0x13b) >> 8])->write_1(((ahd)-> bshs[(0x13b) >> 8]), ((0x13b) & 0xFF), (0))); | |||
1129 | ahd_outb(ahd, SEQ_FLAGS, 0)(((ahd)->tags[(0x139) >> 8])->write_1(((ahd)-> bshs[(0x139) >> 8]), ((0x139) & 0xFF), (0))); | |||
1130 | ahd_assert_atn(ahd); | |||
1131 | scb->flags &= ~SCB_PACKETIZED; | |||
1132 | scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT; | |||
1133 | ahd_freeze_devq(ahd, scb); | |||
1134 | aic_set_transaction_status(scb, CAM_REQUEUE_REQ)(scb)->xs->error = (CAM_REQUEUE_REQ); | |||
1135 | aic_freeze_scb(scb); | |||
1136 | ||||
1137 | /* | |||
1138 | * Allow the sequencer to continue with | |||
1139 | * non-pack processing. | |||
1140 | */ | |||
1141 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | |||
1142 | ahd_outb(ahd, CLRLQOINT1, CLRLQOPHACHGINPKT)(((ahd)->tags[(0x55) >> 8])->write_1(((ahd)->bshs [(0x55) >> 8]), ((0x55) & 0xFF), (0x01))); | |||
1143 | if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) { | |||
1144 | ahd_outb(ahd, CLRLQOINT1, 0)(((ahd)->tags[(0x55) >> 8])->write_1(((ahd)->bshs [(0x55) >> 8]), ((0x55) & 0xFF), (0))); | |||
1145 | } | |||
1146 | #ifdef AHD_DEBUG | |||
1147 | if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { | |||
1148 | ahd_print_path(ahd, scb); | |||
1149 | printf("Unexpected command phase from " | |||
1150 | "packetized target\n"); | |||
1151 | } | |||
1152 | #endif | |||
1153 | break; | |||
1154 | } | |||
1155 | } | |||
1156 | break; | |||
1157 | } | |||
1158 | case CFG4OVERRUN0x11: | |||
1159 | { | |||
1160 | struct scb *scb; | |||
1161 | u_int scb_index; | |||
1162 | ||||
1163 | #ifdef AHD_DEBUG | |||
1164 | if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { | |||
1165 | printf("%s: CFG4OVERRUN mode = %x\n", ahd_name(ahd), | |||
1166 | ahd_inb(ahd, MODE_PTR)(((ahd)->tags[(0x00) >> 8])->read_1(((ahd)->bshs [(0x00) >> 8]), ((0x00) & 0xFF)))); | |||
1167 | } | |||
1168 | #endif | |||
1169 | scb_index = ahd_get_scbptr(ahd); | |||
1170 | scb = ahd_lookup_scb(ahd, scb_index); | |||
1171 | if (scb == NULL((void *)0)) { | |||
1172 | /* | |||
1173 | * Attempt to transfer to an SCB that is | |||
1174 | * not outstanding. | |||
1175 | */ | |||
1176 | ahd_assert_atn(ahd); | |||
1177 | ahd_outb(ahd, MSG_OUT, HOST_MSG)(((ahd)->tags[(0x137) >> 8])->write_1(((ahd)-> bshs[(0x137) >> 8]), ((0x137) & 0xFF), (0xff))); | |||
1178 | ahd->msgout_buf[0] = MSG_ABORT_TASK0x0d; | |||
1179 | ahd->msgout_len = 1; | |||
1180 | ahd->msgout_index = 0; | |||
1181 | ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT; | |||
1182 | /* | |||
1183 | * Clear status received flag to prevent any | |||
1184 | * attempt to complete this bogus SCB. | |||
1185 | */ | |||
1186 | ahd_outb(ahd, SCB_CONTROL,(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (ahd_inb_scbram (ahd, 0x192) & ~0x08))) | |||
1187 | ahd_inb_scbram(ahd, SCB_CONTROL)(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (ahd_inb_scbram (ahd, 0x192) & ~0x08))) | |||
1188 | & ~STATUS_RCVD)(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (ahd_inb_scbram (ahd, 0x192) & ~0x08))); | |||
1189 | } | |||
1190 | break; | |||
1191 | } | |||
1192 | case DUMP_CARD_STATE0x0c: | |||
1193 | { | |||
1194 | ahd_dump_card_state(ahd); | |||
1195 | break; | |||
1196 | } | |||
1197 | case PDATA_REINIT0x06: | |||
1198 | { | |||
1199 | #ifdef AHD_DEBUG | |||
1200 | if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { | |||
1201 | printf("%s: PDATA_REINIT - DFCNTRL = 0x%x " | |||
1202 | "SG_CACHE_SHADOW = 0x%x\n", | |||
1203 | ahd_name(ahd), ahd_inb(ahd, DFCNTRL)(((ahd)->tags[(0x19) >> 8])->read_1(((ahd)->bshs [(0x19) >> 8]), ((0x19) & 0xFF))), | |||
1204 | ahd_inb(ahd, SG_CACHE_SHADOW)(((ahd)->tags[(0x1b) >> 8])->read_1(((ahd)->bshs [(0x1b) >> 8]), ((0x1b) & 0xFF)))); | |||
1205 | } | |||
1206 | #endif | |||
1207 | ahd_reinitialize_dataptrs(ahd); | |||
1208 | break; | |||
1209 | } | |||
1210 | case HOST_MSG_LOOP0x07: | |||
1211 | { | |||
1212 | struct ahd_devinfo devinfo; | |||
1213 | ||||
1214 | /* | |||
1215 | * The sequencer has encountered a message phase | |||
1216 | * that requires host assistance for completion. | |||
1217 | * While handling the message phase(s), we will be | |||
1218 | * notified by the sequencer after each byte is | |||
1219 | * transferred so we can track bus phase changes. | |||
1220 | * | |||
1221 | * If this is the first time we've seen a HOST_MSG_LOOP | |||
1222 | * interrupt, initialize the state of the host message | |||
1223 | * loop. | |||
1224 | */ | |||
1225 | ahd_fetch_devinfo(ahd, &devinfo); | |||
1226 | if (ahd->msg_type == MSG_TYPE_NONE) { | |||
1227 | struct scb *scb; | |||
1228 | u_int scb_index; | |||
1229 | u_int bus_phase; | |||
1230 | ||||
1231 | bus_phase = ahd_inb(ahd, SCSISIGI)(((ahd)->tags[(0x41) >> 8])->read_1(((ahd)->bshs [(0x41) >> 8]), ((0x41) & 0xFF))) & PHASE_MASK0xe0; | |||
1232 | if (bus_phase != P_MESGIN0xe0 | |||
1233 | && bus_phase != P_MESGOUT0xa0) { | |||
1234 | printf("ahd_intr: HOST_MSG_LOOP bad " | |||
1235 | "phase 0x%x\n", bus_phase); | |||
1236 | /* | |||
1237 | * Probably transitioned to bus free before | |||
1238 | * we got here. Just punt the message. | |||
1239 | */ | |||
1240 | ahd_dump_card_state(ahd); | |||
1241 | ahd_clear_intstat(ahd); | |||
1242 | ahd_restart(ahd); | |||
1243 | return; | |||
1244 | } | |||
1245 | ||||
1246 | scb_index = ahd_get_scbptr(ahd); | |||
1247 | scb = ahd_lookup_scb(ahd, scb_index); | |||
1248 | if (devinfo.role == ROLE_INITIATOR) { | |||
1249 | if (bus_phase == P_MESGOUT0xa0) | |||
1250 | ahd_setup_initiator_msgout(ahd, | |||
1251 | &devinfo, | |||
1252 | scb); | |||
1253 | else { | |||
1254 | ahd->msg_type = | |||
1255 | MSG_TYPE_INITIATOR_MSGIN; | |||
1256 | ahd->msgin_index = 0; | |||
1257 | } | |||
1258 | } | |||
1259 | #if AHD_TARGET_MODE | |||
1260 | else { | |||
1261 | if (bus_phase == P_MESGOUT0xa0) { | |||
1262 | ahd->msg_type = | |||
1263 | MSG_TYPE_TARGET_MSGOUT; | |||
1264 | ahd->msgin_index = 0; | |||
1265 | } | |||
1266 | else | |||
1267 | ahd_setup_target_msgin(ahd, | |||
1268 | &devinfo, | |||
1269 | scb); | |||
1270 | } | |||
1271 | #endif | |||
1272 | } | |||
1273 | ||||
1274 | ahd_handle_message_phase(ahd); | |||
1275 | break; | |||
1276 | } | |||
1277 | case NO_MATCH0x04: | |||
1278 | { | |||
1279 | /* Ensure we don't leave the selection hardware on */ | |||
1280 | AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK)ahd_assert_modes(ahd, (0x01 << (AHD_MODE_SCSI)), (0x01 << (AHD_MODE_SCSI)), "/usr/src/sys/dev/ic/aic79xx.c", 1280);; | |||
1281 | ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO)(((ahd)->tags[(0x3a) >> 8])->write_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF), ((((ahd)->tags[ (0x3a) >> 8])->read_1(((ahd)->bshs[(0x3a) >> 8]), ((0x3a) & 0xFF))) & ~0x40))); | |||
1282 | ||||
1283 | printf("%s:%c:%d: no active SCB for reconnecting " | |||
1284 | "target - issuing BUS DEVICE RESET\n", | |||
1285 | ahd_name(ahd), 'A', ahd_inb(ahd, SELID)(((ahd)->tags[(0x49) >> 8])->read_1(((ahd)->bshs [(0x49) >> 8]), ((0x49) & 0xFF))) >> 4); | |||
1286 | printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, " | |||
1287 | "REG0 == 0x%x ACCUM = 0x%x\n", | |||
1288 | ahd_inb(ahd, SAVED_SCSIID)(((ahd)->tags[(0x13a) >> 8])->read_1(((ahd)->bshs [(0x13a) >> 8]), ((0x13a) & 0xFF))), ahd_inb(ahd, SAVED_LUN)(((ahd)->tags[(0x13b) >> 8])->read_1(((ahd)->bshs [(0x13b) >> 8]), ((0x13b) & 0xFF))), | |||
1289 | ahd_inw(ahd, REG00xa0), ahd_inb(ahd, ACCUM)(((ahd)->tags[(0xe0) >> 8])->read_1(((ahd)->bshs [(0xe0) >> 8]), ((0xe0) & 0xFF)))); | |||
1290 | printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, " | |||
1291 | "SINDEX == 0x%x\n", | |||
1292 | ahd_inb(ahd, SEQ_FLAGS)(((ahd)->tags[(0x139) >> 8])->read_1(((ahd)->bshs [(0x139) >> 8]), ((0x139) & 0xFF))), ahd_get_scbptr(ahd), | |||
1293 | ahd_find_busy_tcl(ahd, | |||
1294 | BUILD_TCL(ahd_inb(ahd, SAVED_SCSIID),(((((ahd)->tags[(0x13b) >> 8])->read_1(((ahd)-> bshs[(0x13b) >> 8]), ((0x13b) & 0xFF)))) | ((((((ahd )->tags[(0x13a) >> 8])->read_1(((ahd)->bshs[(0x13a ) >> 8]), ((0x13a) & 0xFF)))) & 0xf0) << 4 )) | |||
1295 | ahd_inb(ahd, SAVED_LUN))(((((ahd)->tags[(0x13b) >> 8])->read_1(((ahd)-> bshs[(0x13b) >> 8]), ((0x13b) & 0xFF)))) | ((((((ahd )->tags[(0x13a) >> 8])->read_1(((ahd)->bshs[(0x13a ) >> 8]), ((0x13a) & 0xFF)))) & 0xf0) << 4 ))), | |||
1296 | ahd_inw(ahd, SINDEX0xe2)); | |||
1297 | printf("SELID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, " | |||
1298 | "SCB_CONTROL == 0x%x\n", | |||
1299 | ahd_inb(ahd, SELID)(((ahd)->tags[(0x49) >> 8])->read_1(((ahd)->bshs [(0x49) >> 8]), ((0x49) & 0xFF))), ahd_inb_scbram(ahd, SCB_SCSIID0x193), | |||
1300 | ahd_inb_scbram(ahd, SCB_LUN0x194), | |||
1301 | ahd_inb_scbram(ahd, SCB_CONTROL0x192)); | |||
1302 | printf("SCSIBUS[0] == 0x%x, SCSISIGI == 0x%x\n", | |||
1303 | ahd_inb(ahd, SCSIBUS)(((ahd)->tags[(0x46) >> 8])->read_1(((ahd)->bshs [(0x46) >> 8]), ((0x46) & 0xFF))), ahd_inb(ahd, SCSISIGI)(((ahd)->tags[(0x41) >> 8])->read_1(((ahd)->bshs [(0x41) >> 8]), ((0x41) & 0xFF)))); | |||
1304 | printf("SXFRCTL0 == 0x%x\n", ahd_inb(ahd, SXFRCTL0)(((ahd)->tags[(0x3c) >> 8])->read_1(((ahd)->bshs [(0x3c) >> 8]), ((0x3c) & 0xFF)))); | |||
1305 | printf("SEQCTL0 == 0x%x\n", ahd_inb(ahd, SEQCTL0)(((ahd)->tags[(0xd6) >> 8])->read_1(((ahd)->bshs [(0xd6) >> 8]), ((0xd6) & 0xFF)))); | |||
1306 | ahd_dump_card_state(ahd); | |||
1307 | ahd->msgout_buf[0] = MSG_BUS_DEV_RESET0x0c; | |||
1308 | ahd->msgout_len = 1; | |||
1309 | ahd->msgout_index = 0; | |||
1310 | ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT; | |||
1311 | ahd_outb(ahd, MSG_OUT, HOST_MSG)(((ahd)->tags[(0x137) >> 8])->write_1(((ahd)-> bshs[(0x137) >> 8]), ((0x137) & 0xFF), (0xff))); | |||
1312 | ahd_assert_atn(ahd); | |||
1313 | break; | |||
1314 | } | |||
1315 | case PROTO_VIOLATION0x03: | |||
1316 | { | |||
1317 | ahd_handle_proto_violation(ahd); | |||
1318 | break; | |||
1319 | } | |||
1320 | case IGN_WIDE_RES0x05: | |||
1321 | { | |||
1322 | struct ahd_devinfo devinfo; | |||
1323 | ||||
1324 | ahd_fetch_devinfo(ahd, &devinfo); | |||
1325 | ahd_handle_ign_wide_residue(ahd, &devinfo); | |||
1326 | break; | |||
1327 | } | |||
1328 | case BAD_PHASE0x01: | |||
1329 | { | |||
1330 | u_int lastphase; | |||
1331 | ||||
1332 | lastphase = ahd_inb(ahd, LASTPHASE)(((ahd)->tags[(0x13c) >> 8])->read_1(((ahd)->bshs [(0x13c) >> 8]), ((0x13c) & 0xFF))); | |||
1333 | printf("%s:%c:%d: unknown scsi bus phase %x, " | |||
1334 | "lastphase = 0x%x. Attempting to continue\n", | |||
1335 | ahd_name(ahd), 'A', | |||
1336 | SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID))((((((ahd)->tags[(0x13a) >> 8])->read_1(((ahd)-> bshs[(0x13a) >> 8]), ((0x13a) & 0xFF)))) & 0xf0 ) >> 0x04), | |||
1337 | lastphase, ahd_inb(ahd, SCSISIGI)(((ahd)->tags[(0x41) >> 8])->read_1(((ahd)->bshs [(0x41) >> 8]), ((0x41) & 0xFF)))); | |||
1338 | break; | |||
1339 | } | |||
1340 | case MISSED_BUSFREE0x0b: | |||
1341 | { | |||
1342 | u_int lastphase; | |||
1343 | ||||
1344 | lastphase = ahd_inb(ahd, LASTPHASE)(((ahd)->tags[(0x13c) >> 8])->read_1(((ahd)->bshs [(0x13c) >> 8]), ((0x13c) & 0xFF))); | |||
1345 | printf("%s:%c:%d: Missed busfree. " | |||
1346 | "Lastphase = 0x%x, Curphase = 0x%x\n", | |||
1347 | ahd_name(ahd), 'A', | |||
1348 | SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID))((((((ahd)->tags[(0x13a) >> 8])->read_1(((ahd)-> bshs[(0x13a) >> 8]), ((0x13a) & 0xFF)))) & 0xf0 ) >> 0x04), | |||
1349 | lastphase, ahd_inb(ahd, SCSISIGI)(((ahd)->tags[(0x41) >> 8])->read_1(((ahd)->bshs [(0x41) >> 8]), ((0x41) & 0xFF)))); | |||
1350 | ahd_restart(ahd); | |||
1351 | return; | |||
1352 | } | |||
1353 | case DATA_OVERRUN0x09: | |||
1354 | { | |||
1355 | /* | |||
1356 | * When the sequencer detects an overrun, it | |||
1357 | * places the controller in "BITBUCKET" mode | |||
1358 | * and allows the target to complete its transfer. | |||
1359 | * Unfortunately, none of the counters get updated | |||
1360 | * when the controller is in this mode, so we have | |||
1361 | * no way of knowing how large the overrun was. | |||
1362 | */ | |||
1363 | struct scb *scb; | |||
1364 | u_int scbindex; | |||
1365 | #ifdef AHD_DEBUG | |||
1366 | u_int lastphase; | |||
1367 | #endif | |||
1368 | ||||
1369 | scbindex = ahd_get_scbptr(ahd); | |||
1370 | scb = ahd_lookup_scb(ahd, scbindex); | |||
1371 | #ifdef AHD_DEBUG | |||
1372 | lastphase = ahd_inb(ahd, LASTPHASE)(((ahd)->tags[(0x13c) >> 8])->read_1(((ahd)->bshs [(0x13c) >> 8]), ((0x13c) & 0xFF))); | |||
1373 | if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { | |||
1374 | ahd_print_path(ahd, scb); | |||
1375 | printf("data overrun detected %s. Tag == 0x%x.\n", | |||
1376 | ahd_lookup_phase_entry(lastphase)->phasemsg, | |||
1377 | SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag))); | |||
1378 | ahd_print_path(ahd, scb); | |||
1379 | printf("%s seen Data Phase. Length = %d. " | |||
1380 | "NumSGs = %d.\n", | |||
1381 | ahd_inb(ahd, SEQ_FLAGS)(((ahd)->tags[(0x139) >> 8])->read_1(((ahd)->bshs [(0x139) >> 8]), ((0x139) & 0xFF))) & DPHASE0x20 | |||
1382 | ? "Have" : "Haven't", | |||
1383 | aic_get_transfer_length(scb)((scb)->xs->datalen), scb->sg_count); | |||
1384 | ahd_dump_sglist(scb); | |||
1385 | } | |||
1386 | #endif | |||
1387 | ||||
1388 | /* | |||
1389 | * Set this and it will take effect when the | |||
1390 | * target does a command complete. | |||
1391 | */ | |||
1392 | ahd_freeze_devq(ahd, scb); | |||
1393 | aic_set_transaction_status(scb, CAM_DATA_RUN_ERR)(scb)->xs->error = (CAM_DATA_RUN_ERR); | |||
1394 | aic_freeze_scb(scb); | |||
1395 | break; | |||
1396 | } | |||
1397 | case MKMSG_FAILED0x0a: | |||
1398 | { | |||
1399 | struct ahd_devinfo devinfo; | |||
1400 | struct scb *scb; | |||
1401 | u_int scbid; | |||
1402 | ||||
1403 | ahd_fetch_devinfo(ahd, &devinfo); | |||
1404 | printf("%s:%c:%d:%d: Attempt to issue message failed\n", | |||
1405 | ahd_name(ahd), devinfo.channel, devinfo.target, | |||
1406 | devinfo.lun); | |||
1407 | scbid = ahd_get_scbptr(ahd); | |||
1408 | scb = ahd_lookup_scb(ahd, scbid); | |||
1409 | if (scb != NULL((void *)0)) | |||
1410 | /* | |||
1411 | * Ensure that we didn't put a second instance of this | |||
1412 | * SCB into the QINFIFO. | |||
1413 | */ | |||
1414 | ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb)((((scb)->hscb->scsiid) & 0xf0) >> 0x04), | |||
1415 | SCB_GET_CHANNEL(ahd, scb)('A'), | |||
1416 | SCB_GET_LUN(scb)((scb)->hscb->lun), SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)), | |||
1417 | ROLE_INITIATOR, /*status*/0, | |||
1418 | SEARCH_REMOVE); | |||
1419 | ahd_outb(ahd, SCB_CONTROL,(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (ahd_inb_scbram (ahd, 0x192) & ~0x10))) | |||
1420 | ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE)(((ahd)->tags[(0x192) >> 8])->write_1(((ahd)-> bshs[(0x192) >> 8]), ((0x192) & 0xFF), (ahd_inb_scbram (ahd, 0x192) & ~0x10))); | |||
1421 | break; | |||
1422 | } | |||
1423 | case TASKMGMT_FUNC_COMPLETE0x13: | |||
1424 | { | |||
1425 | u_int scbid; | |||
1426 | struct scb *scb; | |||
1427 | ||||
1428 | scbid = ahd_get_scbptr(ahd); | |||
1429 | scb = ahd_lookup_scb(ahd, scbid); | |||
1430 | if (scb != NULL((void *)0)) { | |||
1431 | u_int lun; | |||
1432 | u_int tag; | |||
1433 | cam_status error; | |||
1434 | ||||
1435 | ahd_print_path(ahd, scb); | |||
1436 | printf("Task Management Func 0x%x Complete\n", | |||
1437 | scb->hscb->task_management); | |||
1438 | lun = CAM_LUN_WILDCARD-1; | |||
1439 | tag = SCB_LIST_NULL0xFF00; | |||
1440 | ||||
1441 | switch (scb->hscb->task_management) { | |||
1442 | case SIU_TASKMGMT_ABORT_TASK0x01: | |||
1443 | tag = SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)); | |||
1444 | case SIU_TASKMGMT_ABORT_TASK_SET0x02: | |||
1445 | case SIU_TASKMGMT_CLEAR_TASK_SET0x04: | |||
1446 | lun = scb->hscb->lun; | |||
1447 | error = CAM_REQ_ABORTED; | |||
1448 | ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb)((((scb)->hscb->scsiid) & 0xf0) >> 0x04), | |||
1449 | 'A', lun, tag, ROLE_INITIATOR, | |||
1450 | error); | |||
1451 | break; | |||
1452 | case SIU_TASKMGMT_LUN_RESET0x08: | |||
1453 | lun = scb->hscb->lun; | |||
1454 | case SIU_TASKMGMT_TARGET_RESET0x20: | |||
1455 | { | |||
1456 | struct ahd_devinfo devinfo; | |||
1457 | ||||
1458 | ahd_scb_devinfo(ahd, &devinfo, scb); | |||
1459 | error = CAM_BDR_SENT; | |||
1460 | ahd_handle_devreset(ahd, &devinfo, lun, | |||
1461 | CAM_BDR_SENT, | |||
1462 | lun != CAM_LUN_WILDCARD-1 | |||
1463 | ? "Lun Reset" | |||
1464 | : "Target Reset", | |||
1465 | /*verbose_level*/0); | |||
1466 | break; | |||
1467 | } | |||
1468 | default: | |||
1469 | panic("Unexpected TaskMgmt Func"); | |||
1470 | break; | |||
1471 | } | |||
1472 | } | |||
1473 | break; | |||
1474 | } | |||
1475 | case TASKMGMT_CMD_CMPLT_OKAY0x14: | |||
1476 | { | |||
1477 | u_int scbid; | |||
1478 | struct scb *scb; | |||
1479 | ||||
1480 | /* | |||
1481 | * An ABORT TASK TMF failed to be delivered before | |||
1482 | * the targeted command completed normally. | |||
1483 | */ | |||
1484 | scbid = ahd_get_scbptr(ahd); | |||
1485 | scb = ahd_lookup_scb(ahd, scbid); | |||
1486 | if (scb != NULL((void *)0)) { | |||
1487 | /* | |||
1488 | * Remove the second instance of this SCB from | |||
1489 | * the QINFIFO if it is still there. | |||
1490 | */ | |||
1491 | ahd_print_path(ahd, scb); | |||
1492 | printf("SCB completes before TMF\n"); | |||
1493 | /* | |||
1494 | * Handle losing the race. Wait until any | |||
1495 | * current selection completes. We will then | |||
1496 | * set the TMF back to zero in this SCB so that | |||
1497 | * the sequencer doesn't bother to issue another | |||
1498 | * sequencer interrupt for its completion. | |||
1499 | */ | |||
1500 | while ((ahd_inb(ahd, SCSISEQ0)(((ahd)->tags[(0x3a) >> 8])->read_1(((ahd)->bshs [(0x3a) >> 8]), ((0x3a) & 0xFF))) & ENSELO0x40) != 0 | |||
1501 | && (ahd_inb(ahd, SSTAT0)(((ahd)->tags[(0x4b) >> 8])->read_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF))) & SELDO0x40) == 0 | |||
1502 | && (ahd_inb(ahd, SSTAT1)(((ahd)->tags[(0x4c) >> 8])->read_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF))) & SELTO0x80) == 0) | |||
1503 | ; | |||
1504 | ahd_outb(ahd, SCB_TASK_MANAGEMENT, 0)(((ahd)->tags[(0x197) >> 8])->write_1(((ahd)-> bshs[(0x197) >> 8]), ((0x197) & 0xFF), (0))); | |||
1505 | ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb)((((scb)->hscb->scsiid) & 0xf0) >> 0x04), | |||
1506 | SCB_GET_CHANNEL(ahd, scb)('A'), | |||
1507 | SCB_GET_LUN(scb)((scb)->hscb->lun), SCB_GET_TAG(scb)((__uint16_t)(scb->hscb->tag)), | |||
1508 | ROLE_INITIATOR, /*status*/0, | |||
1509 | SEARCH_REMOVE); | |||
1510 | } | |||
1511 | break; | |||
1512 | } | |||
1513 | case TRACEPOINT00x15: | |||
1514 | case TRACEPOINT10x16: | |||
1515 | case TRACEPOINT20x17: | |||
1516 | case TRACEPOINT30x18: | |||
1517 | printf("%s: Tracepoint %d\n", ahd_name(ahd), | |||
1518 | seqintcode - TRACEPOINT00x15); | |||
1519 | break; | |||
1520 | case NO_SEQINT0x00: | |||
1521 | break; | |||
1522 | case SAW_HWERR0x19: | |||
1523 | ahd_handle_hwerrint(ahd); | |||
1524 | break; | |||
1525 | default: | |||
1526 | printf("%s: Unexpected SEQINTCODE %d\n", ahd_name(ahd), | |||
1527 | seqintcode); | |||
1528 | break; | |||
1529 | } | |||
1530 | /* | |||
1531 | * The sequencer is paused immediately on | |||
1532 | * a SEQINT, so we should restart it when | |||
1533 | * we're done. | |||
1534 | */ | |||
1535 | ahd_unpause(ahd); | |||
1536 | } | |||
1537 | ||||
1538 | void | |||
1539 | ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) | |||
1540 | { | |||
1541 | struct scb *scb; | |||
1542 | u_int status0; | |||
1543 | u_int status3; | |||
1544 | u_int status; | |||
1545 | u_int lqistat1; | |||
1546 | u_int lqostat0; | |||
1547 | u_int scbid; | |||
1548 | u_int busfreetime; | |||
1549 | ||||
1550 | ahd_update_modes(ahd); | |||
1551 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | |||
1552 | ||||
1553 | status3 = ahd_inb(ahd, SSTAT3)(((ahd)->tags[(0x53) >> 8])->read_1(((ahd)->bshs [(0x53) >> 8]), ((0x53) & 0xFF))) & (NTRAMPERR0x02|OSRAMPERR0x01); | |||
1554 | status0 = ahd_inb(ahd, SSTAT0)(((ahd)->tags[(0x4b) >> 8])->read_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF))) & (IOERR0x08|OVERRUN0x04|SELDI0x20|SELDO0x40); | |||
1555 | status = ahd_inb(ahd, SSTAT1)(((ahd)->tags[(0x4c) >> 8])->read_1(((ahd)->bshs [(0x4c) >> 8]), ((0x4c) & 0xFF))) & (SELTO0x80|SCSIRSTI0x20|BUSFREE0x08|SCSIPERR0x04); | |||
1556 | lqistat1 = ahd_inb(ahd, LQISTAT1)(((ahd)->tags[(0x51) >> 8])->read_1(((ahd)->bshs [(0x51) >> 8]), ((0x51) & 0xFF))); | |||
1557 | lqostat0 = ahd_inb(ahd, LQOSTAT0)(((ahd)->tags[(0x54) >> 8])->read_1(((ahd)->bshs [(0x54) >> 8]), ((0x54) & 0xFF))); | |||
1558 | busfreetime = ahd_inb(ahd, SSTAT2)(((ahd)->tags[(0x4d) >> 8])->read_1(((ahd)->bshs [(0x4d) >> 8]), ((0x4d) & 0xFF))) & BUSFREETIME0xc0; | |||
1559 | if ((status0 & (SELDI0x20|SELDO0x40)) != 0) { | |||
1560 | u_int simode0; | |||
1561 | ||||
1562 | ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); | |||
1563 | simode0 = ahd_inb(ahd, SIMODE0)(((ahd)->tags[(0x4b) >> 8])->read_1(((ahd)->bshs [(0x4b) >> 8]), ((0x4b) & 0xFF))); | |||
1564 | status0 &= simode0 & (IOERR0x08|OVERRUN0x04|SELDI0x20|SELDO0x40); | |||
1565 | ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); | |||
1566 | } | |||
1567 | scbid = ahd_get_scbptr(ahd); | |||
1568 | scb = ahd_lookup_scb(ahd, scbid); | |||
1569 | if (scb
| |||
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
[(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
| |||
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), ((((0x6)) > 0x0 && ((0x6)) < 0x9) ? 0x9 : ((0x6)))); } 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(0x6); | |||
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(0x6); | |||
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(0x6); | |||
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(0x6); | |||
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(0x6); | |||
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(0x6); | |||
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(0x6); | |||
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(0x6); | |||
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 | } |