aic7xxx.c revision 1.106 1 1.106 lukem /* $NetBSD: aic7xxx.c,v 1.106 2003/07/14 15:47:06 lukem Exp $ */
2 1.100 fvdl
3 1.1 mycroft /*
4 1.96 fvdl * Core routines and tables shareable across OS platforms.
5 1.1 mycroft *
6 1.96 fvdl * Copyright (c) 1994-2002 Justin T. Gibbs.
7 1.96 fvdl * Copyright (c) 2000-2002 Adaptec Inc.
8 1.6 mycroft * All rights reserved.
9 1.1 mycroft *
10 1.6 mycroft * Redistribution and use in source and binary forms, with or without
11 1.6 mycroft * modification, are permitted provided that the following conditions
12 1.6 mycroft * are met:
13 1.6 mycroft * 1. Redistributions of source code must retain the above copyright
14 1.42 fvdl * notice, this list of conditions, and the following disclaimer,
15 1.42 fvdl * without modification.
16 1.96 fvdl * 2. Redistributions in binary form must reproduce at minimum a disclaimer
17 1.96 fvdl * substantially similar to the "NO WARRANTY" disclaimer below
18 1.96 fvdl * ("Disclaimer") and any redistribution must be conditioned upon
19 1.96 fvdl * including a substantially similar Disclaimer requirement for further
20 1.96 fvdl * binary redistribution.
21 1.96 fvdl * 3. Neither the names of the above-listed copyright holders nor the names
22 1.96 fvdl * of any contributors may be used to endorse or promote products derived
23 1.96 fvdl * from this software without specific prior written permission.
24 1.1 mycroft *
25 1.42 fvdl * Alternatively, this software may be distributed under the terms of the
26 1.96 fvdl * GNU General Public License ("GPL") version 2 as published by the Free
27 1.96 fvdl * Software Foundation.
28 1.42 fvdl *
29 1.96 fvdl * NO WARRANTY
30 1.96 fvdl * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 1.96 fvdl * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 1.96 fvdl * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
33 1.96 fvdl * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34 1.96 fvdl * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 1.6 mycroft * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 1.6 mycroft * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 1.96 fvdl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
38 1.96 fvdl * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
39 1.96 fvdl * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40 1.96 fvdl * POSSIBILITY OF SUCH DAMAGES.
41 1.96 fvdl *
42 1.106 lukem * $Id: aic7xxx.c,v 1.106 2003/07/14 15:47:06 lukem Exp $
43 1.9 explorer *
44 1.96 fvdl * //depot/aic7xxx/aic7xxx/aic7xxx.c#112 $
45 1.96 fvdl *
46 1.96 fvdl * $FreeBSD: /repoman/r/ncvs/src/sys/dev/aic7xxx/aic7xxx.c,v 1.88 2003/01/20 20:44:55 gibbs Exp $
47 1.1 mycroft */
48 1.1 mycroft /*
49 1.96 fvdl * Ported from FreeBSD by Pascal Renauld, Network Storage Solutions, Inc. - April 2003
50 1.1 mycroft */
51 1.106 lukem
52 1.106 lukem #include <sys/cdefs.h>
53 1.106 lukem __KERNEL_RCSID(0, "$NetBSD: aic7xxx.c,v 1.106 2003/07/14 15:47:06 lukem Exp $");
54 1.83 lukem
55 1.96 fvdl #include <dev/ic/aic7xxx_osm.h>
56 1.96 fvdl #include <dev/ic/aic7xxx_inline.h>
57 1.96 fvdl #include <dev/ic/aic7xxx_cam.h>
58 1.1 mycroft
59 1.96 fvdl /****************************** Softc Data ************************************/
60 1.96 fvdl struct ahc_softc_tailq ahc_tailq = TAILQ_HEAD_INITIALIZER(ahc_tailq);
61 1.42 fvdl
62 1.96 fvdl /***************************** Lookup Tables **********************************/
63 1.96 fvdl char *ahc_chip_names[] =
64 1.42 fvdl {
65 1.42 fvdl "NONE",
66 1.42 fvdl "aic7770",
67 1.42 fvdl "aic7850",
68 1.42 fvdl "aic7855",
69 1.42 fvdl "aic7859",
70 1.42 fvdl "aic7860",
71 1.42 fvdl "aic7870",
72 1.42 fvdl "aic7880",
73 1.96 fvdl "aic7895",
74 1.96 fvdl "aic7895C",
75 1.42 fvdl "aic7890/91",
76 1.96 fvdl "aic7896/97",
77 1.42 fvdl "aic7892",
78 1.42 fvdl "aic7899"
79 1.42 fvdl };
80 1.1 mycroft
81 1.96 fvdl /*
82 1.96 fvdl * Hardware error codes.
83 1.96 fvdl */
84 1.96 fvdl struct ahc_hard_error_entry {
85 1.96 fvdl uint8_t errno;
86 1.96 fvdl char *errmesg;
87 1.42 fvdl };
88 1.28 leo
89 1.96 fvdl static struct ahc_hard_error_entry ahc_hard_errors[] = {
90 1.96 fvdl { ILLHADDR, "Illegal Host Access" },
91 1.96 fvdl { ILLSADDR, "Illegal Sequencer Address referrenced" },
92 1.96 fvdl { ILLOPCODE, "Illegal Opcode in sequencer program" },
93 1.96 fvdl { SQPARERR, "Sequencer Parity Error" },
94 1.96 fvdl { DPARERR, "Data-path Parity Error" },
95 1.96 fvdl { MPARERR, "Scratch or SCB Memory Parity Error" },
96 1.96 fvdl { PCIERRSTAT, "PCI Error detected" },
97 1.96 fvdl { CIOPARERR, "CIOBUS Parity Error" },
98 1.96 fvdl };
99 1.96 fvdl static const u_int num_errors = NUM_ELEMENTS(ahc_hard_errors);
100 1.1 mycroft
101 1.96 fvdl static struct ahc_phase_table_entry ahc_phase_table[] =
102 1.42 fvdl {
103 1.96 fvdl { P_DATAOUT, MSG_NOOP, "in Data-out phase" },
104 1.96 fvdl { P_DATAIN, MSG_INITIATOR_DET_ERR, "in Data-in phase" },
105 1.96 fvdl { P_DATAOUT_DT, MSG_NOOP, "in DT Data-out phase" },
106 1.96 fvdl { P_DATAIN_DT, MSG_INITIATOR_DET_ERR, "in DT Data-in phase" },
107 1.96 fvdl { P_COMMAND, MSG_NOOP, "in Command phase" },
108 1.96 fvdl { P_MESGOUT, MSG_NOOP, "in Message-out phase" },
109 1.96 fvdl { P_STATUS, MSG_INITIATOR_DET_ERR, "in Status phase" },
110 1.96 fvdl { P_MESGIN, MSG_PARITY_ERROR, "in Message-in phase" },
111 1.96 fvdl { P_BUSFREE, MSG_NOOP, "while idle" },
112 1.96 fvdl { 0, MSG_NOOP, "in unknown phase" }
113 1.96 fvdl };
114 1.1 mycroft
115 1.1 mycroft /*
116 1.96 fvdl * In most cases we only wish to itterate over real phases, so
117 1.96 fvdl * exclude the last element from the count.
118 1.1 mycroft */
119 1.96 fvdl static const u_int num_phases = NUM_ELEMENTS(ahc_phase_table) - 1;
120 1.1 mycroft
121 1.96 fvdl /*
122 1.96 fvdl * Valid SCSIRATE values. (p. 3-17)
123 1.96 fvdl * Provides a mapping of tranfer periods in ns to the proper value to
124 1.96 fvdl * stick in the scsixfer reg.
125 1.96 fvdl */
126 1.96 fvdl static struct ahc_syncrate ahc_syncrates[] =
127 1.42 fvdl {
128 1.96 fvdl /* ultra2 fast/ultra period rate */
129 1.96 fvdl { 0x42, 0x000, 9, "80.0" },
130 1.96 fvdl { 0x03, 0x000, 10, "40.0" },
131 1.96 fvdl { 0x04, 0x000, 11, "33.0" },
132 1.96 fvdl { 0x05, 0x100, 12, "20.0" },
133 1.96 fvdl { 0x06, 0x110, 15, "16.0" },
134 1.96 fvdl { 0x07, 0x120, 18, "13.4" },
135 1.96 fvdl { 0x08, 0x000, 25, "10.0" },
136 1.96 fvdl { 0x19, 0x010, 31, "8.0" },
137 1.96 fvdl { 0x1a, 0x020, 37, "6.67" },
138 1.96 fvdl { 0x1b, 0x030, 43, "5.7" },
139 1.96 fvdl { 0x1c, 0x040, 50, "5.0" },
140 1.96 fvdl { 0x00, 0x050, 56, "4.4" },
141 1.96 fvdl { 0x00, 0x060, 62, "4.0" },
142 1.96 fvdl { 0x00, 0x070, 68, "3.6" },
143 1.96 fvdl { 0x00, 0x000, 0, NULL }
144 1.96 fvdl };
145 1.1 mycroft
146 1.96 fvdl /* Our Sequencer Program */
147 1.96 fvdl #include <dev/microcode/aic7xxx/aic7xxx_seq.h>
148 1.1 mycroft
149 1.96 fvdl /**************************** Function Declarations ***************************/
150 1.96 fvdl static void ahc_force_renegotiation(struct ahc_softc *ahc);
151 1.96 fvdl static struct ahc_tmode_tstate*
152 1.96 fvdl ahc_alloc_tstate(struct ahc_softc *ahc,
153 1.96 fvdl u_int scsi_id, char channel);
154 1.96 fvdl #ifdef AHC_TARGET_MODE
155 1.96 fvdl static void ahc_free_tstate(struct ahc_softc *ahc,
156 1.96 fvdl u_int scsi_id, char channel, int force);
157 1.96 fvdl #endif
158 1.96 fvdl static struct ahc_syncrate*
159 1.96 fvdl ahc_devlimited_syncrate(struct ahc_softc *ahc,
160 1.96 fvdl struct ahc_initiator_tinfo *,
161 1.96 fvdl u_int *period,
162 1.96 fvdl u_int *ppr_options,
163 1.96 fvdl role_t role);
164 1.96 fvdl static void ahc_update_pending_scbs(struct ahc_softc *ahc);
165 1.96 fvdl static void ahc_fetch_devinfo(struct ahc_softc *ahc,
166 1.96 fvdl struct ahc_devinfo *devinfo);
167 1.96 fvdl static void ahc_scb_devinfo(struct ahc_softc *ahc,
168 1.96 fvdl struct ahc_devinfo *devinfo,
169 1.96 fvdl struct scb *scb);
170 1.96 fvdl static void ahc_assert_atn(struct ahc_softc *ahc);
171 1.96 fvdl static void ahc_setup_initiator_msgout(struct ahc_softc *ahc,
172 1.96 fvdl struct ahc_devinfo *devinfo,
173 1.96 fvdl struct scb *scb);
174 1.96 fvdl static void ahc_build_transfer_msg(struct ahc_softc *ahc,
175 1.96 fvdl struct ahc_devinfo *devinfo);
176 1.96 fvdl static void ahc_construct_sdtr(struct ahc_softc *ahc,
177 1.96 fvdl struct ahc_devinfo *devinfo,
178 1.96 fvdl u_int period, u_int offset);
179 1.96 fvdl static void ahc_construct_wdtr(struct ahc_softc *ahc,
180 1.96 fvdl struct ahc_devinfo *devinfo,
181 1.96 fvdl u_int bus_width);
182 1.96 fvdl static void ahc_construct_ppr(struct ahc_softc *ahc,
183 1.96 fvdl struct ahc_devinfo *devinfo,
184 1.96 fvdl u_int period, u_int offset,
185 1.96 fvdl u_int bus_width, u_int ppr_options);
186 1.96 fvdl static void ahc_clear_msg_state(struct ahc_softc *ahc);
187 1.96 fvdl static void ahc_handle_proto_violation(struct ahc_softc *ahc);
188 1.96 fvdl static void ahc_handle_message_phase(struct ahc_softc *ahc);
189 1.96 fvdl typedef enum {
190 1.96 fvdl AHCMSG_1B,
191 1.96 fvdl AHCMSG_2B,
192 1.96 fvdl AHCMSG_EXT
193 1.96 fvdl } ahc_msgtype;
194 1.96 fvdl static int ahc_sent_msg(struct ahc_softc *ahc, ahc_msgtype type,
195 1.96 fvdl u_int msgval, int full);
196 1.96 fvdl static int ahc_parse_msg(struct ahc_softc *ahc,
197 1.96 fvdl struct ahc_devinfo *devinfo);
198 1.96 fvdl static int ahc_handle_msg_reject(struct ahc_softc *ahc,
199 1.96 fvdl struct ahc_devinfo *devinfo);
200 1.96 fvdl static void ahc_handle_ign_wide_residue(struct ahc_softc *ahc,
201 1.96 fvdl struct ahc_devinfo *devinfo);
202 1.96 fvdl static void ahc_reinitialize_dataptrs(struct ahc_softc *ahc);
203 1.96 fvdl static void ahc_handle_devreset(struct ahc_softc *ahc,
204 1.96 fvdl struct ahc_devinfo *devinfo,
205 1.96 fvdl cam_status status, char *message,
206 1.96 fvdl int verbose_level);
207 1.96 fvdl #if AHC_TARGET_MODE
208 1.96 fvdl static void ahc_setup_target_msgin(struct ahc_softc *ahc,
209 1.96 fvdl struct ahc_devinfo *devinfo,
210 1.96 fvdl struct scb *scb);
211 1.96 fvdl #endif
212 1.96 fvdl
213 1.96 fvdl //static bus_dmamap_callback_t ahc_dmamap_cb;
214 1.96 fvdl static void ahc_build_free_scb_list(struct ahc_softc *ahc);
215 1.96 fvdl static int ahc_init_scbdata(struct ahc_softc *ahc);
216 1.96 fvdl static void ahc_fini_scbdata(struct ahc_softc *ahc);
217 1.96 fvdl static void ahc_qinfifo_requeue(struct ahc_softc *ahc,
218 1.96 fvdl struct scb *prev_scb,
219 1.96 fvdl struct scb *scb);
220 1.96 fvdl static int ahc_qinfifo_count(struct ahc_softc *ahc);
221 1.96 fvdl static u_int ahc_rem_scb_from_disc_list(struct ahc_softc *ahc,
222 1.96 fvdl u_int prev, u_int scbptr);
223 1.96 fvdl static void ahc_add_curscb_to_free_list(struct ahc_softc *ahc);
224 1.96 fvdl static u_int ahc_rem_wscb(struct ahc_softc *ahc,
225 1.96 fvdl u_int scbpos, u_int prev);
226 1.96 fvdl static void ahc_reset_current_bus(struct ahc_softc *ahc);
227 1.96 fvdl #ifdef AHC_DUMP_SEQ
228 1.96 fvdl static void ahc_dumpseq(struct ahc_softc *ahc);
229 1.96 fvdl #endif
230 1.96 fvdl static void ahc_loadseq(struct ahc_softc *ahc);
231 1.96 fvdl static int ahc_check_patch(struct ahc_softc *ahc,
232 1.96 fvdl struct patch **start_patch,
233 1.96 fvdl u_int start_instr, u_int *skip_addr);
234 1.96 fvdl static void ahc_download_instr(struct ahc_softc *ahc,
235 1.96 fvdl u_int instrptr, uint8_t *dconsts);
236 1.96 fvdl #ifdef AHC_TARGET_MODE
237 1.96 fvdl static void ahc_queue_lstate_event(struct ahc_softc *ahc,
238 1.96 fvdl struct ahc_tmode_lstate *lstate,
239 1.96 fvdl u_int initiator_id,
240 1.96 fvdl u_int event_type,
241 1.96 fvdl u_int event_arg);
242 1.96 fvdl static void ahc_update_scsiid(struct ahc_softc *ahc,
243 1.96 fvdl u_int targid_mask);
244 1.96 fvdl static int ahc_handle_target_cmd(struct ahc_softc *ahc,
245 1.96 fvdl struct target_cmd *cmd);
246 1.96 fvdl #endif
247 1.96 fvdl
248 1.96 fvdl /************************** Added for porting to NetBSD ***********************/
249 1.96 fvdl static int ahc_createdmamem(bus_dma_tag_t tag,
250 1.96 fvdl int size,
251 1.96 fvdl int flags,
252 1.96 fvdl bus_dmamap_t *mapp,
253 1.96 fvdl caddr_t *vaddr,
254 1.96 fvdl bus_addr_t *baddr,
255 1.96 fvdl bus_dma_segment_t *seg,
256 1.96 fvdl int *nseg,
257 1.96 fvdl const char *myname, const char *what);
258 1.96 fvdl static void ahc_freedmamem(bus_dma_tag_t tag,
259 1.96 fvdl int size,
260 1.96 fvdl bus_dmamap_t map,
261 1.96 fvdl caddr_t vaddr,
262 1.96 fvdl bus_dma_segment_t *seg,
263 1.96 fvdl int nseg);
264 1.1 mycroft
265 1.96 fvdl /************************* Sequencer Execution Control ************************/
266 1.1 mycroft /*
267 1.42 fvdl * Restart the sequencer program from address zero
268 1.1 mycroft */
269 1.96 fvdl void
270 1.96 fvdl ahc_restart(struct ahc_softc *ahc)
271 1.42 fvdl {
272 1.1 mycroft
273 1.96 fvdl ahc_pause(ahc);
274 1.96 fvdl
275 1.96 fvdl /* No more pending messages. */
276 1.96 fvdl ahc_clear_msg_state(ahc);
277 1.96 fvdl
278 1.96 fvdl ahc_outb(ahc, SCSISIGO, 0); /* De-assert BSY */
279 1.96 fvdl ahc_outb(ahc, MSG_OUT, MSG_NOOP); /* No message to send */
280 1.96 fvdl ahc_outb(ahc, SXFRCTL1, ahc_inb(ahc, SXFRCTL1) & ~BITBUCKET);
281 1.96 fvdl ahc_outb(ahc, LASTPHASE, P_BUSFREE);
282 1.96 fvdl ahc_outb(ahc, SAVED_SCSIID, 0xFF);
283 1.96 fvdl ahc_outb(ahc, SAVED_LUN, 0xFF);
284 1.1 mycroft
285 1.6 mycroft /*
286 1.96 fvdl * Ensure that the sequencer's idea of TQINPOS
287 1.96 fvdl * matches our own. The sequencer increments TQINPOS
288 1.96 fvdl * only after it sees a DMA complete and a reset could
289 1.96 fvdl * occur before the increment leaving the kernel to believe
290 1.96 fvdl * the command arrived but the sequencer to not.
291 1.6 mycroft */
292 1.96 fvdl ahc_outb(ahc, TQINPOS, ahc->tqinfifonext);
293 1.1 mycroft
294 1.96 fvdl /* Always allow reselection */
295 1.96 fvdl ahc_outb(ahc, SCSISEQ,
296 1.96 fvdl ahc_inb(ahc, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP));
297 1.96 fvdl if ((ahc->features & AHC_CMD_CHAN) != 0) {
298 1.96 fvdl /* Ensure that no DMA operations are in progress */
299 1.96 fvdl ahc_outb(ahc, CCSCBCNT, 0);
300 1.96 fvdl ahc_outb(ahc, CCSGCTL, 0);
301 1.96 fvdl ahc_outb(ahc, CCSCBCTL, 0);
302 1.14 gibbs }
303 1.18 thorpej /*
304 1.96 fvdl * If we were in the process of DMA'ing SCB data into
305 1.96 fvdl * an SCB, replace that SCB on the free list. This prevents
306 1.96 fvdl * an SCB leak.
307 1.18 thorpej */
308 1.96 fvdl if ((ahc_inb(ahc, SEQ_FLAGS2) & SCB_DMA) != 0) {
309 1.96 fvdl ahc_add_curscb_to_free_list(ahc);
310 1.96 fvdl ahc_outb(ahc, SEQ_FLAGS2,
311 1.96 fvdl ahc_inb(ahc, SEQ_FLAGS2) & ~SCB_DMA);
312 1.96 fvdl }
313 1.96 fvdl ahc_outb(ahc, MWI_RESIDUAL, 0);
314 1.96 fvdl ahc_outb(ahc, SEQCTL, FASTMODE);
315 1.96 fvdl ahc_outb(ahc, SEQADDR0, 0);
316 1.96 fvdl ahc_outb(ahc, SEQADDR1, 0);
317 1.96 fvdl ahc_unpause(ahc);
318 1.42 fvdl }
319 1.18 thorpej
320 1.96 fvdl /************************* Input/Output Queues ********************************/
321 1.96 fvdl void
322 1.42 fvdl ahc_run_qoutfifo(struct ahc_softc *ahc)
323 1.42 fvdl {
324 1.42 fvdl struct scb *scb;
325 1.42 fvdl u_int scb_index;
326 1.32 thorpej
327 1.96 fvdl ahc_sync_qoutfifo(ahc, BUS_DMASYNC_POSTREAD);
328 1.96 fvdl while (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL) {
329 1.32 thorpej
330 1.42 fvdl scb_index = ahc->qoutfifo[ahc->qoutfifonext];
331 1.96 fvdl if ((ahc->qoutfifonext & 0x03) == 0x03) {
332 1.96 fvdl u_int modnext;
333 1.96 fvdl
334 1.96 fvdl /*
335 1.96 fvdl * Clear 32bits of QOUTFIFO at a time
336 1.96 fvdl * so that we don't clobber an incoming
337 1.96 fvdl * byte DMA to the array on architectures
338 1.96 fvdl * that only support 32bit load and store
339 1.96 fvdl * operations.
340 1.96 fvdl */
341 1.96 fvdl modnext = ahc->qoutfifonext & ~0x3;
342 1.96 fvdl *((uint32_t *)(&ahc->qoutfifo[modnext])) = 0xFFFFFFFFUL;
343 1.96 fvdl ahc_dmamap_sync(ahc, ahc->parent_dmat /*shared_data_dmat*/,
344 1.96 fvdl ahc->shared_data_dmamap,
345 1.96 fvdl /*offset*/modnext, /*len*/4,
346 1.96 fvdl BUS_DMASYNC_PREREAD);
347 1.96 fvdl }
348 1.96 fvdl ahc->qoutfifonext++;
349 1.42 fvdl
350 1.96 fvdl scb = ahc_lookup_scb(ahc, scb_index);
351 1.96 fvdl if (scb == NULL) {
352 1.42 fvdl printf("%s: WARNING no command for scb %d "
353 1.42 fvdl "(cmdcmplt)\nQOUTPOS = %d\n",
354 1.42 fvdl ahc_name(ahc), scb_index,
355 1.96 fvdl (ahc->qoutfifonext - 1) & 0xFF);
356 1.42 fvdl continue;
357 1.42 fvdl }
358 1.6 mycroft
359 1.6 mycroft /*
360 1.42 fvdl * Save off the residual
361 1.42 fvdl * if there is one.
362 1.6 mycroft */
363 1.96 fvdl ahc_update_residual(ahc, scb);
364 1.42 fvdl ahc_done(ahc, scb);
365 1.1 mycroft }
366 1.1 mycroft }
367 1.1 mycroft
368 1.96 fvdl void
369 1.96 fvdl ahc_run_untagged_queues(struct ahc_softc *ahc)
370 1.59 pk {
371 1.96 fvdl int i;
372 1.42 fvdl
373 1.96 fvdl for (i = 0; i < 16; i++)
374 1.96 fvdl ahc_run_untagged_queue(ahc, &ahc->untagged_queues[i]);
375 1.96 fvdl }
376 1.42 fvdl
377 1.96 fvdl void
378 1.96 fvdl ahc_run_untagged_queue(struct ahc_softc *ahc, struct scb_tailq *queue)
379 1.96 fvdl {
380 1.96 fvdl struct scb *scb;
381 1.28 leo
382 1.96 fvdl if (ahc->untagged_queue_lock != 0)
383 1.96 fvdl return;
384 1.6 mycroft
385 1.96 fvdl if ((scb = TAILQ_FIRST(queue)) != NULL
386 1.96 fvdl && (scb->flags & SCB_ACTIVE) == 0) {
387 1.96 fvdl scb->flags |= SCB_ACTIVE;
388 1.96 fvdl ahc_queue_scb(ahc, scb);
389 1.42 fvdl }
390 1.96 fvdl }
391 1.6 mycroft
392 1.96 fvdl /************************* Interrupt Handling *********************************/
393 1.96 fvdl void
394 1.96 fvdl ahc_handle_brkadrint(struct ahc_softc *ahc)
395 1.96 fvdl {
396 1.96 fvdl /*
397 1.96 fvdl * We upset the sequencer :-(
398 1.96 fvdl * Lookup the error message
399 1.96 fvdl */
400 1.96 fvdl int i;
401 1.96 fvdl int error;
402 1.6 mycroft
403 1.96 fvdl error = ahc_inb(ahc, ERROR);
404 1.96 fvdl for (i = 0; error != 1 && i < num_errors; i++)
405 1.96 fvdl error >>= 1;
406 1.96 fvdl printf("%s: brkadrint, %s at seqaddr = 0x%x\n",
407 1.96 fvdl ahc_name(ahc), ahc_hard_errors[i].errmesg,
408 1.96 fvdl ahc_inb(ahc, SEQADDR0) |
409 1.96 fvdl (ahc_inb(ahc, SEQADDR1) << 8));
410 1.96 fvdl
411 1.96 fvdl ahc_dump_card_state(ahc);
412 1.96 fvdl
413 1.96 fvdl /* Tell everyone that this HBA is no longer availible */
414 1.96 fvdl ahc_abort_scbs(ahc, CAM_TARGET_WILDCARD, ALL_CHANNELS,
415 1.96 fvdl CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_UNKNOWN,
416 1.96 fvdl CAM_NO_HBA);
417 1.29 leo
418 1.96 fvdl /* Disable all interrupt sources by resetting the controller */
419 1.96 fvdl ahc_shutdown(ahc);
420 1.6 mycroft }
421 1.6 mycroft
422 1.96 fvdl void
423 1.96 fvdl ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
424 1.42 fvdl {
425 1.96 fvdl struct scb *scb;
426 1.96 fvdl struct ahc_devinfo devinfo;
427 1.96 fvdl
428 1.96 fvdl ahc_fetch_devinfo(ahc, &devinfo);
429 1.96 fvdl
430 1.96 fvdl /*
431 1.96 fvdl * Clear the upper byte that holds SEQINT status
432 1.96 fvdl * codes and clear the SEQINT bit. We will unpause
433 1.96 fvdl * the sequencer, if appropriate, after servicing
434 1.96 fvdl * the request.
435 1.96 fvdl */
436 1.96 fvdl ahc_outb(ahc, CLRINT, CLRSEQINT);
437 1.96 fvdl switch (intstat & SEQINT_MASK) {
438 1.96 fvdl case BAD_STATUS:
439 1.96 fvdl {
440 1.96 fvdl u_int scb_index;
441 1.96 fvdl struct hardware_scb *hscb;
442 1.42 fvdl
443 1.96 fvdl /*
444 1.96 fvdl * Set the default return value to 0 (don't
445 1.96 fvdl * send sense). The sense code will change
446 1.96 fvdl * this if needed.
447 1.96 fvdl */
448 1.96 fvdl ahc_outb(ahc, RETURN_1, 0);
449 1.96 fvdl
450 1.96 fvdl /*
451 1.96 fvdl * The sequencer will notify us when a command
452 1.96 fvdl * has an error that would be of interest to
453 1.96 fvdl * the kernel. This allows us to leave the sequencer
454 1.96 fvdl * running in the common case of command completes
455 1.96 fvdl * without error. The sequencer will already have
456 1.105 wiz * DMA'd the SCB back up to us, so we can reference
457 1.96 fvdl * the in kernel copy directly.
458 1.96 fvdl */
459 1.96 fvdl scb_index = ahc_inb(ahc, SCB_TAG);
460 1.96 fvdl scb = ahc_lookup_scb(ahc, scb_index);
461 1.96 fvdl if (scb == NULL) {
462 1.96 fvdl ahc_print_devinfo(ahc, &devinfo);
463 1.96 fvdl printf("ahc_intr - referenced scb "
464 1.96 fvdl "not valid during seqint 0x%x scb(%d)\n",
465 1.96 fvdl intstat, scb_index);
466 1.96 fvdl ahc_dump_card_state(ahc);
467 1.96 fvdl panic("for safety");
468 1.96 fvdl goto unpause;
469 1.96 fvdl }
470 1.42 fvdl
471 1.96 fvdl hscb = scb->hscb;
472 1.42 fvdl
473 1.96 fvdl /* Don't want to clobber the original sense code */
474 1.96 fvdl if ((scb->flags & SCB_SENSE) != 0) {
475 1.96 fvdl /*
476 1.96 fvdl * Clear the SCB_SENSE Flag and have
477 1.96 fvdl * the sequencer do a normal command
478 1.96 fvdl * complete.
479 1.96 fvdl */
480 1.96 fvdl scb->flags &= ~SCB_SENSE;
481 1.96 fvdl break;
482 1.96 fvdl }
483 1.96 fvdl /* Freeze the queue until the client sees the error. */
484 1.96 fvdl ahc_freeze_devq(ahc, scb);
485 1.96 fvdl ahc_freeze_scb(scb);
486 1.96 fvdl ahc_set_scsi_status(scb, hscb->shared_data.status.scsi_status);
487 1.96 fvdl switch (hscb->shared_data.status.scsi_status) {
488 1.96 fvdl case SCSI_STATUS_OK:
489 1.101 fvdl printf("%s: Interrupted for status of 0 (?)\n",
490 1.96 fvdl ahc_name(ahc));
491 1.96 fvdl break;
492 1.96 fvdl case SCSI_STATUS_CMD_TERMINATED:
493 1.96 fvdl case SCSI_STATUS_CHECK_COND:
494 1.96 fvdl {
495 1.96 fvdl struct ahc_dma_seg *sg;
496 1.96 fvdl struct scsipi_sense *sc;
497 1.96 fvdl struct ahc_initiator_tinfo *targ_info;
498 1.96 fvdl struct ahc_tmode_tstate *tstate;
499 1.96 fvdl struct ahc_transinfo *tinfo;
500 1.42 fvdl #ifdef AHC_DEBUG
501 1.96 fvdl if (ahc_debug & AHC_SHOW_SENSE) {
502 1.96 fvdl ahc_print_path(ahc, scb);
503 1.96 fvdl printf("SCB %d: requests Check Status\n",
504 1.96 fvdl scb->hscb->tag);
505 1.96 fvdl }
506 1.42 fvdl #endif
507 1.42 fvdl
508 1.96 fvdl if (ahc_perform_autosense(scb) == 0)
509 1.96 fvdl break;
510 1.42 fvdl
511 1.96 fvdl targ_info = ahc_fetch_transinfo(ahc,
512 1.96 fvdl devinfo.channel,
513 1.96 fvdl devinfo.our_scsiid,
514 1.96 fvdl devinfo.target,
515 1.96 fvdl &tstate);
516 1.96 fvdl tinfo = &targ_info->curr;
517 1.96 fvdl sg = scb->sg_list;
518 1.96 fvdl sc = (struct scsipi_sense *)(&hscb->shared_data.cdb);
519 1.96 fvdl /*
520 1.96 fvdl * Save off the residual if there is one.
521 1.96 fvdl */
522 1.96 fvdl ahc_update_residual(ahc, scb);
523 1.96 fvdl #ifdef AHC_DEBUG
524 1.96 fvdl if (ahc_debug & AHC_SHOW_SENSE) {
525 1.96 fvdl ahc_print_path(ahc, scb);
526 1.96 fvdl printf("Sending Sense\n");
527 1.96 fvdl }
528 1.96 fvdl #endif
529 1.96 fvdl sg->addr = ahc_get_sense_bufaddr(ahc, scb);
530 1.96 fvdl sg->len = ahc_get_sense_bufsize(ahc, scb);
531 1.96 fvdl sg->len |= AHC_DMA_LAST_SEG;
532 1.96 fvdl
533 1.96 fvdl /* Fixup byte order */
534 1.96 fvdl sg->addr = ahc_htole32(sg->addr);
535 1.96 fvdl sg->len = ahc_htole32(sg->len);
536 1.96 fvdl
537 1.96 fvdl sc->opcode = REQUEST_SENSE;
538 1.96 fvdl sc->byte2 = 0;
539 1.96 fvdl if (tinfo->protocol_version <= SCSI_REV_2
540 1.96 fvdl && SCB_GET_LUN(scb) < 8)
541 1.96 fvdl sc->byte2 = SCB_GET_LUN(scb) << 5;
542 1.96 fvdl sc->unused[0] = 0;
543 1.96 fvdl sc->unused[1] = 0;
544 1.96 fvdl sc->length = sg->len;
545 1.96 fvdl sc->control = 0;
546 1.42 fvdl
547 1.96 fvdl /*
548 1.96 fvdl * We can't allow the target to disconnect.
549 1.96 fvdl * This will be an untagged transaction and
550 1.96 fvdl * having the target disconnect will make this
551 1.96 fvdl * transaction indestinguishable from outstanding
552 1.96 fvdl * tagged transactions.
553 1.96 fvdl */
554 1.96 fvdl hscb->control = 0;
555 1.42 fvdl
556 1.96 fvdl /*
557 1.96 fvdl * This request sense could be because the
558 1.96 fvdl * the device lost power or in some other
559 1.96 fvdl * way has lost our transfer negotiations.
560 1.96 fvdl * Renegotiate if appropriate. Unit attention
561 1.96 fvdl * errors will be reported before any data
562 1.96 fvdl * phases occur.
563 1.96 fvdl */
564 1.96 fvdl if (ahc_get_residual(scb)
565 1.96 fvdl == ahc_get_transfer_length(scb)) {
566 1.96 fvdl ahc_update_neg_request(ahc, &devinfo,
567 1.96 fvdl tstate, targ_info,
568 1.96 fvdl AHC_NEG_IF_NON_ASYNC);
569 1.96 fvdl }
570 1.96 fvdl if (tstate->auto_negotiate & devinfo.target_mask) {
571 1.96 fvdl hscb->control |= MK_MESSAGE;
572 1.96 fvdl scb->flags &= ~SCB_NEGOTIATE;
573 1.96 fvdl scb->flags |= SCB_AUTO_NEGOTIATE;
574 1.96 fvdl }
575 1.96 fvdl hscb->cdb_len = sizeof(*sc);
576 1.96 fvdl hscb->dataptr = sg->addr;
577 1.96 fvdl hscb->datacnt = sg->len;
578 1.96 fvdl hscb->sgptr = scb->sg_list_phys | SG_FULL_RESID;
579 1.96 fvdl hscb->sgptr = ahc_htole32(hscb->sgptr);
580 1.96 fvdl scb->sg_count = 1;
581 1.96 fvdl scb->flags |= SCB_SENSE;
582 1.96 fvdl ahc_qinfifo_requeue_tail(ahc, scb);
583 1.96 fvdl ahc_outb(ahc, RETURN_1, SEND_SENSE);
584 1.96 fvdl /*
585 1.96 fvdl * Ensure we have enough time to actually
586 1.96 fvdl * retrieve the sense.
587 1.96 fvdl */
588 1.96 fvdl ahc_scb_timer_reset(scb, 5 * 1000000);
589 1.96 fvdl break;
590 1.96 fvdl }
591 1.96 fvdl default:
592 1.96 fvdl break;
593 1.96 fvdl }
594 1.96 fvdl break;
595 1.96 fvdl }
596 1.96 fvdl case NO_MATCH:
597 1.96 fvdl {
598 1.96 fvdl /* Ensure we don't leave the selection hardware on */
599 1.96 fvdl ahc_outb(ahc, SCSISEQ,
600 1.96 fvdl ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP));
601 1.96 fvdl
602 1.96 fvdl printf("%s:%c:%d: no active SCB for reconnecting "
603 1.96 fvdl "target - issuing BUS DEVICE RESET\n",
604 1.96 fvdl ahc_name(ahc), devinfo.channel, devinfo.target);
605 1.96 fvdl printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, "
606 1.96 fvdl "ARG_1 == 0x%x ACCUM = 0x%x\n",
607 1.96 fvdl ahc_inb(ahc, SAVED_SCSIID), ahc_inb(ahc, SAVED_LUN),
608 1.96 fvdl ahc_inb(ahc, ARG_1), ahc_inb(ahc, ACCUM));
609 1.96 fvdl printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, "
610 1.96 fvdl "SINDEX == 0x%x\n",
611 1.96 fvdl ahc_inb(ahc, SEQ_FLAGS), ahc_inb(ahc, SCBPTR),
612 1.96 fvdl ahc_index_busy_tcl(ahc,
613 1.96 fvdl BUILD_TCL(ahc_inb(ahc, SAVED_SCSIID),
614 1.96 fvdl ahc_inb(ahc, SAVED_LUN))),
615 1.96 fvdl ahc_inb(ahc, SINDEX));
616 1.96 fvdl printf("SCSIID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, "
617 1.96 fvdl "SCB_TAG == 0x%x, SCB_CONTROL == 0x%x\n",
618 1.96 fvdl ahc_inb(ahc, SCSIID), ahc_inb(ahc, SCB_SCSIID),
619 1.96 fvdl ahc_inb(ahc, SCB_LUN), ahc_inb(ahc, SCB_TAG),
620 1.96 fvdl ahc_inb(ahc, SCB_CONTROL));
621 1.96 fvdl printf("SCSIBUSL == 0x%x, SCSISIGI == 0x%x\n",
622 1.96 fvdl ahc_inb(ahc, SCSIBUSL), ahc_inb(ahc, SCSISIGI));
623 1.96 fvdl printf("SXFRCTL0 == 0x%x\n", ahc_inb(ahc, SXFRCTL0));
624 1.96 fvdl printf("SEQCTL == 0x%x\n", ahc_inb(ahc, SEQCTL));
625 1.96 fvdl ahc_dump_card_state(ahc);
626 1.96 fvdl ahc->msgout_buf[0] = MSG_BUS_DEV_RESET;
627 1.96 fvdl ahc->msgout_len = 1;
628 1.96 fvdl ahc->msgout_index = 0;
629 1.96 fvdl ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
630 1.96 fvdl ahc_outb(ahc, MSG_OUT, HOST_MSG);
631 1.96 fvdl ahc_assert_atn(ahc);
632 1.96 fvdl break;
633 1.96 fvdl }
634 1.96 fvdl case SEND_REJECT:
635 1.96 fvdl {
636 1.96 fvdl u_int rejbyte = ahc_inb(ahc, ACCUM);
637 1.96 fvdl printf("%s:%c:%d: Warning - unknown message received from "
638 1.96 fvdl "target (0x%x). Rejecting\n",
639 1.96 fvdl ahc_name(ahc), devinfo.channel, devinfo.target, rejbyte);
640 1.96 fvdl break;
641 1.96 fvdl }
642 1.96 fvdl case PROTO_VIOLATION:
643 1.96 fvdl {
644 1.96 fvdl ahc_handle_proto_violation(ahc);
645 1.96 fvdl break;
646 1.96 fvdl }
647 1.96 fvdl case IGN_WIDE_RES:
648 1.96 fvdl ahc_handle_ign_wide_residue(ahc, &devinfo);
649 1.96 fvdl break;
650 1.96 fvdl case PDATA_REINIT:
651 1.96 fvdl ahc_reinitialize_dataptrs(ahc);
652 1.96 fvdl break;
653 1.96 fvdl case BAD_PHASE:
654 1.96 fvdl {
655 1.96 fvdl u_int lastphase;
656 1.96 fvdl
657 1.96 fvdl lastphase = ahc_inb(ahc, LASTPHASE);
658 1.96 fvdl printf("%s:%c:%d: unknown scsi bus phase %x, "
659 1.96 fvdl "lastphase = 0x%x. Attempting to continue\n",
660 1.96 fvdl ahc_name(ahc), devinfo.channel, devinfo.target,
661 1.96 fvdl lastphase, ahc_inb(ahc, SCSISIGI));
662 1.96 fvdl break;
663 1.96 fvdl }
664 1.96 fvdl case MISSED_BUSFREE:
665 1.96 fvdl {
666 1.96 fvdl u_int lastphase;
667 1.96 fvdl
668 1.96 fvdl lastphase = ahc_inb(ahc, LASTPHASE);
669 1.96 fvdl printf("%s:%c:%d: Missed busfree. "
670 1.96 fvdl "Lastphase = 0x%x, Curphase = 0x%x\n",
671 1.96 fvdl ahc_name(ahc), devinfo.channel, devinfo.target,
672 1.96 fvdl lastphase, ahc_inb(ahc, SCSISIGI));
673 1.96 fvdl ahc_restart(ahc);
674 1.96 fvdl return;
675 1.96 fvdl }
676 1.96 fvdl case HOST_MSG_LOOP:
677 1.96 fvdl {
678 1.96 fvdl /*
679 1.96 fvdl * The sequencer has encountered a message phase
680 1.96 fvdl * that requires host assistance for completion.
681 1.96 fvdl * While handling the message phase(s), we will be
682 1.96 fvdl * notified by the sequencer after each byte is
683 1.96 fvdl * transfered so we can track bus phase changes.
684 1.96 fvdl *
685 1.96 fvdl * If this is the first time we've seen a HOST_MSG_LOOP
686 1.96 fvdl * interrupt, initialize the state of the host message
687 1.96 fvdl * loop.
688 1.96 fvdl */
689 1.96 fvdl if (ahc->msg_type == MSG_TYPE_NONE) {
690 1.96 fvdl struct scb *scb;
691 1.96 fvdl u_int scb_index;
692 1.96 fvdl u_int bus_phase;
693 1.96 fvdl
694 1.96 fvdl bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;
695 1.96 fvdl if (bus_phase != P_MESGIN
696 1.96 fvdl && bus_phase != P_MESGOUT) {
697 1.96 fvdl printf("ahc_intr: HOST_MSG_LOOP bad "
698 1.96 fvdl "phase 0x%x\n",
699 1.96 fvdl bus_phase);
700 1.96 fvdl /*
701 1.96 fvdl * Probably transitioned to bus free before
702 1.96 fvdl * we got here. Just punt the message.
703 1.96 fvdl */
704 1.96 fvdl ahc_clear_intstat(ahc);
705 1.96 fvdl ahc_restart(ahc);
706 1.96 fvdl return;
707 1.96 fvdl }
708 1.96 fvdl
709 1.96 fvdl scb_index = ahc_inb(ahc, SCB_TAG);
710 1.96 fvdl scb = ahc_lookup_scb(ahc, scb_index);
711 1.96 fvdl if (devinfo.role == ROLE_INITIATOR) {
712 1.96 fvdl if (scb == NULL)
713 1.96 fvdl panic("HOST_MSG_LOOP with "
714 1.96 fvdl "invalid SCB %x\n", scb_index);
715 1.96 fvdl
716 1.96 fvdl if (bus_phase == P_MESGOUT)
717 1.96 fvdl ahc_setup_initiator_msgout(ahc,
718 1.96 fvdl &devinfo,
719 1.96 fvdl scb);
720 1.96 fvdl else {
721 1.96 fvdl ahc->msg_type =
722 1.96 fvdl MSG_TYPE_INITIATOR_MSGIN;
723 1.96 fvdl ahc->msgin_index = 0;
724 1.96 fvdl }
725 1.96 fvdl }
726 1.96 fvdl #if AHC_TARGET_MODE
727 1.96 fvdl else {
728 1.96 fvdl if (bus_phase == P_MESGOUT) {
729 1.96 fvdl ahc->msg_type =
730 1.96 fvdl MSG_TYPE_TARGET_MSGOUT;
731 1.96 fvdl ahc->msgin_index = 0;
732 1.96 fvdl }
733 1.96 fvdl else
734 1.96 fvdl ahc_setup_target_msgin(ahc,
735 1.96 fvdl &devinfo,
736 1.96 fvdl scb);
737 1.96 fvdl }
738 1.96 fvdl #endif
739 1.96 fvdl }
740 1.96 fvdl
741 1.96 fvdl ahc_handle_message_phase(ahc);
742 1.96 fvdl break;
743 1.96 fvdl }
744 1.96 fvdl case PERR_DETECTED:
745 1.96 fvdl {
746 1.96 fvdl /*
747 1.96 fvdl * If we've cleared the parity error interrupt
748 1.96 fvdl * but the sequencer still believes that SCSIPERR
749 1.96 fvdl * is true, it must be that the parity error is
750 1.96 fvdl * for the currently presented byte on the bus,
751 1.96 fvdl * and we are not in a phase (data-in) where we will
752 1.96 fvdl * eventually ack this byte. Ack the byte and
753 1.96 fvdl * throw it away in the hope that the target will
754 1.96 fvdl * take us to message out to deliver the appropriate
755 1.96 fvdl * error message.
756 1.96 fvdl */
757 1.96 fvdl if ((intstat & SCSIINT) == 0
758 1.96 fvdl && (ahc_inb(ahc, SSTAT1) & SCSIPERR) != 0) {
759 1.96 fvdl
760 1.96 fvdl if ((ahc->features & AHC_DT) == 0) {
761 1.96 fvdl u_int curphase;
762 1.96 fvdl
763 1.96 fvdl /*
764 1.96 fvdl * The hardware will only let you ack bytes
765 1.96 fvdl * if the expected phase in SCSISIGO matches
766 1.96 fvdl * the current phase. Make sure this is
767 1.96 fvdl * currently the case.
768 1.96 fvdl */
769 1.96 fvdl curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;
770 1.96 fvdl ahc_outb(ahc, LASTPHASE, curphase);
771 1.96 fvdl ahc_outb(ahc, SCSISIGO, curphase);
772 1.96 fvdl }
773 1.96 fvdl if ((ahc_inb(ahc, SCSISIGI) & (CDI|MSGI)) == 0) {
774 1.96 fvdl int wait;
775 1.96 fvdl
776 1.96 fvdl /*
777 1.96 fvdl * In a data phase. Faster to bitbucket
778 1.96 fvdl * the data than to individually ack each
779 1.96 fvdl * byte. This is also the only strategy
780 1.96 fvdl * that will work with AUTOACK enabled.
781 1.96 fvdl */
782 1.96 fvdl ahc_outb(ahc, SXFRCTL1,
783 1.96 fvdl ahc_inb(ahc, SXFRCTL1) | BITBUCKET);
784 1.96 fvdl wait = 5000;
785 1.96 fvdl while (--wait != 0) {
786 1.96 fvdl if ((ahc_inb(ahc, SCSISIGI)
787 1.96 fvdl & (CDI|MSGI)) != 0)
788 1.96 fvdl break;
789 1.96 fvdl ahc_delay(100);
790 1.96 fvdl }
791 1.96 fvdl ahc_outb(ahc, SXFRCTL1,
792 1.96 fvdl ahc_inb(ahc, SXFRCTL1) & ~BITBUCKET);
793 1.96 fvdl if (wait == 0) {
794 1.96 fvdl struct scb *scb;
795 1.96 fvdl u_int scb_index;
796 1.96 fvdl
797 1.96 fvdl ahc_print_devinfo(ahc, &devinfo);
798 1.96 fvdl printf("Unable to clear parity error. "
799 1.96 fvdl "Resetting bus.\n");
800 1.96 fvdl scb_index = ahc_inb(ahc, SCB_TAG);
801 1.96 fvdl scb = ahc_lookup_scb(ahc, scb_index);
802 1.96 fvdl if (scb != NULL)
803 1.96 fvdl ahc_set_transaction_status(scb,
804 1.96 fvdl CAM_UNCOR_PARITY);
805 1.96 fvdl ahc_reset_channel(ahc, devinfo.channel,
806 1.96 fvdl /*init reset*/TRUE);
807 1.96 fvdl }
808 1.96 fvdl } else {
809 1.96 fvdl ahc_inb(ahc, SCSIDATL);
810 1.96 fvdl }
811 1.96 fvdl }
812 1.96 fvdl break;
813 1.96 fvdl }
814 1.96 fvdl case DATA_OVERRUN:
815 1.96 fvdl {
816 1.96 fvdl /*
817 1.96 fvdl * When the sequencer detects an overrun, it
818 1.96 fvdl * places the controller in "BITBUCKET" mode
819 1.96 fvdl * and allows the target to complete its transfer.
820 1.96 fvdl * Unfortunately, none of the counters get updated
821 1.96 fvdl * when the controller is in this mode, so we have
822 1.96 fvdl * no way of knowing how large the overrun was.
823 1.96 fvdl */
824 1.96 fvdl u_int scbindex = ahc_inb(ahc, SCB_TAG);
825 1.96 fvdl u_int lastphase = ahc_inb(ahc, LASTPHASE);
826 1.96 fvdl u_int i;
827 1.96 fvdl
828 1.96 fvdl scb = ahc_lookup_scb(ahc, scbindex);
829 1.96 fvdl for (i = 0; i < num_phases; i++) {
830 1.96 fvdl if (lastphase == ahc_phase_table[i].phase)
831 1.96 fvdl break;
832 1.96 fvdl }
833 1.96 fvdl ahc_print_path(ahc, scb);
834 1.96 fvdl printf("data overrun detected %s."
835 1.96 fvdl " Tag == 0x%x.\n",
836 1.96 fvdl ahc_phase_table[i].phasemsg,
837 1.96 fvdl scb->hscb->tag);
838 1.96 fvdl ahc_print_path(ahc, scb);
839 1.96 fvdl printf("%s seen Data Phase. Length = %ld. NumSGs = %d.\n",
840 1.96 fvdl ahc_inb(ahc, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't",
841 1.96 fvdl ahc_get_transfer_length(scb), scb->sg_count);
842 1.96 fvdl if (scb->sg_count > 0) {
843 1.96 fvdl for (i = 0; i < scb->sg_count; i++) {
844 1.96 fvdl
845 1.96 fvdl printf("sg[%d] - Addr 0x%x%x : Length %d\n",
846 1.96 fvdl i,
847 1.96 fvdl (ahc_le32toh(scb->sg_list[i].len) >> 24
848 1.96 fvdl & SG_HIGH_ADDR_BITS),
849 1.96 fvdl ahc_le32toh(scb->sg_list[i].addr),
850 1.96 fvdl ahc_le32toh(scb->sg_list[i].len)
851 1.96 fvdl & AHC_SG_LEN_MASK);
852 1.96 fvdl }
853 1.96 fvdl }
854 1.96 fvdl /*
855 1.96 fvdl * Set this and it will take effect when the
856 1.96 fvdl * target does a command complete.
857 1.96 fvdl */
858 1.96 fvdl ahc_freeze_devq(ahc, scb);
859 1.96 fvdl if ((scb->flags & SCB_SENSE) == 0) {
860 1.96 fvdl ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR);
861 1.96 fvdl } else {
862 1.96 fvdl scb->flags &= ~SCB_SENSE;
863 1.96 fvdl ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
864 1.96 fvdl }
865 1.96 fvdl ahc_freeze_scb(scb);
866 1.96 fvdl
867 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0) {
868 1.96 fvdl /*
869 1.96 fvdl * Clear the channel in case we return
870 1.96 fvdl * to data phase later.
871 1.96 fvdl */
872 1.96 fvdl ahc_outb(ahc, SXFRCTL0,
873 1.96 fvdl ahc_inb(ahc, SXFRCTL0) | CLRSTCNT|CLRCHN);
874 1.96 fvdl ahc_outb(ahc, SXFRCTL0,
875 1.96 fvdl ahc_inb(ahc, SXFRCTL0) | CLRSTCNT|CLRCHN);
876 1.96 fvdl }
877 1.96 fvdl if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
878 1.96 fvdl u_int dscommand1;
879 1.96 fvdl
880 1.96 fvdl /* Ensure HHADDR is 0 for future DMA operations. */
881 1.96 fvdl dscommand1 = ahc_inb(ahc, DSCOMMAND1);
882 1.96 fvdl ahc_outb(ahc, DSCOMMAND1, dscommand1 | HADDLDSEL0);
883 1.96 fvdl ahc_outb(ahc, HADDR, 0);
884 1.96 fvdl ahc_outb(ahc, DSCOMMAND1, dscommand1);
885 1.96 fvdl }
886 1.96 fvdl break;
887 1.96 fvdl }
888 1.96 fvdl case MKMSG_FAILED:
889 1.96 fvdl {
890 1.96 fvdl u_int scbindex;
891 1.96 fvdl
892 1.96 fvdl printf("%s:%c:%d:%d: Attempt to issue message failed\n",
893 1.96 fvdl ahc_name(ahc), devinfo.channel, devinfo.target,
894 1.96 fvdl devinfo.lun);
895 1.96 fvdl scbindex = ahc_inb(ahc, SCB_TAG);
896 1.96 fvdl scb = ahc_lookup_scb(ahc, scbindex);
897 1.96 fvdl if (scb != NULL
898 1.96 fvdl && (scb->flags & SCB_RECOVERY_SCB) != 0)
899 1.96 fvdl /*
900 1.96 fvdl * Ensure that we didn't put a second instance of this
901 1.96 fvdl * SCB into the QINFIFO.
902 1.96 fvdl */
903 1.96 fvdl ahc_search_qinfifo(ahc, SCB_GET_TARGET(ahc, scb),
904 1.96 fvdl SCB_GET_CHANNEL(ahc, scb),
905 1.96 fvdl SCB_GET_LUN(scb), scb->hscb->tag,
906 1.96 fvdl ROLE_INITIATOR, /*status*/0,
907 1.96 fvdl SEARCH_REMOVE);
908 1.96 fvdl break;
909 1.96 fvdl }
910 1.96 fvdl case NO_FREE_SCB:
911 1.96 fvdl {
912 1.96 fvdl printf("%s: No free or disconnected SCBs\n", ahc_name(ahc));
913 1.96 fvdl ahc_dump_card_state(ahc);
914 1.96 fvdl panic("for safety");
915 1.96 fvdl break;
916 1.96 fvdl }
917 1.96 fvdl case SCB_MISMATCH:
918 1.96 fvdl {
919 1.96 fvdl u_int scbptr;
920 1.96 fvdl
921 1.96 fvdl scbptr = ahc_inb(ahc, SCBPTR);
922 1.96 fvdl printf("Bogus TAG after DMA. SCBPTR %d, tag %d, our tag %d\n",
923 1.96 fvdl scbptr, ahc_inb(ahc, ARG_1),
924 1.96 fvdl ahc->scb_data->hscbs[scbptr].tag);
925 1.96 fvdl ahc_dump_card_state(ahc);
926 1.96 fvdl panic("for saftey");
927 1.96 fvdl break;
928 1.96 fvdl }
929 1.96 fvdl case OUT_OF_RANGE:
930 1.96 fvdl {
931 1.96 fvdl printf("%s: BTT calculation out of range\n", ahc_name(ahc));
932 1.96 fvdl printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, "
933 1.96 fvdl "ARG_1 == 0x%x ACCUM = 0x%x\n",
934 1.96 fvdl ahc_inb(ahc, SAVED_SCSIID), ahc_inb(ahc, SAVED_LUN),
935 1.96 fvdl ahc_inb(ahc, ARG_1), ahc_inb(ahc, ACCUM));
936 1.96 fvdl printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, "
937 1.96 fvdl "SINDEX == 0x%x\n, A == 0x%x\n",
938 1.96 fvdl ahc_inb(ahc, SEQ_FLAGS), ahc_inb(ahc, SCBPTR),
939 1.96 fvdl ahc_index_busy_tcl(ahc,
940 1.96 fvdl BUILD_TCL(ahc_inb(ahc, SAVED_SCSIID),
941 1.96 fvdl ahc_inb(ahc, SAVED_LUN))),
942 1.96 fvdl ahc_inb(ahc, SINDEX),
943 1.96 fvdl ahc_inb(ahc, ACCUM));
944 1.96 fvdl printf("SCSIID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, "
945 1.96 fvdl "SCB_TAG == 0x%x, SCB_CONTROL == 0x%x\n",
946 1.96 fvdl ahc_inb(ahc, SCSIID), ahc_inb(ahc, SCB_SCSIID),
947 1.96 fvdl ahc_inb(ahc, SCB_LUN), ahc_inb(ahc, SCB_TAG),
948 1.96 fvdl ahc_inb(ahc, SCB_CONTROL));
949 1.96 fvdl printf("SCSIBUSL == 0x%x, SCSISIGI == 0x%x\n",
950 1.96 fvdl ahc_inb(ahc, SCSIBUSL), ahc_inb(ahc, SCSISIGI));
951 1.96 fvdl ahc_dump_card_state(ahc);
952 1.96 fvdl panic("for safety");
953 1.96 fvdl break;
954 1.96 fvdl }
955 1.96 fvdl default:
956 1.96 fvdl printf("ahc_intr: seqint, "
957 1.96 fvdl "intstat == 0x%x, scsisigi = 0x%x\n",
958 1.96 fvdl intstat, ahc_inb(ahc, SCSISIGI));
959 1.96 fvdl break;
960 1.96 fvdl }
961 1.96 fvdl unpause:
962 1.96 fvdl /*
963 1.96 fvdl * The sequencer is paused immediately on
964 1.96 fvdl * a SEQINT, so we should restart it when
965 1.96 fvdl * we're done.
966 1.96 fvdl */
967 1.96 fvdl ahc_unpause(ahc);
968 1.96 fvdl }
969 1.96 fvdl
970 1.96 fvdl void
971 1.96 fvdl ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
972 1.96 fvdl {
973 1.96 fvdl u_int scb_index;
974 1.96 fvdl u_int status0;
975 1.96 fvdl u_int status;
976 1.96 fvdl struct scb *scb;
977 1.96 fvdl char cur_channel;
978 1.96 fvdl char intr_channel;
979 1.96 fvdl
980 1.96 fvdl if ((ahc->features & AHC_TWIN) != 0
981 1.96 fvdl && ((ahc_inb(ahc, SBLKCTL) & SELBUSB) != 0))
982 1.96 fvdl cur_channel = 'B';
983 1.96 fvdl else
984 1.96 fvdl cur_channel = 'A';
985 1.96 fvdl intr_channel = cur_channel;
986 1.96 fvdl
987 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0)
988 1.96 fvdl status0 = ahc_inb(ahc, SSTAT0) & IOERR;
989 1.96 fvdl else
990 1.96 fvdl status0 = 0;
991 1.96 fvdl status = ahc_inb(ahc, SSTAT1) & (SELTO|SCSIRSTI|BUSFREE|SCSIPERR);
992 1.96 fvdl if (status == 0 && status0 == 0) {
993 1.96 fvdl if ((ahc->features & AHC_TWIN) != 0) {
994 1.96 fvdl /* Try the other channel */
995 1.96 fvdl ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) ^ SELBUSB);
996 1.96 fvdl status = ahc_inb(ahc, SSTAT1)
997 1.96 fvdl & (SELTO|SCSIRSTI|BUSFREE|SCSIPERR);
998 1.96 fvdl intr_channel = (cur_channel == 'A') ? 'B' : 'A';
999 1.96 fvdl }
1000 1.96 fvdl if (status == 0) {
1001 1.96 fvdl printf("%s: Spurious SCSI interrupt\n", ahc_name(ahc));
1002 1.96 fvdl ahc_outb(ahc, CLRINT, CLRSCSIINT);
1003 1.96 fvdl ahc_unpause(ahc);
1004 1.96 fvdl return;
1005 1.96 fvdl }
1006 1.96 fvdl }
1007 1.96 fvdl
1008 1.96 fvdl /* Make sure the sequencer is in a safe location. */
1009 1.96 fvdl ahc_clear_critical_section(ahc);
1010 1.96 fvdl
1011 1.96 fvdl scb_index = ahc_inb(ahc, SCB_TAG);
1012 1.96 fvdl scb = ahc_lookup_scb(ahc, scb_index);
1013 1.96 fvdl if (scb != NULL
1014 1.96 fvdl && (ahc_inb(ahc, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)
1015 1.96 fvdl scb = NULL;
1016 1.96 fvdl
1017 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0
1018 1.96 fvdl && (status0 & IOERR) != 0) {
1019 1.96 fvdl int now_lvd;
1020 1.96 fvdl
1021 1.96 fvdl now_lvd = ahc_inb(ahc, SBLKCTL) & ENAB40;
1022 1.96 fvdl printf("%s: Transceiver State Has Changed to %s mode\n",
1023 1.96 fvdl ahc_name(ahc), now_lvd ? "LVD" : "SE");
1024 1.96 fvdl ahc_outb(ahc, CLRSINT0, CLRIOERR);
1025 1.96 fvdl /*
1026 1.96 fvdl * When transitioning to SE mode, the reset line
1027 1.96 fvdl * glitches, triggering an arbitration bug in some
1028 1.96 fvdl * Ultra2 controllers. This bug is cleared when we
1029 1.96 fvdl * assert the reset line. Since a reset glitch has
1030 1.96 fvdl * already occurred with this transition and a
1031 1.96 fvdl * transceiver state change is handled just like
1032 1.96 fvdl * a bus reset anyway, asserting the reset line
1033 1.96 fvdl * ourselves is safe.
1034 1.96 fvdl */
1035 1.96 fvdl ahc_reset_channel(ahc, intr_channel,
1036 1.96 fvdl /*Initiate Reset*/now_lvd == 0);
1037 1.96 fvdl } else if ((status & SCSIRSTI) != 0) {
1038 1.96 fvdl printf("%s: Someone reset channel %c\n",
1039 1.96 fvdl ahc_name(ahc), intr_channel);
1040 1.96 fvdl if (intr_channel != cur_channel)
1041 1.96 fvdl ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) ^ SELBUSB);
1042 1.96 fvdl ahc_reset_channel(ahc, intr_channel, /*Initiate Reset*/FALSE);
1043 1.96 fvdl } else if ((status & SCSIPERR) != 0) {
1044 1.96 fvdl /*
1045 1.96 fvdl * Determine the bus phase and queue an appropriate message.
1046 1.96 fvdl * SCSIPERR is latched true as soon as a parity error
1047 1.96 fvdl * occurs. If the sequencer acked the transfer that
1048 1.96 fvdl * caused the parity error and the currently presented
1049 1.96 fvdl * transfer on the bus has correct parity, SCSIPERR will
1050 1.96 fvdl * be cleared by CLRSCSIPERR. Use this to determine if
1051 1.96 fvdl * we should look at the last phase the sequencer recorded,
1052 1.96 fvdl * or the current phase presented on the bus.
1053 1.96 fvdl */
1054 1.96 fvdl u_int mesg_out;
1055 1.96 fvdl u_int curphase;
1056 1.96 fvdl u_int errorphase;
1057 1.96 fvdl u_int lastphase;
1058 1.96 fvdl u_int scsirate;
1059 1.96 fvdl u_int i;
1060 1.96 fvdl u_int sstat2;
1061 1.96 fvdl int silent;
1062 1.96 fvdl
1063 1.96 fvdl lastphase = ahc_inb(ahc, LASTPHASE);
1064 1.96 fvdl curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;
1065 1.96 fvdl sstat2 = ahc_inb(ahc, SSTAT2);
1066 1.96 fvdl ahc_outb(ahc, CLRSINT1, CLRSCSIPERR);
1067 1.96 fvdl /*
1068 1.96 fvdl * For all phases save DATA, the sequencer won't
1069 1.96 fvdl * automatically ack a byte that has a parity error
1070 1.96 fvdl * in it. So the only way that the current phase
1071 1.96 fvdl * could be 'data-in' is if the parity error is for
1072 1.96 fvdl * an already acked byte in the data phase. During
1073 1.96 fvdl * synchronous data-in transfers, we may actually
1074 1.96 fvdl * ack bytes before latching the current phase in
1075 1.96 fvdl * LASTPHASE, leading to the discrepancy between
1076 1.96 fvdl * curphase and lastphase.
1077 1.96 fvdl */
1078 1.96 fvdl if ((ahc_inb(ahc, SSTAT1) & SCSIPERR) != 0
1079 1.96 fvdl || curphase == P_DATAIN || curphase == P_DATAIN_DT)
1080 1.96 fvdl errorphase = curphase;
1081 1.96 fvdl else
1082 1.96 fvdl errorphase = lastphase;
1083 1.96 fvdl
1084 1.96 fvdl for (i = 0; i < num_phases; i++) {
1085 1.96 fvdl if (errorphase == ahc_phase_table[i].phase)
1086 1.96 fvdl break;
1087 1.96 fvdl }
1088 1.96 fvdl mesg_out = ahc_phase_table[i].mesg_out;
1089 1.96 fvdl silent = FALSE;
1090 1.96 fvdl if (scb != NULL) {
1091 1.96 fvdl if (SCB_IS_SILENT(scb))
1092 1.96 fvdl silent = TRUE;
1093 1.96 fvdl else
1094 1.96 fvdl ahc_print_path(ahc, scb);
1095 1.96 fvdl scb->flags |= SCB_TRANSMISSION_ERROR;
1096 1.96 fvdl } else
1097 1.96 fvdl printf("%s:%c:%d: ", ahc_name(ahc), intr_channel,
1098 1.96 fvdl SCSIID_TARGET(ahc, ahc_inb(ahc, SAVED_SCSIID)));
1099 1.96 fvdl scsirate = ahc_inb(ahc, SCSIRATE);
1100 1.96 fvdl if (silent == FALSE) {
1101 1.96 fvdl printf("parity error detected %s. "
1102 1.96 fvdl "SEQADDR(0x%x) SCSIRATE(0x%x)\n",
1103 1.96 fvdl ahc_phase_table[i].phasemsg,
1104 1.96 fvdl ahc_inw(ahc, SEQADDR0),
1105 1.96 fvdl scsirate);
1106 1.96 fvdl if ((ahc->features & AHC_DT) != 0) {
1107 1.96 fvdl if ((sstat2 & CRCVALERR) != 0)
1108 1.96 fvdl printf("\tCRC Value Mismatch\n");
1109 1.96 fvdl if ((sstat2 & CRCENDERR) != 0)
1110 1.96 fvdl printf("\tNo terminal CRC packet "
1111 1.96 fvdl "recevied\n");
1112 1.96 fvdl if ((sstat2 & CRCREQERR) != 0)
1113 1.96 fvdl printf("\tIllegal CRC packet "
1114 1.96 fvdl "request\n");
1115 1.96 fvdl if ((sstat2 & DUAL_EDGE_ERR) != 0)
1116 1.96 fvdl printf("\tUnexpected %sDT Data Phase\n",
1117 1.96 fvdl (scsirate & SINGLE_EDGE)
1118 1.96 fvdl ? "" : "non-");
1119 1.96 fvdl }
1120 1.96 fvdl }
1121 1.96 fvdl
1122 1.96 fvdl if ((ahc->features & AHC_DT) != 0
1123 1.96 fvdl && (sstat2 & DUAL_EDGE_ERR) != 0) {
1124 1.96 fvdl /*
1125 1.96 fvdl * This error applies regardless of
1126 1.96 fvdl * data direction, so ignore the value
1127 1.96 fvdl * in the phase table.
1128 1.96 fvdl */
1129 1.96 fvdl mesg_out = MSG_INITIATOR_DET_ERR;
1130 1.96 fvdl }
1131 1.96 fvdl
1132 1.96 fvdl /*
1133 1.96 fvdl * We've set the hardware to assert ATN if we
1134 1.96 fvdl * get a parity error on "in" phases, so all we
1135 1.96 fvdl * need to do is stuff the message buffer with
1136 1.96 fvdl * the appropriate message. "In" phases have set
1137 1.96 fvdl * mesg_out to something other than MSG_NOP.
1138 1.96 fvdl */
1139 1.96 fvdl if (mesg_out != MSG_NOOP) {
1140 1.96 fvdl if (ahc->msg_type != MSG_TYPE_NONE)
1141 1.96 fvdl ahc->send_msg_perror = TRUE;
1142 1.96 fvdl else
1143 1.96 fvdl ahc_outb(ahc, MSG_OUT, mesg_out);
1144 1.96 fvdl }
1145 1.96 fvdl /*
1146 1.96 fvdl * Force a renegotiation with this target just in
1147 1.96 fvdl * case we are out of sync for some external reason
1148 1.96 fvdl * unknown (or unreported) by the target.
1149 1.96 fvdl */
1150 1.96 fvdl ahc_force_renegotiation(ahc);
1151 1.96 fvdl ahc_outb(ahc, CLRINT, CLRSCSIINT);
1152 1.96 fvdl ahc_unpause(ahc);
1153 1.96 fvdl } else if ((status & SELTO) != 0) {
1154 1.96 fvdl u_int scbptr;
1155 1.96 fvdl
1156 1.96 fvdl /* Stop the selection */
1157 1.96 fvdl ahc_outb(ahc, SCSISEQ, 0);
1158 1.96 fvdl
1159 1.96 fvdl /* No more pending messages */
1160 1.96 fvdl ahc_clear_msg_state(ahc);
1161 1.96 fvdl
1162 1.96 fvdl /* Clear interrupt state */
1163 1.96 fvdl ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
1164 1.96 fvdl ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR);
1165 1.96 fvdl
1166 1.96 fvdl /*
1167 1.96 fvdl * Although the driver does not care about the
1168 1.96 fvdl * 'Selection in Progress' status bit, the busy
1169 1.96 fvdl * LED does. SELINGO is only cleared by a sucessfull
1170 1.96 fvdl * selection, so we must manually clear it to insure
1171 1.96 fvdl * the LED turns off just incase no future successful
1172 1.96 fvdl * selections occur (e.g. no devices on the bus).
1173 1.96 fvdl */
1174 1.96 fvdl ahc_outb(ahc, CLRSINT0, CLRSELINGO);
1175 1.96 fvdl
1176 1.96 fvdl scbptr = ahc_inb(ahc, WAITING_SCBH);
1177 1.96 fvdl ahc_outb(ahc, SCBPTR, scbptr);
1178 1.96 fvdl scb_index = ahc_inb(ahc, SCB_TAG);
1179 1.96 fvdl
1180 1.96 fvdl scb = ahc_lookup_scb(ahc, scb_index);
1181 1.96 fvdl if (scb == NULL) {
1182 1.96 fvdl printf("%s: ahc_intr - referenced scb not "
1183 1.96 fvdl "valid during SELTO scb(%d, %d)\n",
1184 1.96 fvdl ahc_name(ahc), scbptr, scb_index);
1185 1.96 fvdl ahc_dump_card_state(ahc);
1186 1.96 fvdl } else {
1187 1.96 fvdl #ifdef AHC_DEBUG
1188 1.96 fvdl if ((ahc_debug & AHC_SHOW_SELTO) != 0) {
1189 1.96 fvdl ahc_print_path(ahc, scb);
1190 1.96 fvdl printf("Saw Selection Timeout for SCB 0x%x\n",
1191 1.96 fvdl scb_index);
1192 1.96 fvdl }
1193 1.96 fvdl #endif
1194 1.96 fvdl /*
1195 1.96 fvdl * Force a renegotiation with this target just in
1196 1.96 fvdl * case the cable was pulled and will later be
1197 1.96 fvdl * re-attached. The target may forget its negotiation
1198 1.96 fvdl * settings with us should it attempt to reselect
1199 1.96 fvdl * during the interruption. The target will not issue
1200 1.96 fvdl * a unit attention in this case, so we must always
1201 1.96 fvdl * renegotiate.
1202 1.96 fvdl */
1203 1.96 fvdl ahc_force_renegotiation(ahc);
1204 1.96 fvdl ahc_set_transaction_status(scb, CAM_SEL_TIMEOUT);
1205 1.96 fvdl ahc_freeze_devq(ahc, scb);
1206 1.96 fvdl }
1207 1.96 fvdl ahc_outb(ahc, CLRINT, CLRSCSIINT);
1208 1.96 fvdl ahc_restart(ahc);
1209 1.96 fvdl } else if ((status & BUSFREE) != 0
1210 1.96 fvdl && (ahc_inb(ahc, SIMODE1) & ENBUSFREE) != 0) {
1211 1.96 fvdl u_int lastphase;
1212 1.96 fvdl u_int saved_scsiid;
1213 1.96 fvdl u_int saved_lun;
1214 1.96 fvdl u_int target;
1215 1.96 fvdl u_int initiator_role_id;
1216 1.96 fvdl char channel;
1217 1.96 fvdl int printerror;
1218 1.96 fvdl
1219 1.96 fvdl /*
1220 1.96 fvdl * Clear our selection hardware as soon as possible.
1221 1.96 fvdl * We may have an entry in the waiting Q for this target,
1222 1.96 fvdl * that is affected by this busfree and we don't want to
1223 1.96 fvdl * go about selecting the target while we handle the event.
1224 1.96 fvdl */
1225 1.96 fvdl ahc_outb(ahc, SCSISEQ,
1226 1.96 fvdl ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP));
1227 1.96 fvdl
1228 1.96 fvdl /*
1229 1.96 fvdl * Disable busfree interrupts and clear the busfree
1230 1.96 fvdl * interrupt status. We do this here so that several
1231 1.96 fvdl * bus transactions occur prior to clearing the SCSIINT
1232 1.96 fvdl * latch. It can take a bit for the clearing to take effect.
1233 1.96 fvdl */
1234 1.96 fvdl ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
1235 1.96 fvdl ahc_outb(ahc, CLRSINT1, CLRBUSFREE|CLRSCSIPERR);
1236 1.96 fvdl
1237 1.96 fvdl /*
1238 1.96 fvdl * Look at what phase we were last in.
1239 1.96 fvdl * If its message out, chances are pretty good
1240 1.96 fvdl * that the busfree was in response to one of
1241 1.96 fvdl * our abort requests.
1242 1.96 fvdl */
1243 1.96 fvdl lastphase = ahc_inb(ahc, LASTPHASE);
1244 1.96 fvdl saved_scsiid = ahc_inb(ahc, SAVED_SCSIID);
1245 1.96 fvdl saved_lun = ahc_inb(ahc, SAVED_LUN);
1246 1.96 fvdl target = SCSIID_TARGET(ahc, saved_scsiid);
1247 1.96 fvdl initiator_role_id = SCSIID_OUR_ID(saved_scsiid);
1248 1.96 fvdl channel = SCSIID_CHANNEL(ahc, saved_scsiid);
1249 1.96 fvdl printerror = 1;
1250 1.96 fvdl
1251 1.96 fvdl if (lastphase == P_MESGOUT) {
1252 1.96 fvdl struct ahc_devinfo devinfo;
1253 1.96 fvdl u_int tag;
1254 1.96 fvdl
1255 1.96 fvdl ahc_fetch_devinfo(ahc, &devinfo);
1256 1.96 fvdl tag = SCB_LIST_NULL;
1257 1.96 fvdl if (ahc_sent_msg(ahc, AHCMSG_1B, MSG_ABORT_TAG, TRUE)
1258 1.96 fvdl || ahc_sent_msg(ahc, AHCMSG_1B, MSG_ABORT, TRUE)) {
1259 1.96 fvdl if (ahc->msgout_buf[ahc->msgout_index - 1]
1260 1.96 fvdl == MSG_ABORT_TAG)
1261 1.96 fvdl tag = scb->hscb->tag;
1262 1.96 fvdl ahc_print_path(ahc, scb);
1263 1.96 fvdl printf("SCB %d - Abort%s Completed.\n",
1264 1.96 fvdl scb->hscb->tag, tag == SCB_LIST_NULL ?
1265 1.96 fvdl "" : " Tag");
1266 1.96 fvdl ahc_abort_scbs(ahc, target, channel,
1267 1.96 fvdl saved_lun, tag,
1268 1.96 fvdl ROLE_INITIATOR,
1269 1.96 fvdl CAM_REQ_ABORTED);
1270 1.96 fvdl printerror = 0;
1271 1.96 fvdl } else if (ahc_sent_msg(ahc, AHCMSG_1B,
1272 1.96 fvdl MSG_BUS_DEV_RESET, TRUE)) {
1273 1.96 fvdl #ifdef __FreeBSD__
1274 1.96 fvdl /*
1275 1.96 fvdl * Don't mark the user's request for this BDR
1276 1.96 fvdl * as completing with CAM_BDR_SENT. CAM3
1277 1.96 fvdl * specifies CAM_REQ_CMP.
1278 1.96 fvdl */
1279 1.96 fvdl if (scb != NULL
1280 1.96 fvdl && scb->io_ctx->ccb_h.func_code== XPT_RESET_DEV
1281 1.96 fvdl && ahc_match_scb(ahc, scb, target, channel,
1282 1.96 fvdl CAM_LUN_WILDCARD,
1283 1.96 fvdl SCB_LIST_NULL,
1284 1.96 fvdl ROLE_INITIATOR)) {
1285 1.96 fvdl ahc_set_transaction_status(scb, CAM_REQ_CMP);
1286 1.96 fvdl }
1287 1.96 fvdl #endif
1288 1.96 fvdl ahc_compile_devinfo(&devinfo,
1289 1.96 fvdl initiator_role_id,
1290 1.96 fvdl target,
1291 1.96 fvdl CAM_LUN_WILDCARD,
1292 1.96 fvdl channel,
1293 1.96 fvdl ROLE_INITIATOR);
1294 1.96 fvdl ahc_handle_devreset(ahc, &devinfo,
1295 1.96 fvdl CAM_BDR_SENT,
1296 1.96 fvdl "Bus Device Reset",
1297 1.96 fvdl /*verbose_level*/0);
1298 1.96 fvdl printerror = 0;
1299 1.96 fvdl } else if (ahc_sent_msg(ahc, AHCMSG_EXT,
1300 1.96 fvdl MSG_EXT_PPR, FALSE)) {
1301 1.96 fvdl struct ahc_initiator_tinfo *tinfo;
1302 1.96 fvdl struct ahc_tmode_tstate *tstate;
1303 1.96 fvdl
1304 1.96 fvdl /*
1305 1.96 fvdl * PPR Rejected. Try non-ppr negotiation
1306 1.96 fvdl * and retry command.
1307 1.96 fvdl */
1308 1.96 fvdl tinfo = ahc_fetch_transinfo(ahc,
1309 1.96 fvdl devinfo.channel,
1310 1.96 fvdl devinfo.our_scsiid,
1311 1.96 fvdl devinfo.target,
1312 1.96 fvdl &tstate);
1313 1.96 fvdl tinfo->curr.transport_version = 2;
1314 1.96 fvdl tinfo->goal.transport_version = 2;
1315 1.96 fvdl tinfo->goal.ppr_options = 0;
1316 1.96 fvdl ahc_qinfifo_requeue_tail(ahc, scb);
1317 1.96 fvdl printerror = 0;
1318 1.96 fvdl } else if (ahc_sent_msg(ahc, AHCMSG_EXT,
1319 1.96 fvdl MSG_EXT_WDTR, FALSE)
1320 1.96 fvdl || ahc_sent_msg(ahc, AHCMSG_EXT,
1321 1.96 fvdl MSG_EXT_SDTR, FALSE)) {
1322 1.96 fvdl /*
1323 1.96 fvdl * Negotiation Rejected. Go-async and
1324 1.96 fvdl * retry command.
1325 1.96 fvdl */
1326 1.96 fvdl ahc_set_width(ahc, &devinfo,
1327 1.96 fvdl MSG_EXT_WDTR_BUS_8_BIT,
1328 1.96 fvdl AHC_TRANS_CUR|AHC_TRANS_GOAL,
1329 1.96 fvdl /*paused*/TRUE);
1330 1.96 fvdl ahc_set_syncrate(ahc, &devinfo,
1331 1.96 fvdl /*syncrate*/NULL,
1332 1.96 fvdl /*period*/0, /*offset*/0,
1333 1.96 fvdl /*ppr_options*/0,
1334 1.96 fvdl AHC_TRANS_CUR|AHC_TRANS_GOAL,
1335 1.96 fvdl /*paused*/TRUE);
1336 1.96 fvdl ahc_qinfifo_requeue_tail(ahc, scb);
1337 1.96 fvdl printerror = 0;
1338 1.96 fvdl }
1339 1.96 fvdl }
1340 1.96 fvdl if (printerror != 0) {
1341 1.96 fvdl u_int i;
1342 1.96 fvdl
1343 1.96 fvdl if (scb != NULL) {
1344 1.96 fvdl u_int tag;
1345 1.96 fvdl
1346 1.96 fvdl if ((scb->hscb->control & TAG_ENB) != 0)
1347 1.96 fvdl tag = scb->hscb->tag;
1348 1.96 fvdl else
1349 1.96 fvdl tag = SCB_LIST_NULL;
1350 1.96 fvdl ahc_print_path(ahc, scb);
1351 1.96 fvdl ahc_abort_scbs(ahc, target, channel,
1352 1.96 fvdl SCB_GET_LUN(scb), tag,
1353 1.96 fvdl ROLE_INITIATOR,
1354 1.96 fvdl CAM_UNEXP_BUSFREE);
1355 1.96 fvdl } else {
1356 1.96 fvdl /*
1357 1.96 fvdl * We had not fully identified this connection,
1358 1.96 fvdl * so we cannot abort anything.
1359 1.96 fvdl */
1360 1.96 fvdl printf("%s: ", ahc_name(ahc));
1361 1.96 fvdl }
1362 1.96 fvdl for (i = 0; i < num_phases; i++) {
1363 1.96 fvdl if (lastphase == ahc_phase_table[i].phase)
1364 1.96 fvdl break;
1365 1.96 fvdl }
1366 1.96 fvdl /*
1367 1.96 fvdl * Renegotiate with this device at the
1368 1.96 fvdl * next oportunity just in case this busfree
1369 1.96 fvdl * is due to a negotiation mismatch with the
1370 1.96 fvdl * device.
1371 1.96 fvdl */
1372 1.96 fvdl ahc_force_renegotiation(ahc);
1373 1.96 fvdl printf("Unexpected busfree %s\n"
1374 1.96 fvdl "SEQADDR == 0x%x\n",
1375 1.96 fvdl ahc_phase_table[i].phasemsg,
1376 1.96 fvdl ahc_inb(ahc, SEQADDR0)
1377 1.96 fvdl | (ahc_inb(ahc, SEQADDR1) << 8));
1378 1.96 fvdl }
1379 1.96 fvdl ahc_outb(ahc, CLRINT, CLRSCSIINT);
1380 1.96 fvdl ahc_restart(ahc);
1381 1.96 fvdl } else {
1382 1.96 fvdl printf("%s: Missing case in ahc_handle_scsiint. status = %x\n",
1383 1.96 fvdl ahc_name(ahc), status);
1384 1.96 fvdl ahc_outb(ahc, CLRINT, CLRSCSIINT);
1385 1.96 fvdl }
1386 1.96 fvdl }
1387 1.96 fvdl
1388 1.96 fvdl /*
1389 1.96 fvdl * Force renegotiation to occur the next time we initiate
1390 1.96 fvdl * a command to the current device.
1391 1.96 fvdl */
1392 1.96 fvdl static void
1393 1.96 fvdl ahc_force_renegotiation(struct ahc_softc *ahc)
1394 1.96 fvdl {
1395 1.96 fvdl struct ahc_devinfo devinfo;
1396 1.96 fvdl struct ahc_initiator_tinfo *targ_info;
1397 1.96 fvdl struct ahc_tmode_tstate *tstate;
1398 1.96 fvdl
1399 1.96 fvdl ahc_fetch_devinfo(ahc, &devinfo);
1400 1.96 fvdl targ_info = ahc_fetch_transinfo(ahc,
1401 1.96 fvdl devinfo.channel,
1402 1.96 fvdl devinfo.our_scsiid,
1403 1.96 fvdl devinfo.target,
1404 1.96 fvdl &tstate);
1405 1.96 fvdl ahc_update_neg_request(ahc, &devinfo, tstate,
1406 1.96 fvdl targ_info, AHC_NEG_IF_NON_ASYNC);
1407 1.96 fvdl }
1408 1.96 fvdl
1409 1.96 fvdl #define AHC_MAX_STEPS 2000
1410 1.96 fvdl void
1411 1.96 fvdl ahc_clear_critical_section(struct ahc_softc *ahc)
1412 1.96 fvdl {
1413 1.96 fvdl int stepping;
1414 1.96 fvdl int steps;
1415 1.96 fvdl u_int simode0;
1416 1.96 fvdl u_int simode1;
1417 1.96 fvdl
1418 1.96 fvdl if (ahc->num_critical_sections == 0)
1419 1.96 fvdl return;
1420 1.96 fvdl
1421 1.96 fvdl stepping = FALSE;
1422 1.96 fvdl steps = 0;
1423 1.96 fvdl simode0 = 0;
1424 1.96 fvdl simode1 = 0;
1425 1.96 fvdl for (;;) {
1426 1.96 fvdl struct cs *cs;
1427 1.96 fvdl u_int seqaddr;
1428 1.96 fvdl u_int i;
1429 1.96 fvdl
1430 1.96 fvdl seqaddr = ahc_inb(ahc, SEQADDR0)
1431 1.96 fvdl | (ahc_inb(ahc, SEQADDR1) << 8);
1432 1.96 fvdl
1433 1.96 fvdl /*
1434 1.96 fvdl * Seqaddr represents the next instruction to execute,
1435 1.96 fvdl * so we are really executing the instruction just
1436 1.96 fvdl * before it.
1437 1.96 fvdl */
1438 1.96 fvdl if (seqaddr != 0)
1439 1.96 fvdl seqaddr -= 1;
1440 1.96 fvdl cs = ahc->critical_sections;
1441 1.96 fvdl for (i = 0; i < ahc->num_critical_sections; i++, cs++) {
1442 1.96 fvdl
1443 1.96 fvdl if (cs->begin < seqaddr && cs->end >= seqaddr)
1444 1.96 fvdl break;
1445 1.96 fvdl }
1446 1.96 fvdl
1447 1.96 fvdl if (i == ahc->num_critical_sections)
1448 1.96 fvdl break;
1449 1.96 fvdl
1450 1.96 fvdl if (steps > AHC_MAX_STEPS) {
1451 1.96 fvdl printf("%s: Infinite loop in critical section\n",
1452 1.96 fvdl ahc_name(ahc));
1453 1.96 fvdl ahc_dump_card_state(ahc);
1454 1.96 fvdl panic("critical section loop");
1455 1.96 fvdl }
1456 1.96 fvdl
1457 1.96 fvdl steps++;
1458 1.96 fvdl if (stepping == FALSE) {
1459 1.96 fvdl
1460 1.96 fvdl /*
1461 1.96 fvdl * Disable all interrupt sources so that the
1462 1.96 fvdl * sequencer will not be stuck by a pausing
1463 1.96 fvdl * interrupt condition while we attempt to
1464 1.96 fvdl * leave a critical section.
1465 1.96 fvdl */
1466 1.96 fvdl simode0 = ahc_inb(ahc, SIMODE0);
1467 1.96 fvdl ahc_outb(ahc, SIMODE0, 0);
1468 1.96 fvdl simode1 = ahc_inb(ahc, SIMODE1);
1469 1.96 fvdl if ((ahc->features & AHC_DT) != 0)
1470 1.96 fvdl /*
1471 1.96 fvdl * On DT class controllers, we
1472 1.96 fvdl * use the enhanced busfree logic.
1473 1.96 fvdl * Unfortunately we cannot re-enable
1474 1.96 fvdl * busfree detection within the
1475 1.96 fvdl * current connection, so we must
1476 1.96 fvdl * leave it on while single stepping.
1477 1.96 fvdl */
1478 1.96 fvdl ahc_outb(ahc, SIMODE1, ENBUSFREE);
1479 1.96 fvdl else
1480 1.96 fvdl ahc_outb(ahc, SIMODE1, 0);
1481 1.96 fvdl ahc_outb(ahc, CLRINT, CLRSCSIINT);
1482 1.96 fvdl ahc_outb(ahc, SEQCTL, ahc_inb(ahc, SEQCTL) | STEP);
1483 1.96 fvdl stepping = TRUE;
1484 1.96 fvdl }
1485 1.96 fvdl if ((ahc->features & AHC_DT) != 0) {
1486 1.96 fvdl ahc_outb(ahc, CLRSINT1, CLRBUSFREE);
1487 1.96 fvdl ahc_outb(ahc, CLRINT, CLRSCSIINT);
1488 1.96 fvdl }
1489 1.96 fvdl ahc_outb(ahc, HCNTRL, ahc->unpause);
1490 1.96 fvdl while (!ahc_is_paused(ahc))
1491 1.96 fvdl ahc_delay(200);
1492 1.96 fvdl }
1493 1.96 fvdl if (stepping) {
1494 1.96 fvdl ahc_outb(ahc, SIMODE0, simode0);
1495 1.96 fvdl ahc_outb(ahc, SIMODE1, simode1);
1496 1.96 fvdl ahc_outb(ahc, SEQCTL, ahc_inb(ahc, SEQCTL) & ~STEP);
1497 1.96 fvdl }
1498 1.96 fvdl }
1499 1.96 fvdl
1500 1.96 fvdl /*
1501 1.96 fvdl * Clear any pending interrupt status.
1502 1.96 fvdl */
1503 1.96 fvdl void
1504 1.96 fvdl ahc_clear_intstat(struct ahc_softc *ahc)
1505 1.96 fvdl {
1506 1.96 fvdl /* Clear any interrupt conditions this may have caused */
1507 1.96 fvdl ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRATNO|CLRSCSIRSTI
1508 1.96 fvdl |CLRBUSFREE|CLRSCSIPERR|CLRPHASECHG|
1509 1.96 fvdl CLRREQINIT);
1510 1.96 fvdl ahc_flush_device_writes(ahc);
1511 1.96 fvdl ahc_outb(ahc, CLRSINT0, CLRSELDO|CLRSELDI|CLRSELINGO);
1512 1.96 fvdl ahc_flush_device_writes(ahc);
1513 1.96 fvdl ahc_outb(ahc, CLRINT, CLRSCSIINT);
1514 1.96 fvdl ahc_flush_device_writes(ahc);
1515 1.96 fvdl }
1516 1.96 fvdl
1517 1.96 fvdl /**************************** Debugging Routines ******************************/
1518 1.96 fvdl #ifdef AHC_DEBUG
1519 1.96 fvdl uint32_t ahc_debug = 0; /* AHC_SHOW_MISC|AHC_SHOW_SENSE|AHC_DEBUG_OPTS;*/
1520 1.96 fvdl #endif
1521 1.96 fvdl
1522 1.96 fvdl void
1523 1.96 fvdl ahc_print_scb(struct scb *scb)
1524 1.96 fvdl {
1525 1.96 fvdl int i;
1526 1.96 fvdl
1527 1.96 fvdl struct hardware_scb *hscb = scb->hscb;
1528 1.96 fvdl
1529 1.96 fvdl printf("scb:%p control:0x%x scsiid:0x%x lun:%d cdb_len:%d\n",
1530 1.96 fvdl (void *)scb,
1531 1.96 fvdl hscb->control,
1532 1.96 fvdl hscb->scsiid,
1533 1.96 fvdl hscb->lun,
1534 1.96 fvdl hscb->cdb_len);
1535 1.96 fvdl printf("Shared Data: ");
1536 1.96 fvdl for (i = 0; i < sizeof(hscb->shared_data.cdb); i++)
1537 1.96 fvdl printf("%#02x", hscb->shared_data.cdb[i]);
1538 1.96 fvdl printf(" dataptr:%#x datacnt:%#x sgptr:%#x tag:%#x\n",
1539 1.96 fvdl ahc_le32toh(hscb->dataptr),
1540 1.96 fvdl ahc_le32toh(hscb->datacnt),
1541 1.96 fvdl ahc_le32toh(hscb->sgptr),
1542 1.96 fvdl hscb->tag);
1543 1.96 fvdl if (scb->sg_count > 0) {
1544 1.96 fvdl for (i = 0; i < scb->sg_count; i++) {
1545 1.96 fvdl printf("sg[%d] - Addr 0x%x%x : Length %d\n",
1546 1.96 fvdl i,
1547 1.96 fvdl (ahc_le32toh(scb->sg_list[i].len) >> 24
1548 1.96 fvdl & SG_HIGH_ADDR_BITS),
1549 1.96 fvdl ahc_le32toh(scb->sg_list[i].addr),
1550 1.96 fvdl ahc_le32toh(scb->sg_list[i].len));
1551 1.96 fvdl }
1552 1.96 fvdl }
1553 1.96 fvdl }
1554 1.96 fvdl
1555 1.96 fvdl /************************* Transfer Negotiation *******************************/
1556 1.96 fvdl /*
1557 1.96 fvdl * Allocate per target mode instance (ID we respond to as a target)
1558 1.96 fvdl * transfer negotiation data structures.
1559 1.96 fvdl */
1560 1.96 fvdl static struct ahc_tmode_tstate *
1561 1.96 fvdl ahc_alloc_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel)
1562 1.96 fvdl {
1563 1.96 fvdl struct ahc_tmode_tstate *master_tstate;
1564 1.96 fvdl struct ahc_tmode_tstate *tstate;
1565 1.96 fvdl int i;
1566 1.96 fvdl
1567 1.96 fvdl master_tstate = ahc->enabled_targets[ahc->our_id];
1568 1.96 fvdl if (channel == 'B') {
1569 1.96 fvdl scsi_id += 8;
1570 1.96 fvdl master_tstate = ahc->enabled_targets[ahc->our_id_b + 8];
1571 1.96 fvdl }
1572 1.96 fvdl if (ahc->enabled_targets[scsi_id] != NULL
1573 1.96 fvdl && ahc->enabled_targets[scsi_id] != master_tstate)
1574 1.96 fvdl panic("%s: ahc_alloc_tstate - Target already allocated",
1575 1.96 fvdl ahc_name(ahc));
1576 1.96 fvdl tstate = (struct ahc_tmode_tstate*)malloc(sizeof(*tstate),
1577 1.96 fvdl M_DEVBUF, M_NOWAIT);
1578 1.96 fvdl if (tstate == NULL)
1579 1.96 fvdl return (NULL);
1580 1.96 fvdl
1581 1.96 fvdl /*
1582 1.96 fvdl * If we have allocated a master tstate, copy user settings from
1583 1.96 fvdl * the master tstate (taken from SRAM or the EEPROM) for this
1584 1.96 fvdl * channel, but reset our current and goal settings to async/narrow
1585 1.96 fvdl * until an initiator talks to us.
1586 1.96 fvdl */
1587 1.96 fvdl if (master_tstate != NULL) {
1588 1.96 fvdl memcpy(tstate, master_tstate, sizeof(*tstate));
1589 1.96 fvdl memset(tstate->enabled_luns, 0, sizeof(tstate->enabled_luns));
1590 1.96 fvdl tstate->ultraenb = 0;
1591 1.96 fvdl for (i = 0; i < AHC_NUM_TARGETS; i++) {
1592 1.96 fvdl memset(&tstate->transinfo[i].curr, 0,
1593 1.96 fvdl sizeof(tstate->transinfo[i].curr));
1594 1.96 fvdl memset(&tstate->transinfo[i].goal, 0,
1595 1.96 fvdl sizeof(tstate->transinfo[i].goal));
1596 1.96 fvdl }
1597 1.96 fvdl } else
1598 1.96 fvdl memset(tstate, 0, sizeof(*tstate));
1599 1.96 fvdl ahc->enabled_targets[scsi_id] = tstate;
1600 1.96 fvdl return (tstate);
1601 1.96 fvdl }
1602 1.96 fvdl
1603 1.96 fvdl #ifdef AHC_TARGET_MODE
1604 1.96 fvdl /*
1605 1.96 fvdl * Free per target mode instance (ID we respond to as a target)
1606 1.96 fvdl * transfer negotiation data structures.
1607 1.96 fvdl */
1608 1.96 fvdl static void
1609 1.96 fvdl ahc_free_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel, int force)
1610 1.96 fvdl {
1611 1.96 fvdl struct ahc_tmode_tstate *tstate;
1612 1.96 fvdl
1613 1.96 fvdl /*
1614 1.96 fvdl * Don't clean up our "master" tstate.
1615 1.96 fvdl * It has our default user settings.
1616 1.96 fvdl */
1617 1.96 fvdl if (((channel == 'B' && scsi_id == ahc->our_id_b)
1618 1.96 fvdl || (channel == 'A' && scsi_id == ahc->our_id))
1619 1.96 fvdl && force == FALSE)
1620 1.96 fvdl return;
1621 1.96 fvdl
1622 1.96 fvdl if (channel == 'B')
1623 1.96 fvdl scsi_id += 8;
1624 1.96 fvdl tstate = ahc->enabled_targets[scsi_id];
1625 1.96 fvdl if (tstate != NULL)
1626 1.96 fvdl free(tstate, M_DEVBUF);
1627 1.96 fvdl ahc->enabled_targets[scsi_id] = NULL;
1628 1.96 fvdl }
1629 1.96 fvdl #endif
1630 1.96 fvdl
1631 1.96 fvdl /*
1632 1.96 fvdl * Called when we have an active connection to a target on the bus,
1633 1.96 fvdl * this function finds the nearest syncrate to the input period limited
1634 1.96 fvdl * by the capabilities of the bus connectivity of and sync settings for
1635 1.96 fvdl * the target.
1636 1.96 fvdl */
1637 1.96 fvdl struct ahc_syncrate *
1638 1.96 fvdl ahc_devlimited_syncrate(struct ahc_softc *ahc,
1639 1.96 fvdl struct ahc_initiator_tinfo *tinfo,
1640 1.96 fvdl u_int *period, u_int *ppr_options, role_t role)
1641 1.96 fvdl {
1642 1.96 fvdl struct ahc_transinfo *transinfo;
1643 1.96 fvdl u_int maxsync;
1644 1.96 fvdl
1645 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0) {
1646 1.96 fvdl if ((ahc_inb(ahc, SBLKCTL) & ENAB40) != 0
1647 1.96 fvdl && (ahc_inb(ahc, SSTAT2) & EXP_ACTIVE) == 0) {
1648 1.96 fvdl maxsync = AHC_SYNCRATE_DT;
1649 1.96 fvdl } else {
1650 1.96 fvdl maxsync = AHC_SYNCRATE_ULTRA;
1651 1.96 fvdl /* Can't do DT on an SE bus */
1652 1.96 fvdl *ppr_options &= ~MSG_EXT_PPR_DT_REQ;
1653 1.96 fvdl }
1654 1.96 fvdl } else if ((ahc->features & AHC_ULTRA) != 0) {
1655 1.96 fvdl maxsync = AHC_SYNCRATE_ULTRA;
1656 1.96 fvdl } else {
1657 1.96 fvdl maxsync = AHC_SYNCRATE_FAST;
1658 1.96 fvdl }
1659 1.96 fvdl /*
1660 1.96 fvdl * Never allow a value higher than our current goal
1661 1.96 fvdl * period otherwise we may allow a target initiated
1662 1.96 fvdl * negotiation to go above the limit as set by the
1663 1.96 fvdl * user. In the case of an initiator initiated
1664 1.96 fvdl * sync negotiation, we limit based on the user
1665 1.96 fvdl * setting. This allows the system to still accept
1666 1.96 fvdl * incoming negotiations even if target initiated
1667 1.96 fvdl * negotiation is not performed.
1668 1.96 fvdl */
1669 1.96 fvdl if (role == ROLE_TARGET)
1670 1.96 fvdl transinfo = &tinfo->user;
1671 1.96 fvdl else
1672 1.96 fvdl transinfo = &tinfo->goal;
1673 1.96 fvdl *ppr_options &= transinfo->ppr_options;
1674 1.96 fvdl if (transinfo->width == MSG_EXT_WDTR_BUS_8_BIT) {
1675 1.96 fvdl maxsync = MAX(maxsync, AHC_SYNCRATE_ULTRA2);
1676 1.96 fvdl *ppr_options &= ~MSG_EXT_PPR_DT_REQ;
1677 1.96 fvdl }
1678 1.96 fvdl if (transinfo->period == 0) {
1679 1.96 fvdl *period = 0;
1680 1.96 fvdl *ppr_options = 0;
1681 1.96 fvdl return (NULL);
1682 1.96 fvdl }
1683 1.96 fvdl *period = MAX(*period, transinfo->period);
1684 1.96 fvdl return (ahc_find_syncrate(ahc, period, ppr_options, maxsync));
1685 1.96 fvdl }
1686 1.96 fvdl
1687 1.96 fvdl /*
1688 1.96 fvdl * Look up the valid period to SCSIRATE conversion in our table.
1689 1.96 fvdl * Return the period and offset that should be sent to the target
1690 1.96 fvdl * if this was the beginning of an SDTR.
1691 1.96 fvdl */
1692 1.96 fvdl struct ahc_syncrate *
1693 1.96 fvdl ahc_find_syncrate(struct ahc_softc *ahc, u_int *period,
1694 1.96 fvdl u_int *ppr_options, u_int maxsync)
1695 1.96 fvdl {
1696 1.96 fvdl struct ahc_syncrate *syncrate;
1697 1.96 fvdl
1698 1.96 fvdl if ((ahc->features & AHC_DT) == 0)
1699 1.96 fvdl *ppr_options &= ~MSG_EXT_PPR_DT_REQ;
1700 1.96 fvdl
1701 1.96 fvdl /* Skip all DT only entries if DT is not available */
1702 1.96 fvdl if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0
1703 1.96 fvdl && maxsync < AHC_SYNCRATE_ULTRA2)
1704 1.96 fvdl maxsync = AHC_SYNCRATE_ULTRA2;
1705 1.96 fvdl
1706 1.96 fvdl for (syncrate = &ahc_syncrates[maxsync];
1707 1.96 fvdl syncrate->rate != NULL;
1708 1.96 fvdl syncrate++) {
1709 1.96 fvdl
1710 1.96 fvdl /*
1711 1.96 fvdl * The Ultra2 table doesn't go as low
1712 1.96 fvdl * as for the Fast/Ultra cards.
1713 1.96 fvdl */
1714 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0
1715 1.96 fvdl && (syncrate->sxfr_u2 == 0))
1716 1.96 fvdl break;
1717 1.96 fvdl
1718 1.96 fvdl if (*period <= syncrate->period) {
1719 1.96 fvdl /*
1720 1.96 fvdl * When responding to a target that requests
1721 1.96 fvdl * sync, the requested rate may fall between
1722 1.96 fvdl * two rates that we can output, but still be
1723 1.96 fvdl * a rate that we can receive. Because of this,
1724 1.96 fvdl * we want to respond to the target with
1725 1.96 fvdl * the same rate that it sent to us even
1726 1.96 fvdl * if the period we use to send data to it
1727 1.96 fvdl * is lower. Only lower the response period
1728 1.96 fvdl * if we must.
1729 1.96 fvdl */
1730 1.96 fvdl if (syncrate == &ahc_syncrates[maxsync])
1731 1.96 fvdl *period = syncrate->period;
1732 1.96 fvdl
1733 1.96 fvdl /*
1734 1.96 fvdl * At some speeds, we only support
1735 1.96 fvdl * ST transfers.
1736 1.96 fvdl */
1737 1.96 fvdl if ((syncrate->sxfr_u2 & ST_SXFR) != 0)
1738 1.96 fvdl *ppr_options &= ~MSG_EXT_PPR_DT_REQ;
1739 1.96 fvdl break;
1740 1.96 fvdl }
1741 1.96 fvdl }
1742 1.96 fvdl
1743 1.96 fvdl if ((*period == 0)
1744 1.96 fvdl || (syncrate->rate == NULL)
1745 1.96 fvdl || ((ahc->features & AHC_ULTRA2) != 0
1746 1.96 fvdl && (syncrate->sxfr_u2 == 0))) {
1747 1.96 fvdl /* Use asynchronous transfers. */
1748 1.96 fvdl *period = 0;
1749 1.96 fvdl syncrate = NULL;
1750 1.96 fvdl *ppr_options &= ~MSG_EXT_PPR_DT_REQ;
1751 1.96 fvdl }
1752 1.96 fvdl return (syncrate);
1753 1.96 fvdl }
1754 1.96 fvdl
1755 1.96 fvdl /*
1756 1.96 fvdl * Convert from an entry in our syncrate table to the SCSI equivalent
1757 1.96 fvdl * sync "period" factor.
1758 1.96 fvdl */
1759 1.96 fvdl u_int
1760 1.96 fvdl ahc_find_period(struct ahc_softc *ahc, u_int scsirate, u_int maxsync)
1761 1.96 fvdl {
1762 1.96 fvdl struct ahc_syncrate *syncrate;
1763 1.96 fvdl
1764 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0)
1765 1.96 fvdl scsirate &= SXFR_ULTRA2;
1766 1.96 fvdl else
1767 1.96 fvdl scsirate &= SXFR;
1768 1.96 fvdl
1769 1.96 fvdl syncrate = &ahc_syncrates[maxsync];
1770 1.96 fvdl while (syncrate->rate != NULL) {
1771 1.96 fvdl
1772 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0) {
1773 1.96 fvdl if (syncrate->sxfr_u2 == 0)
1774 1.96 fvdl break;
1775 1.96 fvdl else if (scsirate == (syncrate->sxfr_u2 & SXFR_ULTRA2))
1776 1.96 fvdl return (syncrate->period);
1777 1.96 fvdl } else if (scsirate == (syncrate->sxfr & SXFR)) {
1778 1.96 fvdl return (syncrate->period);
1779 1.96 fvdl }
1780 1.96 fvdl syncrate++;
1781 1.96 fvdl }
1782 1.96 fvdl return (0); /* async */
1783 1.96 fvdl }
1784 1.96 fvdl
1785 1.96 fvdl /*
1786 1.96 fvdl * Truncate the given synchronous offset to a value the
1787 1.96 fvdl * current adapter type and syncrate are capable of.
1788 1.96 fvdl */
1789 1.96 fvdl void
1790 1.96 fvdl ahc_validate_offset(struct ahc_softc *ahc,
1791 1.96 fvdl struct ahc_initiator_tinfo *tinfo,
1792 1.96 fvdl struct ahc_syncrate *syncrate,
1793 1.96 fvdl u_int *offset, int wide, role_t role)
1794 1.96 fvdl {
1795 1.96 fvdl u_int maxoffset;
1796 1.96 fvdl
1797 1.96 fvdl /* Limit offset to what we can do */
1798 1.96 fvdl if (syncrate == NULL) {
1799 1.96 fvdl maxoffset = 0;
1800 1.96 fvdl } else if ((ahc->features & AHC_ULTRA2) != 0) {
1801 1.96 fvdl maxoffset = MAX_OFFSET_ULTRA2;
1802 1.96 fvdl } else {
1803 1.96 fvdl if (wide)
1804 1.96 fvdl maxoffset = MAX_OFFSET_16BIT;
1805 1.96 fvdl else
1806 1.96 fvdl maxoffset = MAX_OFFSET_8BIT;
1807 1.96 fvdl }
1808 1.96 fvdl *offset = MIN(*offset, maxoffset);
1809 1.96 fvdl if (tinfo != NULL) {
1810 1.96 fvdl if (role == ROLE_TARGET)
1811 1.96 fvdl *offset = MIN(*offset, tinfo->user.offset);
1812 1.96 fvdl else
1813 1.96 fvdl *offset = MIN(*offset, tinfo->goal.offset);
1814 1.96 fvdl }
1815 1.96 fvdl }
1816 1.96 fvdl
1817 1.96 fvdl /*
1818 1.96 fvdl * Truncate the given transfer width parameter to a value the
1819 1.96 fvdl * current adapter type is capable of.
1820 1.96 fvdl */
1821 1.96 fvdl void
1822 1.96 fvdl ahc_validate_width(struct ahc_softc *ahc, struct ahc_initiator_tinfo *tinfo,
1823 1.96 fvdl u_int *bus_width, role_t role)
1824 1.96 fvdl {
1825 1.96 fvdl switch (*bus_width) {
1826 1.96 fvdl default:
1827 1.96 fvdl if (ahc->features & AHC_WIDE) {
1828 1.96 fvdl /* Respond Wide */
1829 1.96 fvdl *bus_width = MSG_EXT_WDTR_BUS_16_BIT;
1830 1.96 fvdl break;
1831 1.96 fvdl }
1832 1.96 fvdl /* FALLTHROUGH */
1833 1.96 fvdl case MSG_EXT_WDTR_BUS_8_BIT:
1834 1.96 fvdl *bus_width = MSG_EXT_WDTR_BUS_8_BIT;
1835 1.96 fvdl break;
1836 1.96 fvdl }
1837 1.96 fvdl if (tinfo != NULL) {
1838 1.96 fvdl if (role == ROLE_TARGET)
1839 1.96 fvdl *bus_width = MIN(tinfo->user.width, *bus_width);
1840 1.96 fvdl else
1841 1.96 fvdl *bus_width = MIN(tinfo->goal.width, *bus_width);
1842 1.96 fvdl }
1843 1.96 fvdl }
1844 1.96 fvdl
1845 1.96 fvdl /*
1846 1.96 fvdl * Update the bitmask of targets for which the controller should
1847 1.96 fvdl * negotiate with at the next convenient oportunity. This currently
1848 1.96 fvdl * means the next time we send the initial identify messages for
1849 1.96 fvdl * a new transaction.
1850 1.96 fvdl */
1851 1.96 fvdl int
1852 1.96 fvdl ahc_update_neg_request(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
1853 1.96 fvdl struct ahc_tmode_tstate *tstate,
1854 1.96 fvdl struct ahc_initiator_tinfo *tinfo, ahc_neg_type neg_type)
1855 1.96 fvdl {
1856 1.96 fvdl u_int auto_negotiate_orig;
1857 1.96 fvdl
1858 1.96 fvdl auto_negotiate_orig = tstate->auto_negotiate;
1859 1.96 fvdl if (neg_type == AHC_NEG_ALWAYS) {
1860 1.96 fvdl /*
1861 1.96 fvdl * Force our "current" settings to be
1862 1.96 fvdl * unknown so that unless a bus reset
1863 1.96 fvdl * occurs the need to renegotiate is
1864 1.96 fvdl * recorded persistently.
1865 1.96 fvdl */
1866 1.96 fvdl if ((ahc->features & AHC_WIDE) != 0)
1867 1.96 fvdl tinfo->curr.width = AHC_WIDTH_UNKNOWN;
1868 1.96 fvdl tinfo->curr.period = AHC_PERIOD_UNKNOWN;
1869 1.96 fvdl tinfo->curr.offset = AHC_OFFSET_UNKNOWN;
1870 1.96 fvdl }
1871 1.96 fvdl if (tinfo->curr.period != tinfo->goal.period
1872 1.96 fvdl || tinfo->curr.width != tinfo->goal.width
1873 1.96 fvdl || tinfo->curr.offset != tinfo->goal.offset
1874 1.96 fvdl || tinfo->curr.ppr_options != tinfo->goal.ppr_options
1875 1.96 fvdl || (neg_type == AHC_NEG_IF_NON_ASYNC
1876 1.96 fvdl && (tinfo->goal.offset != 0
1877 1.96 fvdl || tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT
1878 1.96 fvdl || tinfo->goal.ppr_options != 0)))
1879 1.96 fvdl tstate->auto_negotiate |= devinfo->target_mask;
1880 1.96 fvdl else
1881 1.96 fvdl tstate->auto_negotiate &= ~devinfo->target_mask;
1882 1.96 fvdl
1883 1.96 fvdl return (auto_negotiate_orig != tstate->auto_negotiate);
1884 1.96 fvdl }
1885 1.96 fvdl
1886 1.96 fvdl /*
1887 1.96 fvdl * Update the user/goal/curr tables of synchronous negotiation
1888 1.96 fvdl * parameters as well as, in the case of a current or active update,
1889 1.96 fvdl * any data structures on the host controller. In the case of an
1890 1.96 fvdl * active update, the specified target is currently talking to us on
1891 1.96 fvdl * the bus, so the transfer parameter update must take effect
1892 1.96 fvdl * immediately.
1893 1.96 fvdl */
1894 1.96 fvdl void
1895 1.96 fvdl ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
1896 1.96 fvdl struct ahc_syncrate *syncrate, u_int period,
1897 1.96 fvdl u_int offset, u_int ppr_options, u_int type, int paused)
1898 1.96 fvdl {
1899 1.96 fvdl struct ahc_initiator_tinfo *tinfo;
1900 1.96 fvdl struct ahc_tmode_tstate *tstate;
1901 1.96 fvdl u_int old_period;
1902 1.96 fvdl u_int old_offset;
1903 1.96 fvdl u_int old_ppr;
1904 1.96 fvdl int active;
1905 1.96 fvdl int update_needed;
1906 1.96 fvdl
1907 1.96 fvdl active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE;
1908 1.96 fvdl update_needed = 0;
1909 1.96 fvdl
1910 1.96 fvdl if (syncrate == NULL) {
1911 1.96 fvdl period = 0;
1912 1.96 fvdl offset = 0;
1913 1.96 fvdl }
1914 1.96 fvdl
1915 1.96 fvdl tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
1916 1.96 fvdl devinfo->target, &tstate);
1917 1.96 fvdl
1918 1.96 fvdl if ((type & AHC_TRANS_USER) != 0) {
1919 1.96 fvdl tinfo->user.period = period;
1920 1.96 fvdl tinfo->user.offset = offset;
1921 1.96 fvdl tinfo->user.ppr_options = ppr_options;
1922 1.96 fvdl }
1923 1.96 fvdl
1924 1.96 fvdl if ((type & AHC_TRANS_GOAL) != 0) {
1925 1.96 fvdl tinfo->goal.period = period;
1926 1.96 fvdl tinfo->goal.offset = offset;
1927 1.96 fvdl tinfo->goal.ppr_options = ppr_options;
1928 1.96 fvdl }
1929 1.96 fvdl
1930 1.96 fvdl old_period = tinfo->curr.period;
1931 1.96 fvdl old_offset = tinfo->curr.offset;
1932 1.96 fvdl old_ppr = tinfo->curr.ppr_options;
1933 1.96 fvdl
1934 1.96 fvdl if ((type & AHC_TRANS_CUR) != 0
1935 1.96 fvdl && (old_period != period
1936 1.96 fvdl || old_offset != offset
1937 1.96 fvdl || old_ppr != ppr_options)) {
1938 1.96 fvdl u_int scsirate;
1939 1.96 fvdl
1940 1.96 fvdl update_needed++;
1941 1.96 fvdl scsirate = tinfo->scsirate;
1942 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0) {
1943 1.96 fvdl
1944 1.96 fvdl scsirate &= ~(SXFR_ULTRA2|SINGLE_EDGE|ENABLE_CRC);
1945 1.96 fvdl if (syncrate != NULL) {
1946 1.96 fvdl scsirate |= syncrate->sxfr_u2;
1947 1.96 fvdl if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0)
1948 1.96 fvdl scsirate |= ENABLE_CRC;
1949 1.96 fvdl else
1950 1.96 fvdl scsirate |= SINGLE_EDGE;
1951 1.96 fvdl }
1952 1.96 fvdl } else {
1953 1.96 fvdl
1954 1.96 fvdl scsirate &= ~(SXFR|SOFS);
1955 1.96 fvdl /*
1956 1.96 fvdl * Ensure Ultra mode is set properly for
1957 1.96 fvdl * this target.
1958 1.96 fvdl */
1959 1.96 fvdl tstate->ultraenb &= ~devinfo->target_mask;
1960 1.96 fvdl if (syncrate != NULL) {
1961 1.96 fvdl if (syncrate->sxfr & ULTRA_SXFR) {
1962 1.96 fvdl tstate->ultraenb |=
1963 1.96 fvdl devinfo->target_mask;
1964 1.96 fvdl }
1965 1.96 fvdl scsirate |= syncrate->sxfr & SXFR;
1966 1.96 fvdl scsirate |= offset & SOFS;
1967 1.96 fvdl }
1968 1.96 fvdl if (active) {
1969 1.96 fvdl u_int sxfrctl0;
1970 1.96 fvdl
1971 1.96 fvdl sxfrctl0 = ahc_inb(ahc, SXFRCTL0);
1972 1.96 fvdl sxfrctl0 &= ~FAST20;
1973 1.96 fvdl if (tstate->ultraenb & devinfo->target_mask)
1974 1.96 fvdl sxfrctl0 |= FAST20;
1975 1.96 fvdl ahc_outb(ahc, SXFRCTL0, sxfrctl0);
1976 1.96 fvdl }
1977 1.96 fvdl }
1978 1.96 fvdl if (active) {
1979 1.96 fvdl ahc_outb(ahc, SCSIRATE, scsirate);
1980 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0)
1981 1.96 fvdl ahc_outb(ahc, SCSIOFFSET, offset);
1982 1.96 fvdl }
1983 1.96 fvdl
1984 1.96 fvdl tinfo->scsirate = scsirate;
1985 1.96 fvdl tinfo->curr.period = period;
1986 1.96 fvdl tinfo->curr.offset = offset;
1987 1.96 fvdl tinfo->curr.ppr_options = ppr_options;
1988 1.96 fvdl
1989 1.96 fvdl ahc_send_async(ahc, devinfo->channel, devinfo->target,
1990 1.96 fvdl CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
1991 1.96 fvdl if (bootverbose) {
1992 1.96 fvdl if (offset != 0) {
1993 1.96 fvdl printf("%s: target %d synchronous at %sMHz%s, "
1994 1.96 fvdl "offset = 0x%x\n", ahc_name(ahc),
1995 1.96 fvdl devinfo->target, syncrate->rate,
1996 1.96 fvdl (ppr_options & MSG_EXT_PPR_DT_REQ)
1997 1.96 fvdl ? " DT" : "", offset);
1998 1.96 fvdl } else {
1999 1.96 fvdl printf("%s: target %d using "
2000 1.96 fvdl "asynchronous transfers\n",
2001 1.96 fvdl ahc_name(ahc), devinfo->target);
2002 1.96 fvdl }
2003 1.96 fvdl }
2004 1.96 fvdl }
2005 1.96 fvdl
2006 1.96 fvdl update_needed += ahc_update_neg_request(ahc, devinfo, tstate,
2007 1.96 fvdl tinfo, AHC_NEG_TO_GOAL);
2008 1.96 fvdl
2009 1.96 fvdl if (update_needed)
2010 1.96 fvdl ahc_update_pending_scbs(ahc);
2011 1.96 fvdl }
2012 1.96 fvdl
2013 1.96 fvdl /*
2014 1.96 fvdl * Update the user/goal/curr tables of wide negotiation
2015 1.96 fvdl * parameters as well as, in the case of a current or active update,
2016 1.96 fvdl * any data structures on the host controller. In the case of an
2017 1.96 fvdl * active update, the specified target is currently talking to us on
2018 1.96 fvdl * the bus, so the transfer parameter update must take effect
2019 1.96 fvdl * immediately.
2020 1.96 fvdl */
2021 1.96 fvdl void
2022 1.96 fvdl ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
2023 1.96 fvdl u_int width, u_int type, int paused)
2024 1.96 fvdl {
2025 1.96 fvdl struct ahc_initiator_tinfo *tinfo;
2026 1.96 fvdl struct ahc_tmode_tstate *tstate;
2027 1.96 fvdl u_int oldwidth;
2028 1.96 fvdl int active;
2029 1.96 fvdl int update_needed;
2030 1.96 fvdl
2031 1.96 fvdl active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE;
2032 1.96 fvdl update_needed = 0;
2033 1.96 fvdl tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
2034 1.96 fvdl devinfo->target, &tstate);
2035 1.96 fvdl
2036 1.96 fvdl if ((type & AHC_TRANS_USER) != 0)
2037 1.96 fvdl tinfo->user.width = width;
2038 1.96 fvdl
2039 1.96 fvdl if ((type & AHC_TRANS_GOAL) != 0)
2040 1.96 fvdl tinfo->goal.width = width;
2041 1.96 fvdl
2042 1.96 fvdl oldwidth = tinfo->curr.width;
2043 1.96 fvdl if ((type & AHC_TRANS_CUR) != 0 && oldwidth != width) {
2044 1.96 fvdl u_int scsirate;
2045 1.96 fvdl
2046 1.96 fvdl update_needed++;
2047 1.96 fvdl scsirate = tinfo->scsirate;
2048 1.96 fvdl scsirate &= ~WIDEXFER;
2049 1.96 fvdl if (width == MSG_EXT_WDTR_BUS_16_BIT)
2050 1.96 fvdl scsirate |= WIDEXFER;
2051 1.96 fvdl
2052 1.96 fvdl tinfo->scsirate = scsirate;
2053 1.96 fvdl
2054 1.96 fvdl if (active)
2055 1.96 fvdl ahc_outb(ahc, SCSIRATE, scsirate);
2056 1.96 fvdl
2057 1.96 fvdl tinfo->curr.width = width;
2058 1.96 fvdl
2059 1.96 fvdl ahc_send_async(ahc, devinfo->channel, devinfo->target,
2060 1.96 fvdl CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
2061 1.96 fvdl if (bootverbose) {
2062 1.96 fvdl printf("%s: target %d using %dbit transfers\n",
2063 1.96 fvdl ahc_name(ahc), devinfo->target,
2064 1.96 fvdl 8 * (0x01 << width));
2065 1.96 fvdl }
2066 1.96 fvdl }
2067 1.96 fvdl
2068 1.96 fvdl update_needed += ahc_update_neg_request(ahc, devinfo, tstate,
2069 1.96 fvdl tinfo, AHC_NEG_TO_GOAL);
2070 1.96 fvdl if (update_needed)
2071 1.96 fvdl ahc_update_pending_scbs(ahc);
2072 1.96 fvdl }
2073 1.96 fvdl
2074 1.96 fvdl /*
2075 1.96 fvdl * Update the current state of tagged queuing for a given target.
2076 1.96 fvdl */
2077 1.96 fvdl void
2078 1.96 fvdl ahc_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
2079 1.96 fvdl ahc_queue_alg alg)
2080 1.96 fvdl {
2081 1.96 fvdl ahc_platform_set_tags(ahc, devinfo, alg);
2082 1.96 fvdl }
2083 1.96 fvdl
2084 1.96 fvdl /*
2085 1.96 fvdl * When the transfer settings for a connection change, update any
2086 1.96 fvdl * in-transit SCBs to contain the new data so the hardware will
2087 1.96 fvdl * be set correctly during future (re)selections.
2088 1.96 fvdl */
2089 1.96 fvdl static void
2090 1.96 fvdl ahc_update_pending_scbs(struct ahc_softc *ahc)
2091 1.96 fvdl {
2092 1.96 fvdl struct scb *pending_scb;
2093 1.96 fvdl int pending_scb_count;
2094 1.96 fvdl int i;
2095 1.96 fvdl int paused;
2096 1.96 fvdl u_int saved_scbptr;
2097 1.96 fvdl
2098 1.96 fvdl /*
2099 1.96 fvdl * Traverse the pending SCB list and ensure that all of the
2100 1.96 fvdl * SCBs there have the proper settings.
2101 1.96 fvdl */
2102 1.96 fvdl pending_scb_count = 0;
2103 1.96 fvdl LIST_FOREACH(pending_scb, &ahc->pending_scbs, pending_links) {
2104 1.96 fvdl struct ahc_devinfo devinfo;
2105 1.96 fvdl struct hardware_scb *pending_hscb;
2106 1.96 fvdl struct ahc_initiator_tinfo *tinfo;
2107 1.96 fvdl struct ahc_tmode_tstate *tstate;
2108 1.96 fvdl
2109 1.96 fvdl ahc_scb_devinfo(ahc, &devinfo, pending_scb);
2110 1.96 fvdl tinfo = ahc_fetch_transinfo(ahc, devinfo.channel,
2111 1.96 fvdl devinfo.our_scsiid,
2112 1.96 fvdl devinfo.target, &tstate);
2113 1.96 fvdl pending_hscb = pending_scb->hscb;
2114 1.96 fvdl pending_hscb->control &= ~ULTRAENB;
2115 1.96 fvdl if ((tstate->ultraenb & devinfo.target_mask) != 0)
2116 1.96 fvdl pending_hscb->control |= ULTRAENB;
2117 1.96 fvdl pending_hscb->scsirate = tinfo->scsirate;
2118 1.96 fvdl pending_hscb->scsioffset = tinfo->curr.offset;
2119 1.96 fvdl if ((tstate->auto_negotiate & devinfo.target_mask) == 0
2120 1.96 fvdl && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) {
2121 1.96 fvdl pending_scb->flags &= ~SCB_AUTO_NEGOTIATE;
2122 1.96 fvdl pending_hscb->control &= ~MK_MESSAGE;
2123 1.96 fvdl }
2124 1.96 fvdl ahc_sync_scb(ahc, pending_scb,
2125 1.96 fvdl BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
2126 1.96 fvdl pending_scb_count++;
2127 1.96 fvdl }
2128 1.96 fvdl
2129 1.96 fvdl if (pending_scb_count == 0)
2130 1.96 fvdl return;
2131 1.96 fvdl
2132 1.96 fvdl if (ahc_is_paused(ahc)) {
2133 1.96 fvdl paused = 1;
2134 1.96 fvdl } else {
2135 1.96 fvdl paused = 0;
2136 1.96 fvdl ahc_pause(ahc);
2137 1.96 fvdl }
2138 1.96 fvdl
2139 1.96 fvdl saved_scbptr = ahc_inb(ahc, SCBPTR);
2140 1.96 fvdl /* Ensure that the hscbs down on the card match the new information */
2141 1.96 fvdl for (i = 0; i < ahc->scb_data->maxhscbs; i++) {
2142 1.96 fvdl struct hardware_scb *pending_hscb;
2143 1.96 fvdl u_int control;
2144 1.96 fvdl u_int scb_tag;
2145 1.96 fvdl
2146 1.96 fvdl ahc_outb(ahc, SCBPTR, i);
2147 1.96 fvdl scb_tag = ahc_inb(ahc, SCB_TAG);
2148 1.96 fvdl pending_scb = ahc_lookup_scb(ahc, scb_tag);
2149 1.96 fvdl if (pending_scb == NULL)
2150 1.96 fvdl continue;
2151 1.96 fvdl
2152 1.96 fvdl pending_hscb = pending_scb->hscb;
2153 1.96 fvdl control = ahc_inb(ahc, SCB_CONTROL);
2154 1.96 fvdl control &= ~(ULTRAENB|MK_MESSAGE);
2155 1.96 fvdl control |= pending_hscb->control & (ULTRAENB|MK_MESSAGE);
2156 1.96 fvdl ahc_outb(ahc, SCB_CONTROL, control);
2157 1.96 fvdl ahc_outb(ahc, SCB_SCSIRATE, pending_hscb->scsirate);
2158 1.96 fvdl ahc_outb(ahc, SCB_SCSIOFFSET, pending_hscb->scsioffset);
2159 1.96 fvdl }
2160 1.96 fvdl ahc_outb(ahc, SCBPTR, saved_scbptr);
2161 1.96 fvdl
2162 1.96 fvdl if (paused == 0)
2163 1.96 fvdl ahc_unpause(ahc);
2164 1.96 fvdl }
2165 1.96 fvdl
2166 1.96 fvdl /**************************** Pathing Information *****************************/
2167 1.96 fvdl static void
2168 1.96 fvdl ahc_fetch_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
2169 1.96 fvdl {
2170 1.96 fvdl u_int saved_scsiid;
2171 1.96 fvdl role_t role;
2172 1.96 fvdl int our_id;
2173 1.96 fvdl
2174 1.96 fvdl if (ahc_inb(ahc, SSTAT0) & TARGET)
2175 1.96 fvdl role = ROLE_TARGET;
2176 1.96 fvdl else
2177 1.96 fvdl role = ROLE_INITIATOR;
2178 1.96 fvdl
2179 1.96 fvdl if (role == ROLE_TARGET
2180 1.96 fvdl && (ahc->features & AHC_MULTI_TID) != 0
2181 1.96 fvdl && (ahc_inb(ahc, SEQ_FLAGS)
2182 1.96 fvdl & (CMDPHASE_PENDING|TARG_CMD_PENDING|NO_DISCONNECT)) != 0) {
2183 1.96 fvdl /* We were selected, so pull our id from TARGIDIN */
2184 1.96 fvdl our_id = ahc_inb(ahc, TARGIDIN) & OID;
2185 1.96 fvdl } else if ((ahc->features & AHC_ULTRA2) != 0)
2186 1.96 fvdl our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID;
2187 1.96 fvdl else
2188 1.96 fvdl our_id = ahc_inb(ahc, SCSIID) & OID;
2189 1.96 fvdl
2190 1.96 fvdl saved_scsiid = ahc_inb(ahc, SAVED_SCSIID);
2191 1.96 fvdl ahc_compile_devinfo(devinfo,
2192 1.96 fvdl our_id,
2193 1.96 fvdl SCSIID_TARGET(ahc, saved_scsiid),
2194 1.96 fvdl ahc_inb(ahc, SAVED_LUN),
2195 1.96 fvdl SCSIID_CHANNEL(ahc, saved_scsiid),
2196 1.96 fvdl role);
2197 1.96 fvdl }
2198 1.96 fvdl
2199 1.96 fvdl struct ahc_phase_table_entry*
2200 1.96 fvdl ahc_lookup_phase_entry(int phase)
2201 1.96 fvdl {
2202 1.96 fvdl struct ahc_phase_table_entry *entry;
2203 1.96 fvdl struct ahc_phase_table_entry *last_entry;
2204 1.96 fvdl
2205 1.96 fvdl /*
2206 1.96 fvdl * num_phases doesn't include the default entry which
2207 1.96 fvdl * will be returned if the phase doesn't match.
2208 1.96 fvdl */
2209 1.96 fvdl last_entry = &ahc_phase_table[num_phases];
2210 1.96 fvdl for (entry = ahc_phase_table; entry < last_entry; entry++) {
2211 1.96 fvdl if (phase == entry->phase)
2212 1.96 fvdl break;
2213 1.96 fvdl }
2214 1.96 fvdl return (entry);
2215 1.96 fvdl }
2216 1.96 fvdl
2217 1.96 fvdl void
2218 1.96 fvdl ahc_compile_devinfo(struct ahc_devinfo *devinfo, u_int our_id, u_int target,
2219 1.96 fvdl u_int lun, char channel, role_t role)
2220 1.96 fvdl {
2221 1.96 fvdl devinfo->our_scsiid = our_id;
2222 1.96 fvdl devinfo->target = target;
2223 1.96 fvdl devinfo->lun = lun;
2224 1.96 fvdl devinfo->target_offset = target;
2225 1.96 fvdl devinfo->channel = channel;
2226 1.96 fvdl devinfo->role = role;
2227 1.96 fvdl if (channel == 'B')
2228 1.96 fvdl devinfo->target_offset += 8;
2229 1.96 fvdl devinfo->target_mask = (0x01 << devinfo->target_offset);
2230 1.96 fvdl }
2231 1.96 fvdl
2232 1.96 fvdl void
2233 1.96 fvdl ahc_print_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
2234 1.96 fvdl {
2235 1.96 fvdl printf("%s:%c:%d:%d: ", ahc_name(ahc), devinfo->channel,
2236 1.96 fvdl devinfo->target, devinfo->lun);
2237 1.96 fvdl }
2238 1.96 fvdl
2239 1.96 fvdl static void
2240 1.96 fvdl ahc_scb_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
2241 1.96 fvdl struct scb *scb)
2242 1.96 fvdl {
2243 1.96 fvdl role_t role;
2244 1.96 fvdl int our_id;
2245 1.96 fvdl
2246 1.96 fvdl our_id = SCSIID_OUR_ID(scb->hscb->scsiid);
2247 1.96 fvdl role = ROLE_INITIATOR;
2248 1.96 fvdl if ((scb->flags & SCB_TARGET_SCB) != 0)
2249 1.96 fvdl role = ROLE_TARGET;
2250 1.96 fvdl ahc_compile_devinfo(devinfo, our_id, SCB_GET_TARGET(ahc, scb),
2251 1.96 fvdl SCB_GET_LUN(scb), SCB_GET_CHANNEL(ahc, scb), role);
2252 1.96 fvdl }
2253 1.96 fvdl
2254 1.96 fvdl
2255 1.96 fvdl /************************ Message Phase Processing ****************************/
2256 1.96 fvdl static void
2257 1.96 fvdl ahc_assert_atn(struct ahc_softc *ahc)
2258 1.96 fvdl {
2259 1.96 fvdl u_int scsisigo;
2260 1.96 fvdl
2261 1.96 fvdl scsisigo = ATNO;
2262 1.96 fvdl if ((ahc->features & AHC_DT) == 0)
2263 1.96 fvdl scsisigo |= ahc_inb(ahc, SCSISIGI);
2264 1.96 fvdl ahc_outb(ahc, SCSISIGO, scsisigo);
2265 1.96 fvdl }
2266 1.96 fvdl
2267 1.96 fvdl /*
2268 1.96 fvdl * When an initiator transaction with the MK_MESSAGE flag either reconnects
2269 1.96 fvdl * or enters the initial message out phase, we are interrupted. Fill our
2270 1.96 fvdl * outgoing message buffer with the appropriate message and beging handing
2271 1.96 fvdl * the message phase(s) manually.
2272 1.96 fvdl */
2273 1.96 fvdl static void
2274 1.96 fvdl ahc_setup_initiator_msgout(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
2275 1.96 fvdl struct scb *scb)
2276 1.96 fvdl {
2277 1.96 fvdl /*
2278 1.96 fvdl * To facilitate adding multiple messages together,
2279 1.96 fvdl * each routine should increment the index and len
2280 1.96 fvdl * variables instead of setting them explicitly.
2281 1.96 fvdl */
2282 1.96 fvdl ahc->msgout_index = 0;
2283 1.96 fvdl ahc->msgout_len = 0;
2284 1.96 fvdl
2285 1.96 fvdl if ((scb->flags & SCB_DEVICE_RESET) == 0
2286 1.96 fvdl && ahc_inb(ahc, MSG_OUT) == MSG_IDENTIFYFLAG) {
2287 1.96 fvdl u_int identify_msg;
2288 1.96 fvdl
2289 1.96 fvdl identify_msg = MSG_IDENTIFYFLAG | SCB_GET_LUN(scb);
2290 1.96 fvdl if ((scb->hscb->control & DISCENB) != 0)
2291 1.96 fvdl identify_msg |= MSG_IDENTIFY_DISCFLAG;
2292 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = identify_msg;
2293 1.96 fvdl ahc->msgout_len++;
2294 1.96 fvdl
2295 1.96 fvdl if ((scb->hscb->control & TAG_ENB) != 0) {
2296 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] =
2297 1.96 fvdl scb->hscb->control & (TAG_ENB|SCB_TAG_TYPE);
2298 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = scb->hscb->tag;
2299 1.96 fvdl ahc->msgout_len += 2;
2300 1.96 fvdl }
2301 1.96 fvdl }
2302 1.96 fvdl
2303 1.96 fvdl if (scb->flags & SCB_DEVICE_RESET) {
2304 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_BUS_DEV_RESET;
2305 1.96 fvdl ahc->msgout_len++;
2306 1.96 fvdl ahc_print_path(ahc, scb);
2307 1.96 fvdl printf("Bus Device Reset Message Sent\n");
2308 1.96 fvdl /*
2309 1.96 fvdl * Clear our selection hardware in advance of
2310 1.96 fvdl * the busfree. We may have an entry in the waiting
2311 1.96 fvdl * Q for this target, and we don't want to go about
2312 1.96 fvdl * selecting while we handle the busfree and blow it
2313 1.96 fvdl * away.
2314 1.96 fvdl */
2315 1.96 fvdl ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO));
2316 1.96 fvdl } else if ((scb->flags & SCB_ABORT) != 0) {
2317 1.96 fvdl if ((scb->hscb->control & TAG_ENB) != 0)
2318 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_ABORT_TAG;
2319 1.96 fvdl else
2320 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_ABORT;
2321 1.96 fvdl ahc->msgout_len++;
2322 1.96 fvdl ahc_print_path(ahc, scb);
2323 1.96 fvdl printf("Abort%s Message Sent\n",
2324 1.96 fvdl (scb->hscb->control & TAG_ENB) != 0 ? " Tag" : "");
2325 1.96 fvdl /*
2326 1.96 fvdl * Clear our selection hardware in advance of
2327 1.96 fvdl * the busfree. We may have an entry in the waiting
2328 1.96 fvdl * Q for this target, and we don't want to go about
2329 1.96 fvdl * selecting while we handle the busfree and blow it
2330 1.96 fvdl * away.
2331 1.96 fvdl */
2332 1.96 fvdl ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO));
2333 1.96 fvdl } else if ((scb->flags & (SCB_AUTO_NEGOTIATE|SCB_NEGOTIATE)) != 0) {
2334 1.96 fvdl ahc_build_transfer_msg(ahc, devinfo);
2335 1.96 fvdl } else {
2336 1.96 fvdl printf("ahc_intr: AWAITING_MSG for an SCB that "
2337 1.96 fvdl "does not have a waiting message\n");
2338 1.96 fvdl printf("SCSIID = %x, target_mask = %x\n", scb->hscb->scsiid,
2339 1.96 fvdl devinfo->target_mask);
2340 1.96 fvdl panic("SCB = %d, SCB Control = %x, MSG_OUT = %x "
2341 1.96 fvdl "SCB flags = %x", scb->hscb->tag, scb->hscb->control,
2342 1.96 fvdl ahc_inb(ahc, MSG_OUT), scb->flags);
2343 1.96 fvdl }
2344 1.96 fvdl
2345 1.96 fvdl /*
2346 1.96 fvdl * Clear the MK_MESSAGE flag from the SCB so we aren't
2347 1.96 fvdl * asked to send this message again.
2348 1.96 fvdl */
2349 1.96 fvdl ahc_outb(ahc, SCB_CONTROL, ahc_inb(ahc, SCB_CONTROL) & ~MK_MESSAGE);
2350 1.96 fvdl scb->hscb->control &= ~MK_MESSAGE;
2351 1.96 fvdl ahc->msgout_index = 0;
2352 1.96 fvdl ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
2353 1.96 fvdl }
2354 1.96 fvdl
2355 1.96 fvdl /*
2356 1.96 fvdl * Build an appropriate transfer negotiation message for the
2357 1.96 fvdl * currently active target.
2358 1.96 fvdl */
2359 1.96 fvdl static void
2360 1.96 fvdl ahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
2361 1.96 fvdl {
2362 1.96 fvdl /*
2363 1.96 fvdl * We need to initiate transfer negotiations.
2364 1.96 fvdl * If our current and goal settings are identical,
2365 1.96 fvdl * we want to renegotiate due to a check condition.
2366 1.96 fvdl */
2367 1.96 fvdl struct ahc_initiator_tinfo *tinfo;
2368 1.96 fvdl struct ahc_tmode_tstate *tstate;
2369 1.96 fvdl struct ahc_syncrate *rate;
2370 1.96 fvdl int dowide;
2371 1.96 fvdl int dosync;
2372 1.96 fvdl int doppr;
2373 1.96 fvdl u_int period;
2374 1.96 fvdl u_int ppr_options;
2375 1.96 fvdl u_int offset;
2376 1.96 fvdl
2377 1.96 fvdl tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
2378 1.96 fvdl devinfo->target, &tstate);
2379 1.96 fvdl /*
2380 1.96 fvdl * Filter our period based on the current connection.
2381 1.96 fvdl * If we can't perform DT transfers on this segment (not in LVD
2382 1.96 fvdl * mode for instance), then our decision to issue a PPR message
2383 1.96 fvdl * may change.
2384 1.96 fvdl */
2385 1.96 fvdl period = tinfo->goal.period;
2386 1.96 fvdl ppr_options = tinfo->goal.ppr_options;
2387 1.96 fvdl /* Target initiated PPR is not allowed in the SCSI spec */
2388 1.96 fvdl if (devinfo->role == ROLE_TARGET)
2389 1.96 fvdl ppr_options = 0;
2390 1.96 fvdl rate = ahc_devlimited_syncrate(ahc, tinfo, &period,
2391 1.96 fvdl &ppr_options, devinfo->role);
2392 1.96 fvdl dowide = tinfo->curr.width != tinfo->goal.width;
2393 1.96 fvdl dosync = tinfo->curr.period != period;
2394 1.96 fvdl /*
2395 1.96 fvdl * Only use PPR if we have options that need it, even if the device
2396 1.96 fvdl * claims to support it. There might be an expander in the way
2397 1.96 fvdl * that doesn't.
2398 1.96 fvdl */
2399 1.96 fvdl doppr = ppr_options != 0;
2400 1.96 fvdl
2401 1.96 fvdl if (!dowide && !dosync && !doppr) {
2402 1.96 fvdl dowide = tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT;
2403 1.96 fvdl dosync = tinfo->goal.offset != 0;
2404 1.96 fvdl }
2405 1.96 fvdl
2406 1.96 fvdl if (!dowide && !dosync && !doppr) {
2407 1.96 fvdl /*
2408 1.96 fvdl * Force async with a WDTR message if we have a wide bus,
2409 1.96 fvdl * or just issue an SDTR with a 0 offset.
2410 1.96 fvdl */
2411 1.96 fvdl if ((ahc->features & AHC_WIDE) != 0)
2412 1.96 fvdl dowide = 1;
2413 1.96 fvdl else
2414 1.96 fvdl dosync = 1;
2415 1.96 fvdl
2416 1.96 fvdl if (bootverbose) {
2417 1.96 fvdl ahc_print_devinfo(ahc, devinfo);
2418 1.96 fvdl printf("Ensuring async\n");
2419 1.96 fvdl }
2420 1.96 fvdl }
2421 1.96 fvdl
2422 1.96 fvdl /* Target initiated PPR is not allowed in the SCSI spec */
2423 1.96 fvdl if (devinfo->role == ROLE_TARGET)
2424 1.96 fvdl doppr = 0;
2425 1.96 fvdl
2426 1.96 fvdl /*
2427 1.96 fvdl * Both the PPR message and SDTR message require the
2428 1.96 fvdl * goal syncrate to be limited to what the target device
2429 1.96 fvdl * is capable of handling (based on whether an LVD->SE
2430 1.96 fvdl * expander is on the bus), so combine these two cases.
2431 1.96 fvdl * Regardless, guarantee that if we are using WDTR and SDTR
2432 1.96 fvdl * messages that WDTR comes first.
2433 1.96 fvdl */
2434 1.96 fvdl if (doppr || (dosync && !dowide)) {
2435 1.96 fvdl
2436 1.96 fvdl offset = tinfo->goal.offset;
2437 1.96 fvdl ahc_validate_offset(ahc, tinfo, rate, &offset,
2438 1.96 fvdl doppr ? tinfo->goal.width
2439 1.96 fvdl : tinfo->curr.width,
2440 1.96 fvdl devinfo->role);
2441 1.96 fvdl if (doppr) {
2442 1.96 fvdl ahc_construct_ppr(ahc, devinfo, period, offset,
2443 1.96 fvdl tinfo->goal.width, ppr_options);
2444 1.96 fvdl } else {
2445 1.96 fvdl ahc_construct_sdtr(ahc, devinfo, period, offset);
2446 1.96 fvdl }
2447 1.96 fvdl } else {
2448 1.96 fvdl ahc_construct_wdtr(ahc, devinfo, tinfo->goal.width);
2449 1.96 fvdl }
2450 1.96 fvdl }
2451 1.96 fvdl
2452 1.96 fvdl /*
2453 1.96 fvdl * Build a synchronous negotiation message in our message
2454 1.96 fvdl * buffer based on the input parameters.
2455 1.96 fvdl */
2456 1.96 fvdl static void
2457 1.96 fvdl ahc_construct_sdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
2458 1.96 fvdl u_int period, u_int offset)
2459 1.96 fvdl {
2460 1.96 fvdl if (offset == 0)
2461 1.96 fvdl period = AHC_ASYNC_XFER_PERIOD;
2462 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED;
2463 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_SDTR_LEN;
2464 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_SDTR;
2465 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = period;
2466 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = offset;
2467 1.96 fvdl ahc->msgout_len += 5;
2468 1.96 fvdl if (bootverbose) {
2469 1.96 fvdl printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n",
2470 1.96 fvdl ahc_name(ahc), devinfo->channel, devinfo->target,
2471 1.96 fvdl devinfo->lun, period, offset);
2472 1.96 fvdl }
2473 1.96 fvdl }
2474 1.96 fvdl
2475 1.96 fvdl /*
2476 1.96 fvdl * Build a wide negotiation message in our message
2477 1.96 fvdl * buffer based on the input parameters.
2478 1.96 fvdl */
2479 1.96 fvdl static void
2480 1.96 fvdl ahc_construct_wdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
2481 1.96 fvdl u_int bus_width)
2482 1.96 fvdl {
2483 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED;
2484 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_WDTR_LEN;
2485 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_WDTR;
2486 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = bus_width;
2487 1.96 fvdl ahc->msgout_len += 4;
2488 1.96 fvdl if (bootverbose) {
2489 1.96 fvdl printf("(%s:%c:%d:%d): Sending WDTR %x\n",
2490 1.96 fvdl ahc_name(ahc), devinfo->channel, devinfo->target,
2491 1.96 fvdl devinfo->lun, bus_width);
2492 1.96 fvdl }
2493 1.96 fvdl }
2494 1.96 fvdl
2495 1.96 fvdl /*
2496 1.96 fvdl * Build a parallel protocol request message in our message
2497 1.96 fvdl * buffer based on the input parameters.
2498 1.96 fvdl */
2499 1.96 fvdl static void
2500 1.96 fvdl ahc_construct_ppr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
2501 1.96 fvdl u_int period, u_int offset, u_int bus_width,
2502 1.96 fvdl u_int ppr_options)
2503 1.96 fvdl {
2504 1.96 fvdl if (offset == 0)
2505 1.96 fvdl period = AHC_ASYNC_XFER_PERIOD;
2506 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED;
2507 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_PPR_LEN;
2508 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_PPR;
2509 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = period;
2510 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = 0;
2511 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = offset;
2512 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = bus_width;
2513 1.96 fvdl ahc->msgout_buf[ahc->msgout_index++] = ppr_options;
2514 1.96 fvdl ahc->msgout_len += 8;
2515 1.96 fvdl if (bootverbose) {
2516 1.96 fvdl printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, "
2517 1.96 fvdl "offset %x, ppr_options %x\n", ahc_name(ahc),
2518 1.96 fvdl devinfo->channel, devinfo->target, devinfo->lun,
2519 1.96 fvdl bus_width, period, offset, ppr_options);
2520 1.96 fvdl }
2521 1.96 fvdl }
2522 1.96 fvdl
2523 1.96 fvdl /*
2524 1.96 fvdl * Clear any active message state.
2525 1.96 fvdl */
2526 1.96 fvdl static void
2527 1.96 fvdl ahc_clear_msg_state(struct ahc_softc *ahc)
2528 1.96 fvdl {
2529 1.96 fvdl ahc->msgout_len = 0;
2530 1.96 fvdl ahc->msgin_index = 0;
2531 1.96 fvdl ahc->msg_type = MSG_TYPE_NONE;
2532 1.96 fvdl if ((ahc_inb(ahc, SCSISIGI) & ATNI) != 0) {
2533 1.96 fvdl /*
2534 1.96 fvdl * The target didn't care to respond to our
2535 1.96 fvdl * message request, so clear ATN.
2536 1.96 fvdl */
2537 1.96 fvdl ahc_outb(ahc, CLRSINT1, CLRATNO);
2538 1.96 fvdl }
2539 1.96 fvdl ahc_outb(ahc, MSG_OUT, MSG_NOOP);
2540 1.96 fvdl ahc_outb(ahc, SEQ_FLAGS2,
2541 1.96 fvdl ahc_inb(ahc, SEQ_FLAGS2) & ~TARGET_MSG_PENDING);
2542 1.96 fvdl }
2543 1.96 fvdl
2544 1.96 fvdl static void
2545 1.96 fvdl ahc_handle_proto_violation(struct ahc_softc *ahc)
2546 1.96 fvdl {
2547 1.96 fvdl struct ahc_devinfo devinfo;
2548 1.96 fvdl struct scb *scb;
2549 1.96 fvdl u_int scbid;
2550 1.96 fvdl u_int seq_flags;
2551 1.96 fvdl u_int curphase;
2552 1.96 fvdl u_int lastphase;
2553 1.96 fvdl int found;
2554 1.96 fvdl
2555 1.96 fvdl ahc_fetch_devinfo(ahc, &devinfo);
2556 1.96 fvdl scbid = ahc_inb(ahc, SCB_TAG);
2557 1.96 fvdl scb = ahc_lookup_scb(ahc, scbid);
2558 1.96 fvdl seq_flags = ahc_inb(ahc, SEQ_FLAGS);
2559 1.96 fvdl curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;
2560 1.96 fvdl lastphase = ahc_inb(ahc, LASTPHASE);
2561 1.96 fvdl if ((seq_flags & NOT_IDENTIFIED) != 0) {
2562 1.96 fvdl
2563 1.96 fvdl /*
2564 1.96 fvdl * The reconnecting target either did not send an
2565 1.96 fvdl * identify message, or did, but we didn't find an SCB
2566 1.96 fvdl * to match.
2567 1.96 fvdl */
2568 1.96 fvdl ahc_print_devinfo(ahc, &devinfo);
2569 1.96 fvdl printf("Target did not send an IDENTIFY message. "
2570 1.96 fvdl "LASTPHASE = 0x%x.\n", lastphase);
2571 1.96 fvdl scb = NULL;
2572 1.96 fvdl } else if (scb == NULL) {
2573 1.96 fvdl /*
2574 1.96 fvdl * We don't seem to have an SCB active for this
2575 1.96 fvdl * transaction. Print an error and reset the bus.
2576 1.96 fvdl */
2577 1.96 fvdl ahc_print_devinfo(ahc, &devinfo);
2578 1.96 fvdl printf("No SCB found during protocol violation\n");
2579 1.96 fvdl goto proto_violation_reset;
2580 1.96 fvdl } else {
2581 1.96 fvdl ahc_set_transaction_status(scb, CAM_SEQUENCE_FAIL);
2582 1.96 fvdl if ((seq_flags & NO_CDB_SENT) != 0) {
2583 1.96 fvdl ahc_print_path(ahc, scb);
2584 1.96 fvdl printf("No or incomplete CDB sent to device.\n");
2585 1.96 fvdl } else if ((ahc_inb(ahc, SCB_CONTROL) & STATUS_RCVD) == 0) {
2586 1.96 fvdl /*
2587 1.96 fvdl * The target never bothered to provide status to
2588 1.96 fvdl * us prior to completing the command. Since we don't
2589 1.96 fvdl * know the disposition of this command, we must attempt
2590 1.96 fvdl * to abort it. Assert ATN and prepare to send an abort
2591 1.96 fvdl * message.
2592 1.96 fvdl */
2593 1.96 fvdl ahc_print_path(ahc, scb);
2594 1.96 fvdl printf("Completed command without status.\n");
2595 1.96 fvdl } else {
2596 1.96 fvdl ahc_print_path(ahc, scb);
2597 1.96 fvdl printf("Unknown protocol violation.\n");
2598 1.96 fvdl ahc_dump_card_state(ahc);
2599 1.96 fvdl }
2600 1.96 fvdl }
2601 1.96 fvdl if ((lastphase & ~P_DATAIN_DT) == 0
2602 1.96 fvdl || lastphase == P_COMMAND) {
2603 1.96 fvdl proto_violation_reset:
2604 1.96 fvdl /*
2605 1.96 fvdl * Target either went directly to data/command
2606 1.96 fvdl * phase or didn't respond to our ATN.
2607 1.96 fvdl * The only safe thing to do is to blow
2608 1.96 fvdl * it away with a bus reset.
2609 1.96 fvdl */
2610 1.96 fvdl found = ahc_reset_channel(ahc, 'A', TRUE);
2611 1.96 fvdl printf("%s: Issued Channel %c Bus Reset. "
2612 1.96 fvdl "%d SCBs aborted\n", ahc_name(ahc), 'A', found);
2613 1.96 fvdl } else {
2614 1.96 fvdl /*
2615 1.96 fvdl * Leave the selection hardware off in case
2616 1.96 fvdl * this abort attempt will affect yet to
2617 1.96 fvdl * be sent commands.
2618 1.96 fvdl */
2619 1.96 fvdl ahc_outb(ahc, SCSISEQ,
2620 1.96 fvdl ahc_inb(ahc, SCSISEQ) & ~ENSELO);
2621 1.96 fvdl ahc_assert_atn(ahc);
2622 1.96 fvdl ahc_outb(ahc, MSG_OUT, HOST_MSG);
2623 1.96 fvdl if (scb == NULL) {
2624 1.96 fvdl ahc_print_devinfo(ahc, &devinfo);
2625 1.96 fvdl ahc->msgout_buf[0] = MSG_ABORT_TASK;
2626 1.96 fvdl ahc->msgout_len = 1;
2627 1.96 fvdl ahc->msgout_index = 0;
2628 1.96 fvdl ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
2629 1.96 fvdl } else {
2630 1.96 fvdl ahc_print_path(ahc, scb);
2631 1.96 fvdl scb->flags |= SCB_ABORT;
2632 1.96 fvdl }
2633 1.96 fvdl printf("Protocol violation %s. Attempting to abort.\n",
2634 1.96 fvdl ahc_lookup_phase_entry(curphase)->phasemsg);
2635 1.96 fvdl }
2636 1.96 fvdl }
2637 1.96 fvdl
2638 1.96 fvdl /*
2639 1.96 fvdl * Manual message loop handler.
2640 1.96 fvdl */
2641 1.96 fvdl static void
2642 1.96 fvdl ahc_handle_message_phase(struct ahc_softc *ahc)
2643 1.96 fvdl {
2644 1.96 fvdl struct ahc_devinfo devinfo;
2645 1.96 fvdl u_int bus_phase;
2646 1.96 fvdl int end_session;
2647 1.96 fvdl
2648 1.96 fvdl ahc_fetch_devinfo(ahc, &devinfo);
2649 1.96 fvdl end_session = FALSE;
2650 1.96 fvdl bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;
2651 1.96 fvdl
2652 1.96 fvdl reswitch:
2653 1.96 fvdl switch (ahc->msg_type) {
2654 1.96 fvdl case MSG_TYPE_INITIATOR_MSGOUT:
2655 1.96 fvdl {
2656 1.96 fvdl int lastbyte;
2657 1.96 fvdl int phasemis;
2658 1.96 fvdl int msgdone;
2659 1.96 fvdl
2660 1.96 fvdl if (ahc->msgout_len == 0)
2661 1.96 fvdl panic("HOST_MSG_LOOP interrupt with no active message");
2662 1.96 fvdl
2663 1.96 fvdl #ifdef AHC_DEBUG
2664 1.96 fvdl if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) {
2665 1.96 fvdl ahc_print_devinfo(ahc, &devinfo);
2666 1.96 fvdl printf("INITIATOR_MSG_OUT");
2667 1.96 fvdl }
2668 1.96 fvdl #endif
2669 1.96 fvdl phasemis = bus_phase != P_MESGOUT;
2670 1.96 fvdl if (phasemis) {
2671 1.96 fvdl #ifdef AHC_DEBUG
2672 1.96 fvdl if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) {
2673 1.96 fvdl printf(" PHASEMIS %s\n",
2674 1.96 fvdl ahc_lookup_phase_entry(bus_phase)
2675 1.96 fvdl ->phasemsg);
2676 1.96 fvdl }
2677 1.96 fvdl #endif
2678 1.96 fvdl if (bus_phase == P_MESGIN) {
2679 1.96 fvdl /*
2680 1.96 fvdl * Change gears and see if
2681 1.96 fvdl * this messages is of interest to
2682 1.96 fvdl * us or should be passed back to
2683 1.96 fvdl * the sequencer.
2684 1.96 fvdl */
2685 1.96 fvdl ahc_outb(ahc, CLRSINT1, CLRATNO);
2686 1.96 fvdl ahc->send_msg_perror = FALSE;
2687 1.96 fvdl ahc->msg_type = MSG_TYPE_INITIATOR_MSGIN;
2688 1.96 fvdl ahc->msgin_index = 0;
2689 1.96 fvdl goto reswitch;
2690 1.96 fvdl }
2691 1.96 fvdl end_session = TRUE;
2692 1.96 fvdl break;
2693 1.96 fvdl }
2694 1.96 fvdl
2695 1.96 fvdl if (ahc->send_msg_perror) {
2696 1.96 fvdl ahc_outb(ahc, CLRSINT1, CLRATNO);
2697 1.96 fvdl ahc_outb(ahc, CLRSINT1, CLRREQINIT);
2698 1.96 fvdl #ifdef AHC_DEBUG
2699 1.96 fvdl if ((ahc_debug & AHC_SHOW_MESSAGES) != 0)
2700 1.96 fvdl printf(" byte 0x%x\n", ahc->send_msg_perror);
2701 1.96 fvdl #endif
2702 1.96 fvdl ahc_outb(ahc, SCSIDATL, MSG_PARITY_ERROR);
2703 1.96 fvdl break;
2704 1.96 fvdl }
2705 1.96 fvdl
2706 1.96 fvdl msgdone = ahc->msgout_index == ahc->msgout_len;
2707 1.96 fvdl if (msgdone) {
2708 1.96 fvdl /*
2709 1.96 fvdl * The target has requested a retry.
2710 1.96 fvdl * Re-assert ATN, reset our message index to
2711 1.96 fvdl * 0, and try again.
2712 1.96 fvdl */
2713 1.96 fvdl ahc->msgout_index = 0;
2714 1.96 fvdl ahc_assert_atn(ahc);
2715 1.96 fvdl }
2716 1.96 fvdl
2717 1.96 fvdl lastbyte = ahc->msgout_index == (ahc->msgout_len - 1);
2718 1.96 fvdl if (lastbyte) {
2719 1.96 fvdl /* Last byte is signified by dropping ATN */
2720 1.96 fvdl ahc_outb(ahc, CLRSINT1, CLRATNO);
2721 1.96 fvdl }
2722 1.96 fvdl
2723 1.96 fvdl /*
2724 1.96 fvdl * Clear our interrupt status and present
2725 1.96 fvdl * the next byte on the bus.
2726 1.96 fvdl */
2727 1.96 fvdl ahc_outb(ahc, CLRSINT1, CLRREQINIT);
2728 1.96 fvdl #ifdef AHC_DEBUG
2729 1.96 fvdl if ((ahc_debug & AHC_SHOW_MESSAGES) != 0)
2730 1.96 fvdl printf(" byte 0x%x\n",
2731 1.96 fvdl ahc->msgout_buf[ahc->msgout_index]);
2732 1.96 fvdl #endif
2733 1.96 fvdl ahc_outb(ahc, SCSIDATL, ahc->msgout_buf[ahc->msgout_index++]);
2734 1.96 fvdl break;
2735 1.42 fvdl }
2736 1.96 fvdl case MSG_TYPE_INITIATOR_MSGIN:
2737 1.96 fvdl {
2738 1.96 fvdl int phasemis;
2739 1.96 fvdl int message_done;
2740 1.96 fvdl
2741 1.96 fvdl #ifdef AHC_DEBUG
2742 1.96 fvdl if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) {
2743 1.96 fvdl ahc_print_devinfo(ahc, &devinfo);
2744 1.96 fvdl printf("INITIATOR_MSG_IN");
2745 1.96 fvdl }
2746 1.96 fvdl #endif
2747 1.96 fvdl phasemis = bus_phase != P_MESGIN;
2748 1.96 fvdl if (phasemis) {
2749 1.96 fvdl #ifdef AHC_DEBUG
2750 1.96 fvdl if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) {
2751 1.96 fvdl printf(" PHASEMIS %s\n",
2752 1.96 fvdl ahc_lookup_phase_entry(bus_phase)
2753 1.96 fvdl ->phasemsg);
2754 1.96 fvdl }
2755 1.96 fvdl #endif
2756 1.96 fvdl ahc->msgin_index = 0;
2757 1.96 fvdl if (bus_phase == P_MESGOUT
2758 1.96 fvdl && (ahc->send_msg_perror == TRUE
2759 1.96 fvdl || (ahc->msgout_len != 0
2760 1.96 fvdl && ahc->msgout_index == 0))) {
2761 1.96 fvdl ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
2762 1.96 fvdl goto reswitch;
2763 1.96 fvdl }
2764 1.96 fvdl end_session = TRUE;
2765 1.96 fvdl break;
2766 1.96 fvdl }
2767 1.42 fvdl
2768 1.96 fvdl /* Pull the byte in without acking it */
2769 1.96 fvdl ahc->msgin_buf[ahc->msgin_index] = ahc_inb(ahc, SCSIBUSL);
2770 1.96 fvdl #ifdef AHC_DEBUG
2771 1.96 fvdl if ((ahc_debug & AHC_SHOW_MESSAGES) != 0)
2772 1.96 fvdl printf(" byte 0x%x\n",
2773 1.96 fvdl ahc->msgin_buf[ahc->msgin_index]);
2774 1.96 fvdl #endif
2775 1.42 fvdl
2776 1.96 fvdl message_done = ahc_parse_msg(ahc, &devinfo);
2777 1.42 fvdl
2778 1.96 fvdl if (message_done) {
2779 1.96 fvdl /*
2780 1.96 fvdl * Clear our incoming message buffer in case there
2781 1.96 fvdl * is another message following this one.
2782 1.96 fvdl */
2783 1.96 fvdl ahc->msgin_index = 0;
2784 1.42 fvdl
2785 1.96 fvdl /*
2786 1.96 fvdl * If this message illicited a response,
2787 1.96 fvdl * assert ATN so the target takes us to the
2788 1.96 fvdl * message out phase.
2789 1.96 fvdl */
2790 1.96 fvdl if (ahc->msgout_len != 0) {
2791 1.42 fvdl #ifdef AHC_DEBUG
2792 1.96 fvdl if ((ahc_debug & AHC_SHOW_MESSAGES) != 0) {
2793 1.96 fvdl ahc_print_devinfo(ahc, &devinfo);
2794 1.96 fvdl printf("Asserting ATN for response\n");
2795 1.96 fvdl }
2796 1.42 fvdl #endif
2797 1.96 fvdl ahc_assert_atn(ahc);
2798 1.96 fvdl }
2799 1.96 fvdl } else
2800 1.96 fvdl ahc->msgin_index++;
2801 1.42 fvdl
2802 1.96 fvdl if (message_done == MSGLOOP_TERMINATED) {
2803 1.96 fvdl end_session = TRUE;
2804 1.96 fvdl } else {
2805 1.96 fvdl /* Ack the byte */
2806 1.96 fvdl ahc_outb(ahc, CLRSINT1, CLRREQINIT);
2807 1.96 fvdl ahc_inb(ahc, SCSIDATL);
2808 1.96 fvdl }
2809 1.42 fvdl break;
2810 1.42 fvdl }
2811 1.96 fvdl case MSG_TYPE_TARGET_MSGIN:
2812 1.96 fvdl {
2813 1.96 fvdl int msgdone;
2814 1.96 fvdl int msgout_request;
2815 1.42 fvdl
2816 1.96 fvdl if (ahc->msgout_len == 0)
2817 1.96 fvdl panic("Target MSGIN with no active message");
2818 1.42 fvdl
2819 1.96 fvdl /*
2820 1.96 fvdl * If we interrupted a mesgout session, the initiator
2821 1.96 fvdl * will not know this until our first REQ. So, we
2822 1.96 fvdl * only honor mesgout requests after we've sent our
2823 1.96 fvdl * first byte.
2824 1.96 fvdl */
2825 1.96 fvdl if ((ahc_inb(ahc, SCSISIGI) & ATNI) != 0
2826 1.96 fvdl && ahc->msgout_index > 0)
2827 1.96 fvdl msgout_request = TRUE;
2828 1.96 fvdl else
2829 1.96 fvdl msgout_request = FALSE;
2830 1.42 fvdl
2831 1.96 fvdl if (msgout_request) {
2832 1.42 fvdl
2833 1.96 fvdl /*
2834 1.96 fvdl * Change gears and see if
2835 1.96 fvdl * this messages is of interest to
2836 1.96 fvdl * us or should be passed back to
2837 1.96 fvdl * the sequencer.
2838 1.96 fvdl */
2839 1.96 fvdl ahc->msg_type = MSG_TYPE_TARGET_MSGOUT;
2840 1.96 fvdl ahc_outb(ahc, SCSISIGO, P_MESGOUT | BSYO);
2841 1.96 fvdl ahc->msgin_index = 0;
2842 1.96 fvdl /* Dummy read to REQ for first byte */
2843 1.96 fvdl ahc_inb(ahc, SCSIDATL);
2844 1.96 fvdl ahc_outb(ahc, SXFRCTL0,
2845 1.96 fvdl ahc_inb(ahc, SXFRCTL0) | SPIOEN);
2846 1.96 fvdl break;
2847 1.96 fvdl }
2848 1.42 fvdl
2849 1.96 fvdl msgdone = ahc->msgout_index == ahc->msgout_len;
2850 1.96 fvdl if (msgdone) {
2851 1.96 fvdl ahc_outb(ahc, SXFRCTL0,
2852 1.96 fvdl ahc_inb(ahc, SXFRCTL0) & ~SPIOEN);
2853 1.96 fvdl end_session = TRUE;
2854 1.96 fvdl break;
2855 1.96 fvdl }
2856 1.42 fvdl
2857 1.96 fvdl /*
2858 1.96 fvdl * Present the next byte on the bus.
2859 1.96 fvdl */
2860 1.96 fvdl ahc_outb(ahc, SXFRCTL0, ahc_inb(ahc, SXFRCTL0) | SPIOEN);
2861 1.96 fvdl ahc_outb(ahc, SCSIDATL, ahc->msgout_buf[ahc->msgout_index++]);
2862 1.96 fvdl break;
2863 1.96 fvdl }
2864 1.96 fvdl case MSG_TYPE_TARGET_MSGOUT:
2865 1.96 fvdl {
2866 1.96 fvdl int lastbyte;
2867 1.96 fvdl int msgdone;
2868 1.42 fvdl
2869 1.96 fvdl /*
2870 1.96 fvdl * The initiator signals that this is
2871 1.96 fvdl * the last byte by dropping ATN.
2872 1.96 fvdl */
2873 1.96 fvdl lastbyte = (ahc_inb(ahc, SCSISIGI) & ATNI) == 0;
2874 1.42 fvdl
2875 1.96 fvdl /*
2876 1.96 fvdl * Read the latched byte, but turn off SPIOEN first
2877 1.96 fvdl * so that we don't inadvertently cause a REQ for the
2878 1.96 fvdl * next byte.
2879 1.96 fvdl */
2880 1.96 fvdl ahc_outb(ahc, SXFRCTL0, ahc_inb(ahc, SXFRCTL0) & ~SPIOEN);
2881 1.96 fvdl ahc->msgin_buf[ahc->msgin_index] = ahc_inb(ahc, SCSIDATL);
2882 1.96 fvdl msgdone = ahc_parse_msg(ahc, &devinfo);
2883 1.96 fvdl if (msgdone == MSGLOOP_TERMINATED) {
2884 1.96 fvdl /*
2885 1.96 fvdl * The message is *really* done in that it caused
2886 1.96 fvdl * us to go to bus free. The sequencer has already
2887 1.96 fvdl * been reset at this point, so pull the ejection
2888 1.96 fvdl * handle.
2889 1.96 fvdl */
2890 1.96 fvdl return;
2891 1.96 fvdl }
2892 1.96 fvdl
2893 1.96 fvdl ahc->msgin_index++;
2894 1.42 fvdl
2895 1.96 fvdl /*
2896 1.96 fvdl * XXX Read spec about initiator dropping ATN too soon
2897 1.96 fvdl * and use msgdone to detect it.
2898 1.96 fvdl */
2899 1.96 fvdl if (msgdone == MSGLOOP_MSGCOMPLETE) {
2900 1.96 fvdl ahc->msgin_index = 0;
2901 1.42 fvdl
2902 1.96 fvdl /*
2903 1.96 fvdl * If this message illicited a response, transition
2904 1.96 fvdl * to the Message in phase and send it.
2905 1.96 fvdl */
2906 1.96 fvdl if (ahc->msgout_len != 0) {
2907 1.96 fvdl ahc_outb(ahc, SCSISIGO, P_MESGIN | BSYO);
2908 1.96 fvdl ahc_outb(ahc, SXFRCTL0,
2909 1.96 fvdl ahc_inb(ahc, SXFRCTL0) | SPIOEN);
2910 1.96 fvdl ahc->msg_type = MSG_TYPE_TARGET_MSGIN;
2911 1.96 fvdl ahc->msgin_index = 0;
2912 1.96 fvdl break;
2913 1.96 fvdl }
2914 1.96 fvdl }
2915 1.42 fvdl
2916 1.96 fvdl if (lastbyte)
2917 1.96 fvdl end_session = TRUE;
2918 1.96 fvdl else {
2919 1.96 fvdl /* Ask for the next byte. */
2920 1.96 fvdl ahc_outb(ahc, SXFRCTL0,
2921 1.96 fvdl ahc_inb(ahc, SXFRCTL0) | SPIOEN);
2922 1.96 fvdl }
2923 1.42 fvdl
2924 1.96 fvdl break;
2925 1.96 fvdl }
2926 1.96 fvdl default:
2927 1.96 fvdl panic("Unknown REQINIT message type");
2928 1.96 fvdl }
2929 1.42 fvdl
2930 1.96 fvdl if (end_session) {
2931 1.96 fvdl ahc_clear_msg_state(ahc);
2932 1.96 fvdl ahc_outb(ahc, RETURN_1, EXIT_MSG_LOOP);
2933 1.96 fvdl } else
2934 1.96 fvdl ahc_outb(ahc, RETURN_1, CONT_MSG_LOOP);
2935 1.42 fvdl }
2936 1.42 fvdl
2937 1.96 fvdl /*
2938 1.96 fvdl * See if we sent a particular extended message to the target.
2939 1.96 fvdl * If "full" is true, return true only if the target saw the full
2940 1.96 fvdl * message. If "full" is false, return true if the target saw at
2941 1.96 fvdl * least the first byte of the message.
2942 1.96 fvdl */
2943 1.42 fvdl static int
2944 1.96 fvdl ahc_sent_msg(struct ahc_softc *ahc, ahc_msgtype type, u_int msgval, int full)
2945 1.42 fvdl {
2946 1.96 fvdl int found;
2947 1.96 fvdl u_int index;
2948 1.42 fvdl
2949 1.96 fvdl found = FALSE;
2950 1.96 fvdl index = 0;
2951 1.42 fvdl
2952 1.96 fvdl while (index < ahc->msgout_len) {
2953 1.96 fvdl if (ahc->msgout_buf[index] == MSG_EXTENDED) {
2954 1.96 fvdl u_int end_index;
2955 1.42 fvdl
2956 1.96 fvdl end_index = index + 1 + ahc->msgout_buf[index + 1];
2957 1.96 fvdl if (ahc->msgout_buf[index+2] == msgval
2958 1.96 fvdl && type == AHCMSG_EXT) {
2959 1.42 fvdl
2960 1.96 fvdl if (full) {
2961 1.96 fvdl if (ahc->msgout_index > end_index)
2962 1.96 fvdl found = TRUE;
2963 1.96 fvdl } else if (ahc->msgout_index > index)
2964 1.96 fvdl found = TRUE;
2965 1.96 fvdl }
2966 1.96 fvdl index = end_index;
2967 1.96 fvdl } else if (ahc->msgout_buf[index] >= MSG_SIMPLE_TASK
2968 1.96 fvdl && ahc->msgout_buf[index] <= MSG_IGN_WIDE_RESIDUE) {
2969 1.42 fvdl
2970 1.96 fvdl /* Skip tag type and tag id or residue param*/
2971 1.96 fvdl index += 2;
2972 1.96 fvdl } else {
2973 1.96 fvdl /* Single byte message */
2974 1.96 fvdl if (type == AHCMSG_1B
2975 1.96 fvdl && ahc->msgout_buf[index] == msgval
2976 1.96 fvdl && ahc->msgout_index > index)
2977 1.96 fvdl found = TRUE;
2978 1.96 fvdl index++;
2979 1.96 fvdl }
2980 1.42 fvdl
2981 1.96 fvdl if (found)
2982 1.96 fvdl break;
2983 1.42 fvdl }
2984 1.96 fvdl return (found);
2985 1.96 fvdl }
2986 1.42 fvdl
2987 1.96 fvdl /*
2988 1.96 fvdl * Wait for a complete incoming message, parse it, and respond accordingly.
2989 1.96 fvdl */
2990 1.96 fvdl static int
2991 1.96 fvdl ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
2992 1.96 fvdl {
2993 1.96 fvdl struct ahc_initiator_tinfo *tinfo;
2994 1.96 fvdl struct ahc_tmode_tstate *tstate;
2995 1.96 fvdl int reject;
2996 1.96 fvdl int done;
2997 1.96 fvdl int response;
2998 1.96 fvdl u_int targ_scsirate;
2999 1.42 fvdl
3000 1.96 fvdl done = MSGLOOP_IN_PROG;
3001 1.96 fvdl response = FALSE;
3002 1.96 fvdl reject = FALSE;
3003 1.96 fvdl tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
3004 1.96 fvdl devinfo->target, &tstate);
3005 1.96 fvdl targ_scsirate = tinfo->scsirate;
3006 1.42 fvdl
3007 1.42 fvdl /*
3008 1.96 fvdl * Parse as much of the message as is availible,
3009 1.96 fvdl * rejecting it if we don't support it. When
3010 1.96 fvdl * the entire message is availible and has been
3011 1.96 fvdl * handled, return MSGLOOP_MSGCOMPLETE, indicating
3012 1.96 fvdl * that we have parsed an entire message.
3013 1.42 fvdl *
3014 1.96 fvdl * In the case of extended messages, we accept the length
3015 1.96 fvdl * byte outright and perform more checking once we know the
3016 1.96 fvdl * extended message type.
3017 1.42 fvdl */
3018 1.96 fvdl switch (ahc->msgin_buf[0]) {
3019 1.96 fvdl case MSG_DISCONNECT:
3020 1.96 fvdl case MSG_SAVEDATAPOINTER:
3021 1.96 fvdl case MSG_CMDCOMPLETE:
3022 1.96 fvdl case MSG_RESTOREPOINTERS:
3023 1.96 fvdl case MSG_IGN_WIDE_RESIDUE:
3024 1.96 fvdl /*
3025 1.96 fvdl * End our message loop as these are messages
3026 1.96 fvdl * the sequencer handles on its own.
3027 1.96 fvdl */
3028 1.96 fvdl done = MSGLOOP_TERMINATED;
3029 1.96 fvdl break;
3030 1.96 fvdl case MSG_MESSAGE_REJECT:
3031 1.96 fvdl response = ahc_handle_msg_reject(ahc, devinfo);
3032 1.96 fvdl /* FALLTHROUGH */
3033 1.96 fvdl case MSG_NOOP:
3034 1.96 fvdl done = MSGLOOP_MSGCOMPLETE;
3035 1.96 fvdl break;
3036 1.96 fvdl case MSG_EXTENDED:
3037 1.96 fvdl {
3038 1.96 fvdl /* Wait for enough of the message to begin validation */
3039 1.96 fvdl if (ahc->msgin_index < 2)
3040 1.96 fvdl break;
3041 1.96 fvdl switch (ahc->msgin_buf[2]) {
3042 1.96 fvdl case MSG_EXT_SDTR:
3043 1.96 fvdl {
3044 1.96 fvdl struct ahc_syncrate *syncrate;
3045 1.96 fvdl u_int period;
3046 1.96 fvdl u_int ppr_options;
3047 1.96 fvdl u_int offset;
3048 1.96 fvdl u_int saved_offset;
3049 1.96 fvdl
3050 1.96 fvdl if (ahc->msgin_buf[1] != MSG_EXT_SDTR_LEN) {
3051 1.96 fvdl reject = TRUE;
3052 1.96 fvdl break;
3053 1.96 fvdl }
3054 1.42 fvdl
3055 1.96 fvdl /*
3056 1.96 fvdl * Wait until we have both args before validating
3057 1.96 fvdl * and acting on this message.
3058 1.96 fvdl *
3059 1.96 fvdl * Add one to MSG_EXT_SDTR_LEN to account for
3060 1.96 fvdl * the extended message preamble.
3061 1.96 fvdl */
3062 1.96 fvdl if (ahc->msgin_index < (MSG_EXT_SDTR_LEN + 1))
3063 1.96 fvdl break;
3064 1.42 fvdl
3065 1.96 fvdl period = ahc->msgin_buf[3];
3066 1.96 fvdl ppr_options = 0;
3067 1.96 fvdl saved_offset = offset = ahc->msgin_buf[4];
3068 1.96 fvdl syncrate = ahc_devlimited_syncrate(ahc, tinfo, &period,
3069 1.96 fvdl &ppr_options,
3070 1.96 fvdl devinfo->role);
3071 1.96 fvdl ahc_validate_offset(ahc, tinfo, syncrate, &offset,
3072 1.96 fvdl targ_scsirate & WIDEXFER,
3073 1.96 fvdl devinfo->role);
3074 1.96 fvdl if (bootverbose) {
3075 1.96 fvdl printf("(%s:%c:%d:%d): Received "
3076 1.96 fvdl "SDTR period %x, offset %x\n\t"
3077 1.96 fvdl "Filtered to period %x, offset %x\n",
3078 1.96 fvdl ahc_name(ahc), devinfo->channel,
3079 1.96 fvdl devinfo->target, devinfo->lun,
3080 1.96 fvdl ahc->msgin_buf[3], saved_offset,
3081 1.96 fvdl period, offset);
3082 1.96 fvdl }
3083 1.96 fvdl ahc_set_syncrate(ahc, devinfo,
3084 1.96 fvdl syncrate, period,
3085 1.96 fvdl offset, ppr_options,
3086 1.96 fvdl AHC_TRANS_ACTIVE|AHC_TRANS_GOAL,
3087 1.96 fvdl /*paused*/TRUE);
3088 1.42 fvdl
3089 1.96 fvdl /*
3090 1.96 fvdl * See if we initiated Sync Negotiation
3091 1.96 fvdl * and didn't have to fall down to async
3092 1.96 fvdl * transfers.
3093 1.96 fvdl */
3094 1.96 fvdl if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_SDTR, TRUE)) {
3095 1.96 fvdl /* We started it */
3096 1.96 fvdl if (saved_offset != offset) {
3097 1.96 fvdl /* Went too low - force async */
3098 1.96 fvdl reject = TRUE;
3099 1.96 fvdl }
3100 1.96 fvdl } else {
3101 1.96 fvdl /*
3102 1.96 fvdl * Send our own SDTR in reply
3103 1.96 fvdl */
3104 1.96 fvdl if (bootverbose
3105 1.96 fvdl && devinfo->role == ROLE_INITIATOR) {
3106 1.96 fvdl printf("(%s:%c:%d:%d): Target "
3107 1.96 fvdl "Initiated SDTR\n",
3108 1.96 fvdl ahc_name(ahc), devinfo->channel,
3109 1.96 fvdl devinfo->target, devinfo->lun);
3110 1.96 fvdl }
3111 1.96 fvdl ahc->msgout_index = 0;
3112 1.96 fvdl ahc->msgout_len = 0;
3113 1.96 fvdl ahc_construct_sdtr(ahc, devinfo,
3114 1.96 fvdl period, offset);
3115 1.96 fvdl ahc->msgout_index = 0;
3116 1.96 fvdl response = TRUE;
3117 1.96 fvdl }
3118 1.96 fvdl done = MSGLOOP_MSGCOMPLETE;
3119 1.96 fvdl break;
3120 1.96 fvdl }
3121 1.96 fvdl case MSG_EXT_WDTR:
3122 1.96 fvdl {
3123 1.96 fvdl u_int bus_width;
3124 1.96 fvdl u_int saved_width;
3125 1.96 fvdl u_int sending_reply;
3126 1.42 fvdl
3127 1.96 fvdl sending_reply = FALSE;
3128 1.96 fvdl if (ahc->msgin_buf[1] != MSG_EXT_WDTR_LEN) {
3129 1.96 fvdl reject = TRUE;
3130 1.96 fvdl break;
3131 1.96 fvdl }
3132 1.42 fvdl
3133 1.96 fvdl /*
3134 1.96 fvdl * Wait until we have our arg before validating
3135 1.96 fvdl * and acting on this message.
3136 1.96 fvdl *
3137 1.96 fvdl * Add one to MSG_EXT_WDTR_LEN to account for
3138 1.96 fvdl * the extended message preamble.
3139 1.96 fvdl */
3140 1.96 fvdl if (ahc->msgin_index < (MSG_EXT_WDTR_LEN + 1))
3141 1.96 fvdl break;
3142 1.42 fvdl
3143 1.96 fvdl bus_width = ahc->msgin_buf[3];
3144 1.96 fvdl saved_width = bus_width;
3145 1.96 fvdl ahc_validate_width(ahc, tinfo, &bus_width,
3146 1.96 fvdl devinfo->role);
3147 1.96 fvdl if (bootverbose) {
3148 1.96 fvdl printf("(%s:%c:%d:%d): Received WDTR "
3149 1.96 fvdl "%x filtered to %x\n",
3150 1.96 fvdl ahc_name(ahc), devinfo->channel,
3151 1.96 fvdl devinfo->target, devinfo->lun,
3152 1.96 fvdl saved_width, bus_width);
3153 1.96 fvdl }
3154 1.42 fvdl
3155 1.96 fvdl if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_WDTR, TRUE)) {
3156 1.96 fvdl /*
3157 1.96 fvdl * Don't send a WDTR back to the
3158 1.96 fvdl * target, since we asked first.
3159 1.96 fvdl * If the width went higher than our
3160 1.96 fvdl * request, reject it.
3161 1.96 fvdl */
3162 1.96 fvdl if (saved_width > bus_width) {
3163 1.96 fvdl reject = TRUE;
3164 1.96 fvdl printf("(%s:%c:%d:%d): requested %dBit "
3165 1.96 fvdl "transfers. Rejecting...\n",
3166 1.96 fvdl ahc_name(ahc), devinfo->channel,
3167 1.96 fvdl devinfo->target, devinfo->lun,
3168 1.96 fvdl 8 * (0x01 << bus_width));
3169 1.96 fvdl bus_width = 0;
3170 1.96 fvdl }
3171 1.96 fvdl } else {
3172 1.96 fvdl /*
3173 1.96 fvdl * Send our own WDTR in reply
3174 1.96 fvdl */
3175 1.96 fvdl if (bootverbose
3176 1.96 fvdl && devinfo->role == ROLE_INITIATOR) {
3177 1.96 fvdl printf("(%s:%c:%d:%d): Target "
3178 1.96 fvdl "Initiated WDTR\n",
3179 1.96 fvdl ahc_name(ahc), devinfo->channel,
3180 1.96 fvdl devinfo->target, devinfo->lun);
3181 1.96 fvdl }
3182 1.96 fvdl ahc->msgout_index = 0;
3183 1.96 fvdl ahc->msgout_len = 0;
3184 1.96 fvdl ahc_construct_wdtr(ahc, devinfo, bus_width);
3185 1.96 fvdl ahc->msgout_index = 0;
3186 1.96 fvdl response = TRUE;
3187 1.96 fvdl sending_reply = TRUE;
3188 1.96 fvdl }
3189 1.96 fvdl ahc_set_width(ahc, devinfo, bus_width,
3190 1.96 fvdl AHC_TRANS_ACTIVE|AHC_TRANS_GOAL,
3191 1.96 fvdl /*paused*/TRUE);
3192 1.96 fvdl /* After a wide message, we are async */
3193 1.96 fvdl ahc_set_syncrate(ahc, devinfo,
3194 1.96 fvdl /*syncrate*/NULL, /*period*/0,
3195 1.96 fvdl /*offset*/0, /*ppr_options*/0,
3196 1.96 fvdl AHC_TRANS_ACTIVE, /*paused*/TRUE);
3197 1.96 fvdl if (sending_reply == FALSE && reject == FALSE) {
3198 1.42 fvdl
3199 1.96 fvdl if (tinfo->goal.offset) {
3200 1.96 fvdl ahc->msgout_index = 0;
3201 1.96 fvdl ahc->msgout_len = 0;
3202 1.96 fvdl ahc_build_transfer_msg(ahc, devinfo);
3203 1.96 fvdl ahc->msgout_index = 0;
3204 1.96 fvdl response = TRUE;
3205 1.96 fvdl }
3206 1.96 fvdl }
3207 1.96 fvdl done = MSGLOOP_MSGCOMPLETE;
3208 1.96 fvdl break;
3209 1.96 fvdl }
3210 1.96 fvdl case MSG_EXT_PPR:
3211 1.96 fvdl {
3212 1.96 fvdl struct ahc_syncrate *syncrate;
3213 1.96 fvdl u_int period;
3214 1.96 fvdl u_int offset;
3215 1.96 fvdl u_int bus_width;
3216 1.96 fvdl u_int ppr_options;
3217 1.96 fvdl u_int saved_width;
3218 1.96 fvdl u_int saved_offset;
3219 1.96 fvdl u_int saved_ppr_options;
3220 1.42 fvdl
3221 1.96 fvdl if (ahc->msgin_buf[1] != MSG_EXT_PPR_LEN) {
3222 1.96 fvdl reject = TRUE;
3223 1.96 fvdl break;
3224 1.96 fvdl }
3225 1.42 fvdl
3226 1.96 fvdl /*
3227 1.96 fvdl * Wait until we have all args before validating
3228 1.96 fvdl * and acting on this message.
3229 1.96 fvdl *
3230 1.96 fvdl * Add one to MSG_EXT_PPR_LEN to account for
3231 1.96 fvdl * the extended message preamble.
3232 1.96 fvdl */
3233 1.96 fvdl if (ahc->msgin_index < (MSG_EXT_PPR_LEN + 1))
3234 1.96 fvdl break;
3235 1.42 fvdl
3236 1.96 fvdl period = ahc->msgin_buf[3];
3237 1.96 fvdl offset = ahc->msgin_buf[5];
3238 1.96 fvdl bus_width = ahc->msgin_buf[6];
3239 1.96 fvdl saved_width = bus_width;
3240 1.96 fvdl ppr_options = ahc->msgin_buf[7];
3241 1.96 fvdl /*
3242 1.96 fvdl * According to the spec, a DT only
3243 1.96 fvdl * period factor with no DT option
3244 1.96 fvdl * set implies async.
3245 1.96 fvdl */
3246 1.96 fvdl if ((ppr_options & MSG_EXT_PPR_DT_REQ) == 0
3247 1.96 fvdl && period == 9)
3248 1.96 fvdl offset = 0;
3249 1.96 fvdl saved_ppr_options = ppr_options;
3250 1.96 fvdl saved_offset = offset;
3251 1.42 fvdl
3252 1.96 fvdl /*
3253 1.96 fvdl * Mask out any options we don't support
3254 1.96 fvdl * on any controller. Transfer options are
3255 1.96 fvdl * only available if we are negotiating wide.
3256 1.96 fvdl */
3257 1.96 fvdl ppr_options &= MSG_EXT_PPR_DT_REQ;
3258 1.96 fvdl if (bus_width == 0)
3259 1.96 fvdl ppr_options = 0;
3260 1.96 fvdl
3261 1.96 fvdl ahc_validate_width(ahc, tinfo, &bus_width,
3262 1.96 fvdl devinfo->role);
3263 1.96 fvdl syncrate = ahc_devlimited_syncrate(ahc, tinfo, &period,
3264 1.96 fvdl &ppr_options,
3265 1.96 fvdl devinfo->role);
3266 1.96 fvdl ahc_validate_offset(ahc, tinfo, syncrate,
3267 1.96 fvdl &offset, bus_width,
3268 1.96 fvdl devinfo->role);
3269 1.42 fvdl
3270 1.96 fvdl if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_PPR, TRUE)) {
3271 1.96 fvdl /*
3272 1.96 fvdl * If we are unable to do any of the
3273 1.96 fvdl * requested options (we went too low),
3274 1.96 fvdl * then we'll have to reject the message.
3275 1.96 fvdl */
3276 1.96 fvdl if (saved_width > bus_width
3277 1.96 fvdl || saved_offset != offset
3278 1.96 fvdl || saved_ppr_options != ppr_options) {
3279 1.96 fvdl reject = TRUE;
3280 1.96 fvdl period = 0;
3281 1.96 fvdl offset = 0;
3282 1.96 fvdl bus_width = 0;
3283 1.96 fvdl ppr_options = 0;
3284 1.96 fvdl syncrate = NULL;
3285 1.96 fvdl }
3286 1.96 fvdl } else {
3287 1.96 fvdl if (devinfo->role != ROLE_TARGET)
3288 1.96 fvdl printf("(%s:%c:%d:%d): Target "
3289 1.96 fvdl "Initiated PPR\n",
3290 1.96 fvdl ahc_name(ahc), devinfo->channel,
3291 1.96 fvdl devinfo->target, devinfo->lun);
3292 1.96 fvdl else
3293 1.96 fvdl printf("(%s:%c:%d:%d): Initiator "
3294 1.96 fvdl "Initiated PPR\n",
3295 1.96 fvdl ahc_name(ahc), devinfo->channel,
3296 1.96 fvdl devinfo->target, devinfo->lun);
3297 1.96 fvdl ahc->msgout_index = 0;
3298 1.96 fvdl ahc->msgout_len = 0;
3299 1.96 fvdl ahc_construct_ppr(ahc, devinfo, period, offset,
3300 1.96 fvdl bus_width, ppr_options);
3301 1.96 fvdl ahc->msgout_index = 0;
3302 1.96 fvdl response = TRUE;
3303 1.96 fvdl }
3304 1.96 fvdl if (bootverbose) {
3305 1.96 fvdl printf("(%s:%c:%d:%d): Received PPR width %x, "
3306 1.96 fvdl "period %x, offset %x,options %x\n"
3307 1.96 fvdl "\tFiltered to width %x, period %x, "
3308 1.96 fvdl "offset %x, options %x\n",
3309 1.96 fvdl ahc_name(ahc), devinfo->channel,
3310 1.96 fvdl devinfo->target, devinfo->lun,
3311 1.96 fvdl saved_width, ahc->msgin_buf[3],
3312 1.96 fvdl saved_offset, saved_ppr_options,
3313 1.96 fvdl bus_width, period, offset, ppr_options);
3314 1.96 fvdl }
3315 1.96 fvdl ahc_set_width(ahc, devinfo, bus_width,
3316 1.96 fvdl AHC_TRANS_ACTIVE|AHC_TRANS_GOAL,
3317 1.96 fvdl /*paused*/TRUE);
3318 1.96 fvdl ahc_set_syncrate(ahc, devinfo,
3319 1.96 fvdl syncrate, period,
3320 1.96 fvdl offset, ppr_options,
3321 1.96 fvdl AHC_TRANS_ACTIVE|AHC_TRANS_GOAL,
3322 1.96 fvdl /*paused*/TRUE);
3323 1.96 fvdl done = MSGLOOP_MSGCOMPLETE;
3324 1.96 fvdl break;
3325 1.96 fvdl }
3326 1.96 fvdl default:
3327 1.96 fvdl /* Unknown extended message. Reject it. */
3328 1.96 fvdl reject = TRUE;
3329 1.96 fvdl break;
3330 1.96 fvdl }
3331 1.96 fvdl break;
3332 1.96 fvdl }
3333 1.96 fvdl #ifdef AHC_TARGET_MODE
3334 1.96 fvdl case MSG_BUS_DEV_RESET:
3335 1.96 fvdl ahc_handle_devreset(ahc, devinfo,
3336 1.96 fvdl CAM_BDR_SENT,
3337 1.96 fvdl "Bus Device Reset Received",
3338 1.96 fvdl /*verbose_level*/0);
3339 1.96 fvdl ahc_restart(ahc);
3340 1.96 fvdl done = MSGLOOP_TERMINATED;
3341 1.96 fvdl break;
3342 1.96 fvdl case MSG_ABORT_TAG:
3343 1.96 fvdl case MSG_ABORT:
3344 1.96 fvdl case MSG_CLEAR_QUEUE:
3345 1.42 fvdl {
3346 1.96 fvdl int tag;
3347 1.42 fvdl
3348 1.96 fvdl /* Target mode messages */
3349 1.96 fvdl if (devinfo->role != ROLE_TARGET) {
3350 1.96 fvdl reject = TRUE;
3351 1.96 fvdl break;
3352 1.42 fvdl }
3353 1.96 fvdl tag = SCB_LIST_NULL;
3354 1.96 fvdl if (ahc->msgin_buf[0] == MSG_ABORT_TAG)
3355 1.96 fvdl tag = ahc_inb(ahc, INITIATOR_TAG);
3356 1.96 fvdl ahc_abort_scbs(ahc, devinfo->target, devinfo->channel,
3357 1.96 fvdl devinfo->lun, tag, ROLE_TARGET,
3358 1.96 fvdl CAM_REQ_ABORTED);
3359 1.42 fvdl
3360 1.96 fvdl tstate = ahc->enabled_targets[devinfo->our_scsiid];
3361 1.96 fvdl if (tstate != NULL) {
3362 1.96 fvdl struct ahc_tmode_lstate* lstate;
3363 1.42 fvdl
3364 1.96 fvdl lstate = tstate->enabled_luns[devinfo->lun];
3365 1.96 fvdl if (lstate != NULL) {
3366 1.96 fvdl ahc_queue_lstate_event(ahc, lstate,
3367 1.96 fvdl devinfo->our_scsiid,
3368 1.96 fvdl ahc->msgin_buf[0],
3369 1.96 fvdl /*arg*/tag);
3370 1.96 fvdl ahc_send_lstate_events(ahc, lstate);
3371 1.96 fvdl }
3372 1.96 fvdl }
3373 1.96 fvdl ahc_restart(ahc);
3374 1.96 fvdl done = MSGLOOP_TERMINATED;
3375 1.42 fvdl break;
3376 1.96 fvdl }
3377 1.96 fvdl #endif
3378 1.96 fvdl case MSG_TERM_IO_PROC:
3379 1.96 fvdl default:
3380 1.96 fvdl reject = TRUE;
3381 1.42 fvdl break;
3382 1.42 fvdl }
3383 1.42 fvdl
3384 1.96 fvdl if (reject) {
3385 1.96 fvdl /*
3386 1.96 fvdl * Setup to reject the message.
3387 1.96 fvdl */
3388 1.96 fvdl ahc->msgout_index = 0;
3389 1.96 fvdl ahc->msgout_len = 1;
3390 1.96 fvdl ahc->msgout_buf[0] = MSG_MESSAGE_REJECT;
3391 1.96 fvdl done = MSGLOOP_MSGCOMPLETE;
3392 1.96 fvdl response = TRUE;
3393 1.96 fvdl }
3394 1.42 fvdl
3395 1.96 fvdl if (done != MSGLOOP_IN_PROG && !response)
3396 1.96 fvdl /* Clear the outgoing message buffer */
3397 1.96 fvdl ahc->msgout_len = 0;
3398 1.42 fvdl
3399 1.96 fvdl return (done);
3400 1.42 fvdl }
3401 1.42 fvdl
3402 1.42 fvdl /*
3403 1.96 fvdl * Process a message reject message.
3404 1.42 fvdl */
3405 1.96 fvdl static int
3406 1.96 fvdl ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
3407 1.42 fvdl {
3408 1.96 fvdl /*
3409 1.96 fvdl * What we care about here is if we had an
3410 1.96 fvdl * outstanding SDTR or WDTR message for this
3411 1.96 fvdl * target. If we did, this is a signal that
3412 1.96 fvdl * the target is refusing negotiation.
3413 1.96 fvdl */
3414 1.96 fvdl struct scb *scb;
3415 1.96 fvdl struct ahc_initiator_tinfo *tinfo;
3416 1.96 fvdl struct ahc_tmode_tstate *tstate;
3417 1.96 fvdl u_int scb_index;
3418 1.96 fvdl u_int last_msg;
3419 1.96 fvdl int response = 0;
3420 1.42 fvdl
3421 1.96 fvdl scb_index = ahc_inb(ahc, SCB_TAG);
3422 1.96 fvdl scb = ahc_lookup_scb(ahc, scb_index);
3423 1.96 fvdl tinfo = ahc_fetch_transinfo(ahc, devinfo->channel,
3424 1.96 fvdl devinfo->our_scsiid,
3425 1.96 fvdl devinfo->target, &tstate);
3426 1.96 fvdl /* Might be necessary */
3427 1.96 fvdl last_msg = ahc_inb(ahc, LAST_MSG);
3428 1.42 fvdl
3429 1.96 fvdl if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_PPR, /*full*/FALSE)) {
3430 1.96 fvdl /*
3431 1.96 fvdl * Target does not support the PPR message.
3432 1.96 fvdl * Attempt to negotiate SPI-2 style.
3433 1.96 fvdl */
3434 1.96 fvdl if (bootverbose) {
3435 1.96 fvdl printf("(%s:%c:%d:%d): PPR Rejected. "
3436 1.96 fvdl "Trying WDTR/SDTR\n",
3437 1.96 fvdl ahc_name(ahc), devinfo->channel,
3438 1.96 fvdl devinfo->target, devinfo->lun);
3439 1.96 fvdl }
3440 1.96 fvdl tinfo->goal.ppr_options = 0;
3441 1.96 fvdl tinfo->curr.transport_version = 2;
3442 1.96 fvdl tinfo->goal.transport_version = 2;
3443 1.96 fvdl ahc->msgout_index = 0;
3444 1.96 fvdl ahc->msgout_len = 0;
3445 1.96 fvdl ahc_build_transfer_msg(ahc, devinfo);
3446 1.96 fvdl ahc->msgout_index = 0;
3447 1.96 fvdl response = 1;
3448 1.96 fvdl } else if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_WDTR, /*full*/FALSE)) {
3449 1.42 fvdl
3450 1.96 fvdl /* note 8bit xfers */
3451 1.96 fvdl if (bootverbose)
3452 1.96 fvdl printf("(%s:%c:%d:%d): refuses WIDE negotiation. Using "
3453 1.96 fvdl "8bit transfers\n", ahc_name(ahc),
3454 1.96 fvdl devinfo->channel, devinfo->target, devinfo->lun);
3455 1.96 fvdl ahc_set_width(ahc, devinfo, MSG_EXT_WDTR_BUS_8_BIT,
3456 1.96 fvdl AHC_TRANS_ACTIVE|AHC_TRANS_GOAL,
3457 1.96 fvdl /*paused*/TRUE);
3458 1.96 fvdl /*
3459 1.96 fvdl * No need to clear the sync rate. If the target
3460 1.96 fvdl * did not accept the command, our syncrate is
3461 1.96 fvdl * unaffected. If the target started the negotiation,
3462 1.96 fvdl * but rejected our response, we already cleared the
3463 1.96 fvdl * sync rate before sending our WDTR.
3464 1.96 fvdl */
3465 1.96 fvdl if (tinfo->goal.offset != tinfo->curr.offset) {
3466 1.42 fvdl
3467 1.96 fvdl /* Start the sync negotiation */
3468 1.96 fvdl ahc->msgout_index = 0;
3469 1.96 fvdl ahc->msgout_len = 0;
3470 1.96 fvdl ahc_build_transfer_msg(ahc, devinfo);
3471 1.96 fvdl ahc->msgout_index = 0;
3472 1.96 fvdl response = 1;
3473 1.96 fvdl }
3474 1.96 fvdl } else if (ahc_sent_msg(ahc, AHCMSG_EXT, MSG_EXT_SDTR, /*full*/FALSE)) {
3475 1.96 fvdl /* note asynch xfers and clear flag */
3476 1.96 fvdl ahc_set_syncrate(ahc, devinfo, /*syncrate*/NULL, /*period*/0,
3477 1.96 fvdl /*offset*/0, /*ppr_options*/0,
3478 1.96 fvdl AHC_TRANS_ACTIVE|AHC_TRANS_GOAL,
3479 1.96 fvdl /*paused*/TRUE);
3480 1.96 fvdl if (bootverbose)
3481 1.96 fvdl printf("(%s:%c:%d:%d): refuses synchronous negotiation."
3482 1.96 fvdl " Using asynchronous transfers\n",
3483 1.96 fvdl ahc_name(ahc), devinfo->channel,
3484 1.96 fvdl devinfo->target, devinfo->lun);
3485 1.96 fvdl } else if ((scb->hscb->control & MSG_SIMPLE_TASK) != 0) {
3486 1.96 fvdl int tag_type;
3487 1.96 fvdl int mask;
3488 1.96 fvdl
3489 1.96 fvdl tag_type = (scb->hscb->control & MSG_SIMPLE_TASK);
3490 1.96 fvdl
3491 1.96 fvdl if (tag_type == MSG_SIMPLE_TASK) {
3492 1.96 fvdl if (bootverbose)
3493 1.96 fvdl printf("(%s:%c:%d:%d): refuses tagged commands."
3494 1.96 fvdl " Performing non-tagged I/O\n",
3495 1.96 fvdl ahc_name(ahc), devinfo->channel,
3496 1.96 fvdl devinfo->target, devinfo->lun);
3497 1.96 fvdl ahc_set_tags(ahc, devinfo, AHC_QUEUE_NONE);
3498 1.96 fvdl mask = ~0x23;
3499 1.96 fvdl } else {
3500 1.96 fvdl if (bootverbose)
3501 1.96 fvdl printf("(%s:%c:%d:%d): refuses %s tagged "
3502 1.96 fvdl "commands. Performing simple queue "
3503 1.96 fvdl "tagged I/O only\n",
3504 1.96 fvdl ahc_name(ahc), devinfo->channel,
3505 1.96 fvdl devinfo->target, devinfo->lun,
3506 1.96 fvdl tag_type == MSG_ORDERED_TASK
3507 1.96 fvdl ? "ordered" : "head of queue");
3508 1.96 fvdl ahc_set_tags(ahc, devinfo, AHC_QUEUE_BASIC);
3509 1.96 fvdl mask = ~0x03;
3510 1.96 fvdl }
3511 1.42 fvdl
3512 1.96 fvdl /*
3513 1.96 fvdl * Resend the identify for this CCB as the target
3514 1.96 fvdl * may believe that the selection is invalid otherwise.
3515 1.96 fvdl */
3516 1.96 fvdl ahc_outb(ahc, SCB_CONTROL,
3517 1.96 fvdl ahc_inb(ahc, SCB_CONTROL) & mask);
3518 1.96 fvdl scb->hscb->control &= mask;
3519 1.96 fvdl ahc_set_transaction_tag(scb, /*enabled*/FALSE,
3520 1.96 fvdl /*type*/MSG_SIMPLE_TASK);
3521 1.96 fvdl ahc_outb(ahc, MSG_OUT, MSG_IDENTIFYFLAG);
3522 1.96 fvdl ahc_assert_atn(ahc);
3523 1.42 fvdl
3524 1.96 fvdl /*
3525 1.96 fvdl * This transaction is now at the head of
3526 1.96 fvdl * the untagged queue for this target.
3527 1.96 fvdl */
3528 1.96 fvdl if ((ahc->flags & AHC_SCB_BTT) == 0) {
3529 1.96 fvdl struct scb_tailq *untagged_q;
3530 1.42 fvdl
3531 1.96 fvdl untagged_q =
3532 1.96 fvdl &(ahc->untagged_queues[devinfo->target_offset]);
3533 1.96 fvdl TAILQ_INSERT_HEAD(untagged_q, scb, links.tqe);
3534 1.96 fvdl scb->flags |= SCB_UNTAGGEDQ;
3535 1.42 fvdl }
3536 1.96 fvdl ahc_busy_tcl(ahc, BUILD_TCL(scb->hscb->scsiid, devinfo->lun),
3537 1.96 fvdl scb->hscb->tag);
3538 1.96 fvdl
3539 1.96 fvdl /*
3540 1.96 fvdl * Requeue all tagged commands for this target
3541 1.96 fvdl * currently in our posession so they can be
3542 1.96 fvdl * converted to untagged commands.
3543 1.96 fvdl */
3544 1.96 fvdl ahc_search_qinfifo(ahc, SCB_GET_TARGET(ahc, scb),
3545 1.96 fvdl SCB_GET_CHANNEL(ahc, scb),
3546 1.96 fvdl SCB_GET_LUN(scb), /*tag*/SCB_LIST_NULL,
3547 1.96 fvdl ROLE_INITIATOR, CAM_REQUEUE_REQ,
3548 1.96 fvdl SEARCH_COMPLETE);
3549 1.96 fvdl } else {
3550 1.96 fvdl /*
3551 1.96 fvdl * Otherwise, we ignore it.
3552 1.96 fvdl */
3553 1.96 fvdl if (bootverbose)
3554 1.96 fvdl printf("%s:%c:%d: Message reject for %x -- ignored\n",
3555 1.96 fvdl ahc_name(ahc), devinfo->channel, devinfo->target,
3556 1.96 fvdl last_msg);
3557 1.42 fvdl }
3558 1.96 fvdl return (response);
3559 1.42 fvdl }
3560 1.42 fvdl
3561 1.96 fvdl /*
3562 1.96 fvdl * Process an ingnore wide residue message.
3563 1.96 fvdl */
3564 1.42 fvdl static void
3565 1.96 fvdl ahc_handle_ign_wide_residue(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
3566 1.42 fvdl {
3567 1.96 fvdl u_int scb_index;
3568 1.96 fvdl struct scb *scb;
3569 1.42 fvdl
3570 1.96 fvdl scb_index = ahc_inb(ahc, SCB_TAG);
3571 1.96 fvdl scb = ahc_lookup_scb(ahc, scb_index);
3572 1.96 fvdl /*
3573 1.96 fvdl * XXX Actually check data direction in the sequencer?
3574 1.96 fvdl * Perhaps add datadir to some spare bits in the hscb?
3575 1.96 fvdl */
3576 1.96 fvdl if ((ahc_inb(ahc, SEQ_FLAGS) & DPHASE) == 0
3577 1.96 fvdl || ahc_get_transfer_dir(scb) != CAM_DIR_IN) {
3578 1.96 fvdl /*
3579 1.96 fvdl * Ignore the message if we haven't
3580 1.96 fvdl * seen an appropriate data phase yet.
3581 1.96 fvdl */
3582 1.42 fvdl } else {
3583 1.96 fvdl /*
3584 1.96 fvdl * If the residual occurred on the last
3585 1.96 fvdl * transfer and the transfer request was
3586 1.96 fvdl * expected to end on an odd count, do
3587 1.96 fvdl * nothing. Otherwise, subtract a byte
3588 1.96 fvdl * and update the residual count accordingly.
3589 1.96 fvdl */
3590 1.96 fvdl uint32_t sgptr;
3591 1.42 fvdl
3592 1.96 fvdl sgptr = ahc_inb(ahc, SCB_RESIDUAL_SGPTR);
3593 1.96 fvdl if ((sgptr & SG_LIST_NULL) != 0
3594 1.96 fvdl && ahc_inb(ahc, DATA_COUNT_ODD) == 1) {
3595 1.96 fvdl /*
3596 1.96 fvdl * If the residual occurred on the last
3597 1.96 fvdl * transfer and the transfer request was
3598 1.96 fvdl * expected to end on an odd count, do
3599 1.96 fvdl * nothing.
3600 1.96 fvdl */
3601 1.42 fvdl } else {
3602 1.96 fvdl struct ahc_dma_seg *sg;
3603 1.96 fvdl uint32_t data_cnt;
3604 1.96 fvdl uint32_t data_addr;
3605 1.96 fvdl uint32_t sglen;
3606 1.96 fvdl
3607 1.96 fvdl /* Pull in the rest of the sgptr */
3608 1.96 fvdl sgptr |= (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 3) << 24)
3609 1.96 fvdl | (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 2) << 16)
3610 1.96 fvdl | (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 1) << 8);
3611 1.96 fvdl sgptr &= SG_PTR_MASK;
3612 1.96 fvdl data_cnt = (ahc_inb(ahc, SCB_RESIDUAL_DATACNT+3) << 24)
3613 1.96 fvdl | (ahc_inb(ahc, SCB_RESIDUAL_DATACNT+2) << 16)
3614 1.96 fvdl | (ahc_inb(ahc, SCB_RESIDUAL_DATACNT+1) << 8)
3615 1.96 fvdl | (ahc_inb(ahc, SCB_RESIDUAL_DATACNT));
3616 1.42 fvdl
3617 1.96 fvdl data_addr = (ahc_inb(ahc, SHADDR + 3) << 24)
3618 1.96 fvdl | (ahc_inb(ahc, SHADDR + 2) << 16)
3619 1.96 fvdl | (ahc_inb(ahc, SHADDR + 1) << 8)
3620 1.96 fvdl | (ahc_inb(ahc, SHADDR));
3621 1.42 fvdl
3622 1.96 fvdl data_cnt += 1;
3623 1.96 fvdl data_addr -= 1;
3624 1.42 fvdl
3625 1.96 fvdl sg = ahc_sg_bus_to_virt(scb, sgptr);
3626 1.42 fvdl /*
3627 1.96 fvdl * The residual sg ptr points to the next S/G
3628 1.96 fvdl * to load so we must go back one.
3629 1.42 fvdl */
3630 1.96 fvdl sg--;
3631 1.96 fvdl sglen = ahc_le32toh(sg->len) & AHC_SG_LEN_MASK;
3632 1.96 fvdl if (sg != scb->sg_list
3633 1.96 fvdl && sglen < (data_cnt & AHC_SG_LEN_MASK)) {
3634 1.96 fvdl
3635 1.96 fvdl sg--;
3636 1.96 fvdl sglen = ahc_le32toh(sg->len);
3637 1.96 fvdl /*
3638 1.96 fvdl * Preserve High Address and SG_LIST bits
3639 1.96 fvdl * while setting the count to 1.
3640 1.96 fvdl */
3641 1.96 fvdl data_cnt = 1 | (sglen & (~AHC_SG_LEN_MASK));
3642 1.96 fvdl data_addr = ahc_le32toh(sg->addr)
3643 1.96 fvdl + (sglen & AHC_SG_LEN_MASK) - 1;
3644 1.96 fvdl
3645 1.96 fvdl /*
3646 1.96 fvdl * Increment sg so it points to the
3647 1.96 fvdl * "next" sg.
3648 1.96 fvdl */
3649 1.96 fvdl sg++;
3650 1.96 fvdl sgptr = ahc_sg_virt_to_bus(scb, sg);
3651 1.96 fvdl ahc_outb(ahc, SCB_RESIDUAL_SGPTR + 3,
3652 1.96 fvdl sgptr >> 24);
3653 1.96 fvdl ahc_outb(ahc, SCB_RESIDUAL_SGPTR + 2,
3654 1.96 fvdl sgptr >> 16);
3655 1.96 fvdl ahc_outb(ahc, SCB_RESIDUAL_SGPTR + 1,
3656 1.96 fvdl sgptr >> 8);
3657 1.96 fvdl ahc_outb(ahc, SCB_RESIDUAL_SGPTR, sgptr);
3658 1.42 fvdl }
3659 1.42 fvdl
3660 1.96 fvdl ahc_outb(ahc, SCB_RESIDUAL_DATACNT + 3, data_cnt >> 24);
3661 1.96 fvdl ahc_outb(ahc, SCB_RESIDUAL_DATACNT + 2, data_cnt >> 16);
3662 1.96 fvdl ahc_outb(ahc, SCB_RESIDUAL_DATACNT + 1, data_cnt >> 8);
3663 1.96 fvdl ahc_outb(ahc, SCB_RESIDUAL_DATACNT, data_cnt);
3664 1.42 fvdl }
3665 1.96 fvdl }
3666 1.96 fvdl }
3667 1.42 fvdl
3668 1.42 fvdl
3669 1.96 fvdl /*
3670 1.96 fvdl * Reinitialize the data pointers for the active transfer
3671 1.96 fvdl * based on its current residual.
3672 1.96 fvdl */
3673 1.96 fvdl static void
3674 1.96 fvdl ahc_reinitialize_dataptrs(struct ahc_softc *ahc)
3675 1.96 fvdl {
3676 1.96 fvdl struct scb *scb;
3677 1.96 fvdl struct ahc_dma_seg *sg;
3678 1.96 fvdl u_int scb_index;
3679 1.96 fvdl uint32_t sgptr;
3680 1.96 fvdl uint32_t resid;
3681 1.96 fvdl uint32_t dataptr;
3682 1.42 fvdl
3683 1.96 fvdl scb_index = ahc_inb(ahc, SCB_TAG);
3684 1.96 fvdl scb = ahc_lookup_scb(ahc, scb_index);
3685 1.96 fvdl sgptr = (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 3) << 24)
3686 1.96 fvdl | (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 2) << 16)
3687 1.96 fvdl | (ahc_inb(ahc, SCB_RESIDUAL_SGPTR + 1) << 8)
3688 1.96 fvdl | ahc_inb(ahc, SCB_RESIDUAL_SGPTR);
3689 1.96 fvdl
3690 1.96 fvdl sgptr &= SG_PTR_MASK;
3691 1.96 fvdl sg = ahc_sg_bus_to_virt(scb, sgptr);
3692 1.96 fvdl
3693 1.96 fvdl /* The residual sg_ptr always points to the next sg */
3694 1.96 fvdl sg--;
3695 1.96 fvdl
3696 1.96 fvdl resid = (ahc_inb(ahc, SCB_RESIDUAL_DATACNT + 2) << 16)
3697 1.96 fvdl | (ahc_inb(ahc, SCB_RESIDUAL_DATACNT + 1) << 8)
3698 1.96 fvdl | ahc_inb(ahc, SCB_RESIDUAL_DATACNT);
3699 1.96 fvdl
3700 1.96 fvdl dataptr = ahc_le32toh(sg->addr)
3701 1.96 fvdl + (ahc_le32toh(sg->len) & AHC_SG_LEN_MASK)
3702 1.96 fvdl - resid;
3703 1.96 fvdl if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
3704 1.96 fvdl u_int dscommand1;
3705 1.96 fvdl
3706 1.96 fvdl dscommand1 = ahc_inb(ahc, DSCOMMAND1);
3707 1.96 fvdl ahc_outb(ahc, DSCOMMAND1, dscommand1 | HADDLDSEL0);
3708 1.96 fvdl ahc_outb(ahc, HADDR,
3709 1.96 fvdl (ahc_le32toh(sg->len) >> 24) & SG_HIGH_ADDR_BITS);
3710 1.96 fvdl ahc_outb(ahc, DSCOMMAND1, dscommand1);
3711 1.96 fvdl }
3712 1.96 fvdl ahc_outb(ahc, HADDR + 3, dataptr >> 24);
3713 1.96 fvdl ahc_outb(ahc, HADDR + 2, dataptr >> 16);
3714 1.96 fvdl ahc_outb(ahc, HADDR + 1, dataptr >> 8);
3715 1.96 fvdl ahc_outb(ahc, HADDR, dataptr);
3716 1.96 fvdl ahc_outb(ahc, HCNT + 2, resid >> 16);
3717 1.96 fvdl ahc_outb(ahc, HCNT + 1, resid >> 8);
3718 1.96 fvdl ahc_outb(ahc, HCNT, resid);
3719 1.96 fvdl if ((ahc->features & AHC_ULTRA2) == 0) {
3720 1.96 fvdl ahc_outb(ahc, STCNT + 2, resid >> 16);
3721 1.96 fvdl ahc_outb(ahc, STCNT + 1, resid >> 8);
3722 1.96 fvdl ahc_outb(ahc, STCNT, resid);
3723 1.42 fvdl }
3724 1.42 fvdl }
3725 1.42 fvdl
3726 1.96 fvdl /*
3727 1.96 fvdl * Handle the effects of issuing a bus device reset message.
3728 1.96 fvdl */
3729 1.42 fvdl static void
3730 1.96 fvdl ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
3731 1.96 fvdl cam_status status, char *message, int verbose_level)
3732 1.42 fvdl {
3733 1.96 fvdl #ifdef AHC_TARGET_MODE
3734 1.96 fvdl struct ahc_tmode_tstate* tstate;
3735 1.96 fvdl u_int lun;
3736 1.96 fvdl #endif
3737 1.96 fvdl int found;
3738 1.42 fvdl
3739 1.96 fvdl found = ahc_abort_scbs(ahc, devinfo->target, devinfo->channel,
3740 1.96 fvdl CAM_LUN_WILDCARD, SCB_LIST_NULL, devinfo->role,
3741 1.96 fvdl status);
3742 1.42 fvdl
3743 1.96 fvdl #ifdef AHC_TARGET_MODE
3744 1.96 fvdl /*
3745 1.96 fvdl * Send an immediate notify ccb to all target mord peripheral
3746 1.96 fvdl * drivers affected by this action.
3747 1.96 fvdl */
3748 1.96 fvdl tstate = ahc->enabled_targets[devinfo->our_scsiid];
3749 1.96 fvdl if (tstate != NULL) {
3750 1.96 fvdl for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
3751 1.96 fvdl struct ahc_tmode_lstate* lstate;
3752 1.42 fvdl
3753 1.96 fvdl lstate = tstate->enabled_luns[lun];
3754 1.96 fvdl if (lstate == NULL)
3755 1.96 fvdl continue;
3756 1.42 fvdl
3757 1.96 fvdl ahc_queue_lstate_event(ahc, lstate, devinfo->our_scsiid,
3758 1.96 fvdl MSG_BUS_DEV_RESET, /*arg*/0);
3759 1.96 fvdl ahc_send_lstate_events(ahc, lstate);
3760 1.96 fvdl }
3761 1.42 fvdl }
3762 1.96 fvdl #endif
3763 1.42 fvdl
3764 1.96 fvdl /*
3765 1.96 fvdl * Go back to async/narrow transfers and renegotiate.
3766 1.96 fvdl */
3767 1.96 fvdl ahc_set_width(ahc, devinfo, MSG_EXT_WDTR_BUS_8_BIT,
3768 1.96 fvdl AHC_TRANS_CUR, /*paused*/TRUE);
3769 1.96 fvdl ahc_set_syncrate(ahc, devinfo, /*syncrate*/NULL,
3770 1.96 fvdl /*period*/0, /*offset*/0, /*ppr_options*/0,
3771 1.96 fvdl AHC_TRANS_CUR, /*paused*/TRUE);
3772 1.96 fvdl
3773 1.96 fvdl ahc_send_async(ahc, devinfo->channel, devinfo->target,
3774 1.96 fvdl CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
3775 1.42 fvdl
3776 1.96 fvdl if (message != NULL
3777 1.96 fvdl && (verbose_level <= bootverbose))
3778 1.96 fvdl printf("%s: %s on %c:%d. %d SCBs aborted\n", ahc_name(ahc),
3779 1.96 fvdl message, devinfo->channel, devinfo->target, found);
3780 1.42 fvdl }
3781 1.42 fvdl
3782 1.96 fvdl #ifdef AHC_TARGET_MODE
3783 1.42 fvdl static void
3784 1.96 fvdl ahc_setup_target_msgin(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
3785 1.96 fvdl struct scb *scb)
3786 1.42 fvdl {
3787 1.42 fvdl
3788 1.96 fvdl /*
3789 1.96 fvdl * To facilitate adding multiple messages together,
3790 1.96 fvdl * each routine should increment the index and len
3791 1.96 fvdl * variables instead of setting them explicitly.
3792 1.96 fvdl */
3793 1.96 fvdl ahc->msgout_index = 0;
3794 1.96 fvdl ahc->msgout_len = 0;
3795 1.96 fvdl
3796 1.96 fvdl if (scb != NULL && (scb->flags & SCB_AUTO_NEGOTIATE) != 0)
3797 1.96 fvdl ahc_build_transfer_msg(ahc, devinfo);
3798 1.96 fvdl else
3799 1.96 fvdl panic("ahc_intr: AWAITING target message with no message");
3800 1.96 fvdl
3801 1.96 fvdl ahc->msgout_index = 0;
3802 1.96 fvdl ahc->msg_type = MSG_TYPE_TARGET_MSGIN;
3803 1.96 fvdl }
3804 1.96 fvdl #endif
3805 1.96 fvdl
3806 1.96 fvdl int
3807 1.96 fvdl ahc_softc_init(struct ahc_softc *ahc)
3808 1.96 fvdl {
3809 1.42 fvdl
3810 1.96 fvdl /* The IRQMS bit is only valid on VL and EISA chips */
3811 1.96 fvdl if ((ahc->chip & AHC_PCI) == 0)
3812 1.96 fvdl ahc->unpause = ahc_inb(ahc, HCNTRL) & IRQMS;
3813 1.96 fvdl else
3814 1.96 fvdl ahc->unpause = 0;
3815 1.96 fvdl ahc->pause = ahc->unpause | PAUSE;
3816 1.96 fvdl /* XXX The shared scb data stuff should be deprecated */
3817 1.96 fvdl if (ahc->scb_data == NULL) {
3818 1.96 fvdl ahc->scb_data = malloc(sizeof(*ahc->scb_data),
3819 1.96 fvdl M_DEVBUF, M_NOWAIT);
3820 1.96 fvdl if (ahc->scb_data == NULL)
3821 1.96 fvdl return (ENOMEM);
3822 1.96 fvdl memset(ahc->scb_data, 0, sizeof(*ahc->scb_data));
3823 1.49 fvdl }
3824 1.96 fvdl
3825 1.96 fvdl return (0);
3826 1.42 fvdl }
3827 1.42 fvdl
3828 1.96 fvdl void
3829 1.96 fvdl ahc_softc_insert(struct ahc_softc *ahc)
3830 1.71 bouyer {
3831 1.96 fvdl struct ahc_softc *list_ahc;
3832 1.71 bouyer
3833 1.96 fvdl #if AHC_PCI_CONFIG > 0
3834 1.96 fvdl /*
3835 1.96 fvdl * Second Function PCI devices need to inherit some
3836 1.96 fvdl * settings from function 0.
3837 1.96 fvdl */
3838 1.96 fvdl if ((ahc->chip & AHC_BUS_MASK) == AHC_PCI
3839 1.96 fvdl && (ahc->features & AHC_MULTI_FUNC) != 0) {
3840 1.96 fvdl TAILQ_FOREACH(list_ahc, &ahc_tailq, links) {
3841 1.96 fvdl ahc_dev_softc_t list_pci;
3842 1.96 fvdl ahc_dev_softc_t pci;
3843 1.96 fvdl
3844 1.96 fvdl list_pci = list_ahc->dev_softc;
3845 1.96 fvdl pci = ahc->dev_softc;
3846 1.96 fvdl if (ahc_get_pci_slot(list_pci) == ahc_get_pci_slot(pci)
3847 1.96 fvdl && ahc_get_pci_bus(list_pci) == ahc_get_pci_bus(pci)) {
3848 1.96 fvdl struct ahc_softc *master;
3849 1.96 fvdl struct ahc_softc *slave;
3850 1.96 fvdl
3851 1.96 fvdl if (ahc_get_pci_function(list_pci) == 0) {
3852 1.96 fvdl master = list_ahc;
3853 1.96 fvdl slave = ahc;
3854 1.96 fvdl } else {
3855 1.96 fvdl master = ahc;
3856 1.96 fvdl slave = list_ahc;
3857 1.96 fvdl }
3858 1.96 fvdl slave->flags &= ~AHC_BIOS_ENABLED;
3859 1.96 fvdl slave->flags |=
3860 1.96 fvdl master->flags & AHC_BIOS_ENABLED;
3861 1.96 fvdl slave->flags &= ~AHC_PRIMARY_CHANNEL;
3862 1.96 fvdl slave->flags |=
3863 1.96 fvdl master->flags & AHC_PRIMARY_CHANNEL;
3864 1.96 fvdl break;
3865 1.96 fvdl }
3866 1.96 fvdl }
3867 1.96 fvdl }
3868 1.96 fvdl #endif
3869 1.71 bouyer
3870 1.96 fvdl /*
3871 1.96 fvdl * Insertion sort into our list of softcs.
3872 1.96 fvdl */
3873 1.96 fvdl list_ahc = TAILQ_FIRST(&ahc_tailq);
3874 1.96 fvdl while (list_ahc != NULL
3875 1.96 fvdl && ahc_softc_comp(list_ahc, ahc) <= 0)
3876 1.96 fvdl list_ahc = TAILQ_NEXT(list_ahc, links);
3877 1.96 fvdl if (list_ahc != NULL)
3878 1.96 fvdl TAILQ_INSERT_BEFORE(list_ahc, ahc, links);
3879 1.96 fvdl else
3880 1.96 fvdl TAILQ_INSERT_TAIL(&ahc_tailq, ahc, links);
3881 1.96 fvdl ahc->init_level++;
3882 1.71 bouyer }
3883 1.71 bouyer
3884 1.42 fvdl /*
3885 1.96 fvdl * Verify that the passed in softc pointer is for a
3886 1.96 fvdl * controller that is still configured.
3887 1.42 fvdl */
3888 1.96 fvdl struct ahc_softc *
3889 1.96 fvdl ahc_find_softc(struct ahc_softc *ahc)
3890 1.42 fvdl {
3891 1.96 fvdl struct ahc_softc *list_ahc;
3892 1.42 fvdl
3893 1.96 fvdl TAILQ_FOREACH(list_ahc, &ahc_tailq, links) {
3894 1.96 fvdl if (list_ahc == ahc)
3895 1.96 fvdl return (ahc);
3896 1.42 fvdl }
3897 1.96 fvdl return (NULL);
3898 1.86 ichiro }
3899 1.86 ichiro
3900 1.96 fvdl void
3901 1.96 fvdl ahc_set_unit(struct ahc_softc *ahc, int unit)
3902 1.86 ichiro {
3903 1.96 fvdl ahc->unit = unit;
3904 1.96 fvdl }
3905 1.86 ichiro
3906 1.96 fvdl void
3907 1.96 fvdl ahc_set_name(struct ahc_softc *ahc, char *name)
3908 1.96 fvdl {
3909 1.96 fvdl if (ahc->name != NULL)
3910 1.96 fvdl free(ahc->name, M_DEVBUF);
3911 1.96 fvdl ahc->name = name;
3912 1.86 ichiro }
3913 1.86 ichiro
3914 1.96 fvdl void
3915 1.96 fvdl ahc_free(struct ahc_softc *ahc)
3916 1.86 ichiro {
3917 1.96 fvdl int i;
3918 1.86 ichiro
3919 1.96 fvdl ahc_fini_scbdata(ahc);
3920 1.96 fvdl switch (ahc->init_level) {
3921 1.96 fvdl default:
3922 1.96 fvdl case 2:
3923 1.96 fvdl ahc_shutdown(ahc);
3924 1.104 fvdl /* TAILQ_REMOVE(&ahc_tailq, ahc, links); XXX */
3925 1.96 fvdl /* FALLTHROUGH */
3926 1.96 fvdl case 1:
3927 1.96 fvdl bus_dmamap_unload(ahc->parent_dmat, ahc->shared_data_dmamap);
3928 1.96 fvdl bus_dmamap_destroy(ahc->parent_dmat, ahc->shared_data_dmamap);
3929 1.96 fvdl bus_dmamem_unmap(ahc->parent_dmat, (caddr_t)ahc->qoutfifo, ahc->shared_data_size);
3930 1.96 fvdl bus_dmamem_free(ahc->parent_dmat, &ahc->shared_data_seg, ahc->shared_data_nseg);
3931 1.86 ichiro break;
3932 1.96 fvdl case 0:
3933 1.86 ichiro break;
3934 1.86 ichiro }
3935 1.86 ichiro
3936 1.96 fvdl ahc_platform_free(ahc);
3937 1.96 fvdl for (i = 0; i < AHC_NUM_TARGETS; i++) {
3938 1.96 fvdl struct ahc_tmode_tstate *tstate;
3939 1.96 fvdl
3940 1.96 fvdl tstate = ahc->enabled_targets[i];
3941 1.96 fvdl if (tstate != NULL) {
3942 1.96 fvdl #if AHC_TARGET_MODE
3943 1.96 fvdl int j;
3944 1.96 fvdl
3945 1.96 fvdl for (j = 0; j < AHC_NUM_LUNS; j++) {
3946 1.96 fvdl struct ahc_tmode_lstate *lstate;
3947 1.96 fvdl
3948 1.96 fvdl lstate = tstate->enabled_luns[j];
3949 1.96 fvdl if (lstate != NULL) {
3950 1.96 fvdl /*xpt_free_path(lstate->path);*/
3951 1.96 fvdl free(lstate, M_DEVBUF);
3952 1.96 fvdl }
3953 1.96 fvdl }
3954 1.96 fvdl #endif
3955 1.96 fvdl free(tstate, M_DEVBUF);
3956 1.96 fvdl }
3957 1.96 fvdl }
3958 1.96 fvdl #if AHC_TARGET_MODE
3959 1.96 fvdl if (ahc->black_hole != NULL) {
3960 1.96 fvdl /*xpt_free_path(ahc->black_hole->path);*/
3961 1.96 fvdl free(ahc->black_hole, M_DEVBUF);
3962 1.96 fvdl }
3963 1.96 fvdl #endif
3964 1.104 fvdl #ifndef __NetBSD__
3965 1.96 fvdl if (ahc->name != NULL)
3966 1.96 fvdl free(ahc->name, M_DEVBUF);
3967 1.104 fvdl #endif
3968 1.96 fvdl if (ahc->seep_config != NULL)
3969 1.96 fvdl free(ahc->seep_config, M_DEVBUF);
3970 1.96 fvdl #ifndef __FreeBSD__
3971 1.96 fvdl free(ahc, M_DEVBUF);
3972 1.96 fvdl #endif
3973 1.96 fvdl return;
3974 1.42 fvdl }
3975 1.42 fvdl
3976 1.96 fvdl void
3977 1.96 fvdl ahc_shutdown(void *arg)
3978 1.42 fvdl {
3979 1.96 fvdl struct ahc_softc *ahc;
3980 1.96 fvdl int i;
3981 1.42 fvdl
3982 1.96 fvdl ahc = (struct ahc_softc *)arg;
3983 1.42 fvdl
3984 1.96 fvdl /* This will reset most registers to 0, but not all */
3985 1.96 fvdl ahc_reset(ahc);
3986 1.96 fvdl ahc_outb(ahc, SCSISEQ, 0);
3987 1.96 fvdl ahc_outb(ahc, SXFRCTL0, 0);
3988 1.96 fvdl ahc_outb(ahc, DSPCISTATUS, 0);
3989 1.42 fvdl
3990 1.96 fvdl for (i = TARG_SCSIRATE; i < SCSICONF; i++)
3991 1.96 fvdl ahc_outb(ahc, i, 0);
3992 1.42 fvdl }
3993 1.42 fvdl
3994 1.42 fvdl /*
3995 1.96 fvdl * Reset the controller and record some information about it
3996 1.96 fvdl * that is only available just after a reset.
3997 1.42 fvdl */
3998 1.42 fvdl int
3999 1.96 fvdl ahc_reset(struct ahc_softc *ahc)
4000 1.42 fvdl {
4001 1.96 fvdl u_int sblkctl;
4002 1.96 fvdl u_int sxfrctl1_a, sxfrctl1_b;
4003 1.96 fvdl int wait;
4004 1.96 fvdl
4005 1.96 fvdl /*
4006 1.96 fvdl * Preserve the value of the SXFRCTL1 register for all channels.
4007 1.96 fvdl * It contains settings that affect termination and we don't want
4008 1.96 fvdl * to disturb the integrity of the bus.
4009 1.96 fvdl */
4010 1.96 fvdl ahc_pause(ahc);
4011 1.96 fvdl if ((ahc_inb(ahc, HCNTRL) & CHIPRST) != 0) {
4012 1.96 fvdl /*
4013 1.96 fvdl * The chip has not been initialized since
4014 1.96 fvdl * PCI/EISA/VLB bus reset. Don't trust
4015 1.96 fvdl * "left over BIOS data".
4016 1.96 fvdl */
4017 1.96 fvdl ahc->flags |= AHC_NO_BIOS_INIT;
4018 1.96 fvdl }
4019 1.96 fvdl sxfrctl1_b = 0;
4020 1.96 fvdl if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7770) {
4021 1.96 fvdl u_int sblkctl;
4022 1.42 fvdl
4023 1.96 fvdl /*
4024 1.96 fvdl * Save channel B's settings in case this chip
4025 1.96 fvdl * is setup for TWIN channel operation.
4026 1.96 fvdl */
4027 1.96 fvdl sblkctl = ahc_inb(ahc, SBLKCTL);
4028 1.96 fvdl ahc_outb(ahc, SBLKCTL, sblkctl | SELBUSB);
4029 1.96 fvdl sxfrctl1_b = ahc_inb(ahc, SXFRCTL1);
4030 1.96 fvdl ahc_outb(ahc, SBLKCTL, sblkctl & ~SELBUSB);
4031 1.96 fvdl }
4032 1.96 fvdl sxfrctl1_a = ahc_inb(ahc, SXFRCTL1);
4033 1.42 fvdl
4034 1.96 fvdl ahc_outb(ahc, HCNTRL, CHIPRST | ahc->pause);
4035 1.42 fvdl
4036 1.42 fvdl /*
4037 1.96 fvdl * Ensure that the reset has finished. We delay 1000us
4038 1.96 fvdl * prior to reading the register to make sure the chip
4039 1.96 fvdl * has sufficiently completed its reset to handle register
4040 1.96 fvdl * accesses.
4041 1.42 fvdl */
4042 1.96 fvdl wait = 1000;
4043 1.96 fvdl do {
4044 1.96 fvdl ahc_delay(1000);
4045 1.96 fvdl } while (--wait && !(ahc_inb(ahc, HCNTRL) & CHIPRSTACK));
4046 1.42 fvdl
4047 1.96 fvdl if (wait == 0) {
4048 1.96 fvdl printf("%s: WARNING - Failed chip reset! "
4049 1.96 fvdl "Trying to initialize anyway.\n", ahc_name(ahc));
4050 1.42 fvdl }
4051 1.96 fvdl ahc_outb(ahc, HCNTRL, ahc->pause);
4052 1.42 fvdl
4053 1.96 fvdl /* Determine channel configuration */
4054 1.96 fvdl sblkctl = ahc_inb(ahc, SBLKCTL) & (SELBUSB|SELWIDE);
4055 1.96 fvdl /* No Twin Channel PCI cards */
4056 1.96 fvdl if ((ahc->chip & AHC_PCI) != 0)
4057 1.96 fvdl sblkctl &= ~SELBUSB;
4058 1.96 fvdl switch (sblkctl) {
4059 1.96 fvdl case 0:
4060 1.96 fvdl /* Single Narrow Channel */
4061 1.96 fvdl break;
4062 1.96 fvdl case 2:
4063 1.96 fvdl /* Wide Channel */
4064 1.96 fvdl ahc->features |= AHC_WIDE;
4065 1.96 fvdl break;
4066 1.96 fvdl case 8:
4067 1.96 fvdl /* Twin Channel */
4068 1.96 fvdl ahc->features |= AHC_TWIN;
4069 1.96 fvdl break;
4070 1.96 fvdl default:
4071 1.96 fvdl printf(" Unsupported adapter type (0x%x). Ignoring\n", sblkctl);
4072 1.96 fvdl return(-1);
4073 1.42 fvdl }
4074 1.42 fvdl
4075 1.96 fvdl /*
4076 1.96 fvdl * Reload sxfrctl1.
4077 1.96 fvdl *
4078 1.96 fvdl * We must always initialize STPWEN to 1 before we
4079 1.96 fvdl * restore the saved values. STPWEN is initialized
4080 1.96 fvdl * to a tri-state condition which can only be cleared
4081 1.96 fvdl * by turning it on.
4082 1.96 fvdl */
4083 1.96 fvdl if ((ahc->features & AHC_TWIN) != 0) {
4084 1.96 fvdl u_int sblkctl;
4085 1.42 fvdl
4086 1.96 fvdl sblkctl = ahc_inb(ahc, SBLKCTL);
4087 1.96 fvdl ahc_outb(ahc, SBLKCTL, sblkctl | SELBUSB);
4088 1.96 fvdl ahc_outb(ahc, SXFRCTL1, sxfrctl1_b);
4089 1.96 fvdl ahc_outb(ahc, SBLKCTL, sblkctl & ~SELBUSB);
4090 1.42 fvdl }
4091 1.96 fvdl ahc_outb(ahc, SXFRCTL1, sxfrctl1_a);
4092 1.42 fvdl
4093 1.96 fvdl #ifdef AHC_DUMP_SEQ
4094 1.96 fvdl if (ahc->init_level == 0)
4095 1.96 fvdl ahc_dumpseq(ahc);
4096 1.96 fvdl #endif
4097 1.42 fvdl
4098 1.96 fvdl return (0);
4099 1.42 fvdl }
4100 1.42 fvdl
4101 1.96 fvdl /*
4102 1.96 fvdl * Determine the number of SCBs available on the controller
4103 1.96 fvdl */
4104 1.96 fvdl int
4105 1.96 fvdl ahc_probe_scbs(struct ahc_softc *ahc) {
4106 1.96 fvdl int i;
4107 1.96 fvdl
4108 1.96 fvdl for (i = 0; i < AHC_SCB_MAX; i++) {
4109 1.42 fvdl
4110 1.96 fvdl ahc_outb(ahc, SCBPTR, i);
4111 1.96 fvdl ahc_outb(ahc, SCB_BASE, i);
4112 1.96 fvdl if (ahc_inb(ahc, SCB_BASE) != i)
4113 1.96 fvdl break;
4114 1.96 fvdl ahc_outb(ahc, SCBPTR, 0);
4115 1.96 fvdl if (ahc_inb(ahc, SCB_BASE) != 0)
4116 1.96 fvdl break;
4117 1.42 fvdl }
4118 1.96 fvdl return (i);
4119 1.42 fvdl }
4120 1.42 fvdl
4121 1.96 fvdl #if 0
4122 1.42 fvdl static void
4123 1.96 fvdl ahc_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
4124 1.42 fvdl {
4125 1.96 fvdl bus_addr_t *baddr;
4126 1.42 fvdl
4127 1.96 fvdl baddr = (bus_addr_t *)arg;
4128 1.96 fvdl *baddr = segs->ds_addr;
4129 1.42 fvdl }
4130 1.42 fvdl #endif
4131 1.42 fvdl
4132 1.42 fvdl static void
4133 1.96 fvdl ahc_build_free_scb_list(struct ahc_softc *ahc)
4134 1.42 fvdl {
4135 1.96 fvdl int scbsize;
4136 1.96 fvdl int i;
4137 1.59 pk
4138 1.96 fvdl scbsize = 32;
4139 1.96 fvdl if ((ahc->flags & AHC_LSCBS_ENABLED) != 0)
4140 1.96 fvdl scbsize = 64;
4141 1.42 fvdl
4142 1.96 fvdl for (i = 0; i < ahc->scb_data->maxhscbs; i++) {
4143 1.96 fvdl int j;
4144 1.42 fvdl
4145 1.96 fvdl ahc_outb(ahc, SCBPTR, i);
4146 1.42 fvdl
4147 1.42 fvdl /*
4148 1.96 fvdl * Touch all SCB bytes to avoid parity errors
4149 1.96 fvdl * should one of our debugging routines read
4150 1.96 fvdl * an otherwise uninitiatlized byte.
4151 1.42 fvdl */
4152 1.96 fvdl for (j = 0; j < scbsize; j++)
4153 1.96 fvdl ahc_outb(ahc, SCB_BASE+j, 0xFF);
4154 1.42 fvdl
4155 1.96 fvdl /* Clear the control byte. */
4156 1.96 fvdl ahc_outb(ahc, SCB_CONTROL, 0);
4157 1.42 fvdl
4158 1.96 fvdl /* Set the next pointer */
4159 1.96 fvdl if ((ahc->flags & AHC_PAGESCBS) != 0)
4160 1.96 fvdl ahc_outb(ahc, SCB_NEXT, i+1);
4161 1.96 fvdl else
4162 1.96 fvdl ahc_outb(ahc, SCB_NEXT, SCB_LIST_NULL);
4163 1.42 fvdl
4164 1.96 fvdl /* Make the tag number, SCSIID, and lun invalid */
4165 1.96 fvdl ahc_outb(ahc, SCB_TAG, SCB_LIST_NULL);
4166 1.96 fvdl ahc_outb(ahc, SCB_SCSIID, 0xFF);
4167 1.96 fvdl ahc_outb(ahc, SCB_LUN, 0xFF);
4168 1.96 fvdl }
4169 1.42 fvdl
4170 1.96 fvdl /* Make sure that the last SCB terminates the free list */
4171 1.96 fvdl ahc_outb(ahc, SCBPTR, i-1);
4172 1.96 fvdl ahc_outb(ahc, SCB_NEXT, SCB_LIST_NULL);
4173 1.96 fvdl }
4174 1.42 fvdl
4175 1.96 fvdl static int
4176 1.96 fvdl ahc_init_scbdata(struct ahc_softc *ahc)
4177 1.96 fvdl {
4178 1.96 fvdl struct scb_data *scb_data;
4179 1.42 fvdl
4180 1.96 fvdl scb_data = ahc->scb_data;
4181 1.96 fvdl SLIST_INIT(&scb_data->free_scbs);
4182 1.96 fvdl SLIST_INIT(&scb_data->sg_maps);
4183 1.42 fvdl
4184 1.96 fvdl /* Allocate SCB resources */
4185 1.96 fvdl scb_data->scbarray =
4186 1.96 fvdl (struct scb *)malloc(sizeof(struct scb) * AHC_SCB_MAX_ALLOC,
4187 1.96 fvdl M_DEVBUF, M_NOWAIT);
4188 1.96 fvdl if (scb_data->scbarray == NULL)
4189 1.96 fvdl return (ENOMEM);
4190 1.96 fvdl memset(scb_data->scbarray, 0, sizeof(struct scb) * AHC_SCB_MAX_ALLOC);
4191 1.42 fvdl
4192 1.96 fvdl /* Determine the number of hardware SCBs and initialize them */
4193 1.42 fvdl
4194 1.96 fvdl scb_data->maxhscbs = ahc_probe_scbs(ahc);
4195 1.96 fvdl if ((ahc->flags & AHC_PAGESCBS) != 0) {
4196 1.96 fvdl /* SCB 0 heads the free list */
4197 1.96 fvdl ahc_outb(ahc, FREE_SCBH, 0);
4198 1.96 fvdl } else {
4199 1.96 fvdl ahc_outb(ahc, FREE_SCBH, SCB_LIST_NULL);
4200 1.42 fvdl }
4201 1.42 fvdl
4202 1.96 fvdl if (ahc->scb_data->maxhscbs == 0) {
4203 1.96 fvdl printf("%s: No SCB space found\n", ahc_name(ahc));
4204 1.96 fvdl return (ENXIO);
4205 1.42 fvdl }
4206 1.42 fvdl
4207 1.96 fvdl ahc_build_free_scb_list(ahc);
4208 1.59 pk
4209 1.42 fvdl /*
4210 1.96 fvdl * Create our DMA tags. These tags define the kinds of device
4211 1.96 fvdl * accessible memory allocations and memory mappings we will
4212 1.96 fvdl * need to perform during normal operation.
4213 1.96 fvdl *
4214 1.96 fvdl * Unless we need to further restrict the allocation, we rely
4215 1.96 fvdl * on the restrictions of the parent dmat, hence the common
4216 1.96 fvdl * use of MAXADDR and MAXSIZE.
4217 1.42 fvdl */
4218 1.6 mycroft
4219 1.96 fvdl if (ahc_createdmamem(ahc->parent_dmat,
4220 1.96 fvdl AHC_SCB_MAX * sizeof(struct hardware_scb), ahc->sc_dmaflags,
4221 1.96 fvdl &scb_data->hscb_dmamap,
4222 1.96 fvdl (caddr_t *)&scb_data->hscbs, &scb_data->hscb_busaddr,
4223 1.96 fvdl &scb_data->hscb_seg, &scb_data->hscb_nseg, ahc_name(ahc),
4224 1.96 fvdl "hardware SCB structures") < 0)
4225 1.96 fvdl goto error_exit;
4226 1.96 fvdl
4227 1.96 fvdl scb_data->init_level++;
4228 1.96 fvdl
4229 1.96 fvdl if (ahc_createdmamem(ahc->parent_dmat,
4230 1.96 fvdl AHC_SCB_MAX * sizeof(struct scsipi_sense_data), ahc->sc_dmaflags,
4231 1.96 fvdl &scb_data->sense_dmamap, (caddr_t *)&scb_data->sense,
4232 1.96 fvdl &scb_data->sense_busaddr, &scb_data->sense_seg,
4233 1.96 fvdl &scb_data->sense_nseg, ahc_name(ahc), "sense buffers") < 0)
4234 1.96 fvdl goto error_exit;
4235 1.96 fvdl
4236 1.96 fvdl scb_data->init_level++;
4237 1.6 mycroft
4238 1.96 fvdl /* Perform initial CCB allocation */
4239 1.96 fvdl memset(scb_data->hscbs, 0,
4240 1.96 fvdl AHC_SCB_MAX_ALLOC * sizeof(struct hardware_scb));
4241 1.96 fvdl ahc_alloc_scbs(ahc);
4242 1.104 fvdl scb_data->init_level++;
4243 1.1 mycroft
4244 1.96 fvdl if (scb_data->numscbs == 0) {
4245 1.96 fvdl printf("%s: ahc_init_scbdata - "
4246 1.96 fvdl "Unable to allocate initial scbs\n",
4247 1.96 fvdl ahc_name(ahc));
4248 1.96 fvdl goto error_exit;
4249 1.42 fvdl }
4250 1.6 mycroft
4251 1.96 fvdl /*
4252 1.96 fvdl * Tell the sequencer which SCB will be the next one it receives.
4253 1.96 fvdl */
4254 1.96 fvdl ahc->next_queued_scb = ahc_get_scb(ahc);
4255 1.96 fvdl ahc_outb(ahc, NEXT_QUEUED_SCB, ahc->next_queued_scb->hscb->tag);
4256 1.96 fvdl
4257 1.96 fvdl /*
4258 1.96 fvdl * Note that we were successfull
4259 1.96 fvdl */
4260 1.96 fvdl return (0);
4261 1.6 mycroft
4262 1.96 fvdl error_exit:
4263 1.42 fvdl
4264 1.96 fvdl return (ENOMEM);
4265 1.96 fvdl }
4266 1.6 mycroft
4267 1.96 fvdl static void
4268 1.96 fvdl ahc_fini_scbdata(struct ahc_softc *ahc)
4269 1.96 fvdl {
4270 1.96 fvdl struct scb_data *scb_data;
4271 1.6 mycroft
4272 1.96 fvdl scb_data = ahc->scb_data;
4273 1.96 fvdl if (scb_data == NULL)
4274 1.96 fvdl return;
4275 1.42 fvdl
4276 1.96 fvdl switch (scb_data->init_level) {
4277 1.96 fvdl default:
4278 1.104 fvdl case 5:
4279 1.96 fvdl {
4280 1.96 fvdl struct sg_map_node *sg_map;
4281 1.42 fvdl
4282 1.96 fvdl while ((sg_map = SLIST_FIRST(&scb_data->sg_maps))!= NULL) {
4283 1.96 fvdl SLIST_REMOVE_HEAD(&scb_data->sg_maps, links);
4284 1.96 fvdl ahc_freedmamem(ahc->parent_dmat, PAGE_SIZE,
4285 1.96 fvdl sg_map->sg_dmamap, (caddr_t)sg_map->sg_vaddr,
4286 1.96 fvdl &sg_map->sg_dmasegs, sg_map->sg_nseg);
4287 1.96 fvdl free(sg_map, M_DEVBUF);
4288 1.96 fvdl }
4289 1.96 fvdl }
4290 1.96 fvdl /*FALLTHROUGH*/
4291 1.104 fvdl case 4:
4292 1.96 fvdl ahc_freedmamem(ahc->parent_dmat,
4293 1.96 fvdl AHC_SCB_MAX * sizeof(struct scsipi_sense_data),
4294 1.96 fvdl scb_data->sense_dmamap, (caddr_t)scb_data->sense,
4295 1.96 fvdl &scb_data->sense_seg, scb_data->sense_nseg);
4296 1.96 fvdl /*FALLTHROUGH*/
4297 1.104 fvdl case 3:
4298 1.96 fvdl ahc_freedmamem(ahc->parent_dmat,
4299 1.96 fvdl AHC_SCB_MAX * sizeof(struct hardware_scb),
4300 1.96 fvdl scb_data->hscb_dmamap, (caddr_t)scb_data->hscbs,
4301 1.96 fvdl &scb_data->hscb_seg, scb_data->hscb_nseg);
4302 1.96 fvdl /*FALLTHROUGH*/
4303 1.104 fvdl case 2:
4304 1.104 fvdl case 1:
4305 1.104 fvdl case 0:
4306 1.104 fvdl break;
4307 1.96 fvdl }
4308 1.96 fvdl if (scb_data->scbarray != NULL)
4309 1.96 fvdl free(scb_data->scbarray, M_DEVBUF);
4310 1.96 fvdl }
4311 1.6 mycroft
4312 1.96 fvdl void
4313 1.96 fvdl ahc_alloc_scbs(struct ahc_softc *ahc)
4314 1.96 fvdl {
4315 1.96 fvdl struct scb_data *scb_data;
4316 1.96 fvdl struct scb *next_scb;
4317 1.96 fvdl struct sg_map_node *sg_map;
4318 1.96 fvdl bus_addr_t physaddr;
4319 1.96 fvdl struct ahc_dma_seg *segs;
4320 1.96 fvdl int newcount;
4321 1.96 fvdl int i;
4322 1.6 mycroft
4323 1.96 fvdl scb_data = ahc->scb_data;
4324 1.96 fvdl if (scb_data->numscbs >= AHC_SCB_MAX_ALLOC)
4325 1.96 fvdl /* Can't allocate any more */
4326 1.96 fvdl return;
4327 1.6 mycroft
4328 1.96 fvdl next_scb = &scb_data->scbarray[scb_data->numscbs];
4329 1.6 mycroft
4330 1.96 fvdl sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT);
4331 1.42 fvdl
4332 1.96 fvdl if (sg_map == NULL)
4333 1.96 fvdl return;
4334 1.6 mycroft
4335 1.96 fvdl /* Allocate S/G space for the next batch of SCBS */
4336 1.96 fvdl if (ahc_createdmamem(ahc->parent_dmat, PAGE_SIZE, ahc->sc_dmaflags,
4337 1.96 fvdl &sg_map->sg_dmamap,
4338 1.96 fvdl (caddr_t *)&sg_map->sg_vaddr, &sg_map->sg_physaddr,
4339 1.96 fvdl &sg_map->sg_dmasegs, &sg_map->sg_nseg, ahc_name(ahc),
4340 1.96 fvdl "SG space") < 0) {
4341 1.96 fvdl free(sg_map, M_DEVBUF);
4342 1.96 fvdl return;
4343 1.96 fvdl }
4344 1.6 mycroft
4345 1.96 fvdl SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links);
4346 1.6 mycroft
4347 1.96 fvdl segs = sg_map->sg_vaddr;
4348 1.96 fvdl physaddr = sg_map->sg_physaddr;
4349 1.6 mycroft
4350 1.96 fvdl newcount = (PAGE_SIZE / (AHC_NSEG * sizeof(struct ahc_dma_seg)));
4351 1.96 fvdl newcount = MIN(newcount, (AHC_SCB_MAX_ALLOC - scb_data->numscbs));
4352 1.96 fvdl for (i = 0; i < newcount; i++) {
4353 1.96 fvdl struct scb_platform_data *pdata;
4354 1.96 fvdl int error;
4355 1.6 mycroft
4356 1.96 fvdl pdata = (struct scb_platform_data *)malloc(sizeof(*pdata),
4357 1.96 fvdl M_DEVBUF, M_NOWAIT);
4358 1.96 fvdl if (pdata == NULL)
4359 1.96 fvdl break;
4360 1.96 fvdl next_scb->platform_data = pdata;
4361 1.96 fvdl next_scb->sg_map = sg_map;
4362 1.96 fvdl next_scb->sg_list = segs;
4363 1.42 fvdl /*
4364 1.96 fvdl * The sequencer always starts with the second entry.
4365 1.96 fvdl * The first entry is embedded in the scb.
4366 1.42 fvdl */
4367 1.96 fvdl next_scb->sg_list_phys = physaddr + sizeof(struct ahc_dma_seg);
4368 1.96 fvdl next_scb->ahc_softc = ahc;
4369 1.96 fvdl next_scb->flags = SCB_FREE;
4370 1.96 fvdl
4371 1.96 fvdl error = bus_dmamap_create(ahc->parent_dmat,
4372 1.103 tls AHC_MAXTRANSFER_SIZE, AHC_NSEG, MAXPHYS, 0,
4373 1.96 fvdl BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW,
4374 1.96 fvdl &next_scb->dmamap);
4375 1.96 fvdl if (error != 0)
4376 1.96 fvdl break;
4377 1.6 mycroft
4378 1.96 fvdl next_scb->hscb = &scb_data->hscbs[scb_data->numscbs];
4379 1.96 fvdl next_scb->hscb->tag = ahc->scb_data->numscbs;
4380 1.96 fvdl SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs,
4381 1.96 fvdl next_scb, links.sle);
4382 1.96 fvdl segs += AHC_NSEG;
4383 1.96 fvdl physaddr += (AHC_NSEG * sizeof(struct ahc_dma_seg));
4384 1.96 fvdl next_scb++;
4385 1.96 fvdl ahc->scb_data->numscbs++;
4386 1.6 mycroft }
4387 1.1 mycroft }
4388 1.1 mycroft
4389 1.96 fvdl void
4390 1.96 fvdl ahc_controller_info(struct ahc_softc *ahc, char *buf)
4391 1.1 mycroft {
4392 1.96 fvdl int len;
4393 1.42 fvdl
4394 1.96 fvdl len = sprintf(buf, "%s: ", ahc_chip_names[ahc->chip & AHC_CHIPID_MASK]);
4395 1.96 fvdl buf += len;
4396 1.96 fvdl if ((ahc->features & AHC_TWIN) != 0)
4397 1.96 fvdl len = sprintf(buf, "Twin Channel, A SCSI Id=%d, "
4398 1.96 fvdl "B SCSI Id=%d, primary %c, ",
4399 1.96 fvdl ahc->our_id, ahc->our_id_b,
4400 1.96 fvdl (ahc->flags & AHC_PRIMARY_CHANNEL) + 'A');
4401 1.96 fvdl else {
4402 1.96 fvdl const char *speed;
4403 1.96 fvdl const char *type;
4404 1.96 fvdl
4405 1.96 fvdl speed = "";
4406 1.96 fvdl if ((ahc->features & AHC_ULTRA) != 0) {
4407 1.96 fvdl speed = "Ultra ";
4408 1.96 fvdl } else if ((ahc->features & AHC_DT) != 0) {
4409 1.96 fvdl speed = "Ultra160 ";
4410 1.96 fvdl } else if ((ahc->features & AHC_ULTRA2) != 0) {
4411 1.96 fvdl speed = "Ultra2 ";
4412 1.96 fvdl }
4413 1.96 fvdl if ((ahc->features & AHC_WIDE) != 0) {
4414 1.96 fvdl type = "Wide";
4415 1.96 fvdl } else {
4416 1.96 fvdl type = "Single";
4417 1.96 fvdl }
4418 1.96 fvdl len = sprintf(buf, "%s%s Channel %c, SCSI Id=%d, ",
4419 1.96 fvdl speed, type, ahc->channel, ahc->our_id);
4420 1.42 fvdl }
4421 1.96 fvdl buf += len;
4422 1.42 fvdl
4423 1.96 fvdl if ((ahc->flags & AHC_PAGESCBS) != 0)
4424 1.96 fvdl sprintf(buf, "%d/%d SCBs",
4425 1.96 fvdl ahc->scb_data->maxhscbs, AHC_MAX_QUEUE);
4426 1.96 fvdl else
4427 1.96 fvdl sprintf(buf, "%d SCBs", ahc->scb_data->maxhscbs);
4428 1.42 fvdl }
4429 1.1 mycroft
4430 1.96 fvdl /*
4431 1.96 fvdl * Start the board, ready for normal operation
4432 1.96 fvdl */
4433 1.96 fvdl int
4434 1.96 fvdl ahc_init(struct ahc_softc *ahc)
4435 1.42 fvdl {
4436 1.96 fvdl int max_targ;
4437 1.96 fvdl int i;
4438 1.96 fvdl int term;
4439 1.96 fvdl u_int scsi_conf;
4440 1.96 fvdl u_int scsiseq_template;
4441 1.96 fvdl u_int ultraenb;
4442 1.96 fvdl u_int discenable;
4443 1.96 fvdl u_int tagenable;
4444 1.96 fvdl size_t driver_data_size;
4445 1.96 fvdl uint32_t physaddr;
4446 1.42 fvdl
4447 1.96 fvdl #ifdef AHC_DEBUG
4448 1.96 fvdl if ((ahc_debug & AHC_DEBUG_SEQUENCER) != 0)
4449 1.96 fvdl ahc->flags |= AHC_SEQUENCER_DEBUG;
4450 1.96 fvdl #endif
4451 1.42 fvdl
4452 1.96 fvdl #ifdef AHC_PRINT_SRAM
4453 1.96 fvdl printf("Scratch Ram:");
4454 1.96 fvdl for (i = 0x20; i < 0x5f; i++) {
4455 1.96 fvdl if (((i % 8) == 0) && (i != 0)) {
4456 1.96 fvdl printf ("\n ");
4457 1.42 fvdl }
4458 1.96 fvdl printf (" 0x%x", ahc_inb(ahc, i));
4459 1.42 fvdl }
4460 1.96 fvdl if ((ahc->features & AHC_MORE_SRAM) != 0) {
4461 1.96 fvdl for (i = 0x70; i < 0x7f; i++) {
4462 1.96 fvdl if (((i % 8) == 0) && (i != 0)) {
4463 1.96 fvdl printf ("\n ");
4464 1.96 fvdl }
4465 1.96 fvdl printf (" 0x%x", ahc_inb(ahc, i));
4466 1.96 fvdl }
4467 1.42 fvdl }
4468 1.96 fvdl printf ("\n");
4469 1.96 fvdl /*
4470 1.96 fvdl * Reading uninitialized scratch ram may
4471 1.96 fvdl * generate parity errors.
4472 1.96 fvdl */
4473 1.96 fvdl ahc_outb(ahc, CLRINT, CLRPARERR);
4474 1.96 fvdl ahc_outb(ahc, CLRINT, CLRBRKADRINT);
4475 1.96 fvdl #endif
4476 1.96 fvdl max_targ = 15;
4477 1.6 mycroft
4478 1.42 fvdl /*
4479 1.96 fvdl * Assume we have a board at this stage and it has been reset.
4480 1.42 fvdl */
4481 1.96 fvdl if ((ahc->flags & AHC_USEDEFAULTS) != 0)
4482 1.96 fvdl ahc->our_id = ahc->our_id_b = 7;
4483 1.96 fvdl
4484 1.59 pk /*
4485 1.96 fvdl * Default to allowing initiator operations.
4486 1.59 pk */
4487 1.96 fvdl ahc->flags |= AHC_INITIATORROLE;
4488 1.6 mycroft
4489 1.1 mycroft /*
4490 1.96 fvdl * Only allow target mode features if this unit has them enabled.
4491 1.1 mycroft */
4492 1.96 fvdl //if ((AHC_TMODE_ENABLE & (0x1 << ahc->unit)) == 0)
4493 1.96 fvdl ahc->features &= ~AHC_TARGETMODE;
4494 1.42 fvdl
4495 1.96 fvdl /*
4496 1.96 fvdl * DMA tag for our command fifos and other data in system memory
4497 1.96 fvdl * the card's sequencer must be able to access. For initiator
4498 1.96 fvdl * roles, we need to allocate space for the qinfifo and qoutfifo.
4499 1.96 fvdl * The qinfifo and qoutfifo are composed of 256 1 byte elements.
4500 1.96 fvdl * When providing for the target mode role, we must additionally
4501 1.96 fvdl * provide space for the incoming target command fifo and an extra
4502 1.105 wiz * byte to deal with a DMA bug in some chip versions.
4503 1.96 fvdl */
4504 1.96 fvdl driver_data_size = 2 * 256 * sizeof(uint8_t);
4505 1.96 fvdl if ((ahc->features & AHC_TARGETMODE) != 0)
4506 1.96 fvdl driver_data_size += AHC_TMODE_CMDS * sizeof(struct target_cmd)
4507 1.96 fvdl + /*DMA WideOdd Bug Buffer*/1;
4508 1.42 fvdl
4509 1.96 fvdl if (ahc_createdmamem(ahc->parent_dmat, driver_data_size,
4510 1.96 fvdl ahc->sc_dmaflags,
4511 1.96 fvdl &ahc->shared_data_dmamap, (caddr_t *)&ahc->qoutfifo,
4512 1.96 fvdl &ahc->shared_data_busaddr, &ahc->shared_data_seg,
4513 1.96 fvdl &ahc->shared_data_nseg, ahc_name(ahc), "shared data") < 0)
4514 1.96 fvdl return (ENOMEM);
4515 1.6 mycroft
4516 1.96 fvdl ahc->init_level++;
4517 1.1 mycroft
4518 1.96 fvdl if ((ahc->features & AHC_TARGETMODE) != 0) {
4519 1.96 fvdl ahc->targetcmds = (struct target_cmd *)ahc->qoutfifo;
4520 1.96 fvdl ahc->qoutfifo = (uint8_t *)&ahc->targetcmds[AHC_TMODE_CMDS];
4521 1.96 fvdl ahc->dma_bug_buf = ahc->shared_data_busaddr
4522 1.96 fvdl + driver_data_size - 1;
4523 1.96 fvdl /* All target command blocks start out invalid. */
4524 1.96 fvdl for (i = 0; i < AHC_TMODE_CMDS; i++)
4525 1.96 fvdl ahc->targetcmds[i].cmd_valid = 0;
4526 1.96 fvdl ahc_sync_tqinfifo(ahc, BUS_DMASYNC_PREREAD);
4527 1.96 fvdl ahc->tqinfifonext = 1;
4528 1.96 fvdl ahc_outb(ahc, KERNEL_TQINPOS, ahc->tqinfifonext - 1);
4529 1.96 fvdl ahc_outb(ahc, TQINPOS, ahc->tqinfifonext);
4530 1.96 fvdl ahc->qoutfifo = (uint8_t *)&ahc->targetcmds[256];
4531 1.42 fvdl }
4532 1.96 fvdl ahc->qinfifo = &ahc->qoutfifo[256];
4533 1.14 gibbs
4534 1.96 fvdl ahc->init_level++;
4535 1.14 gibbs
4536 1.96 fvdl /* Allocate SCB data now that buffer_dmat is initialized */
4537 1.96 fvdl if (ahc->scb_data->maxhscbs == 0)
4538 1.96 fvdl if (ahc_init_scbdata(ahc) != 0)
4539 1.96 fvdl return (ENOMEM);
4540 1.42 fvdl
4541 1.96 fvdl if (bootverbose)
4542 1.96 fvdl printf("%s: found %d SCBs\n", ahc_name(ahc),
4543 1.96 fvdl ahc->scb_data->maxhscbs);
4544 1.42 fvdl
4545 1.96 fvdl /*
4546 1.96 fvdl * Allocate a tstate to house information for our
4547 1.96 fvdl * initiator presence on the bus as well as the user
4548 1.96 fvdl * data for any target mode initiator.
4549 1.96 fvdl */
4550 1.96 fvdl if (ahc_alloc_tstate(ahc, ahc->our_id, 'A') == NULL) {
4551 1.96 fvdl printf("%s: unable to allocate ahc_tmode_tstate. "
4552 1.96 fvdl "Failing attach\n", ahc_name(ahc));
4553 1.96 fvdl return (ENOMEM);
4554 1.96 fvdl }
4555 1.42 fvdl
4556 1.96 fvdl if ((ahc->features & AHC_TWIN) != 0) {
4557 1.96 fvdl if (ahc_alloc_tstate(ahc, ahc->our_id_b, 'B') == NULL) {
4558 1.96 fvdl printf("%s: unable to allocate ahc_tmode_tstate. "
4559 1.96 fvdl "Failing attach\n", ahc_name(ahc));
4560 1.96 fvdl return (ENOMEM);
4561 1.96 fvdl }
4562 1.96 fvdl }
4563 1.42 fvdl
4564 1.96 fvdl ahc_outb(ahc, SEQ_FLAGS, 0);
4565 1.96 fvdl ahc_outb(ahc, SEQ_FLAGS2, 0);
4566 1.42 fvdl
4567 1.96 fvdl if (ahc->scb_data->maxhscbs < AHC_SCB_MAX_ALLOC) {
4568 1.96 fvdl ahc->flags |= AHC_PAGESCBS;
4569 1.96 fvdl } else {
4570 1.96 fvdl ahc->flags &= ~AHC_PAGESCBS;
4571 1.96 fvdl }
4572 1.42 fvdl
4573 1.96 fvdl #ifdef AHC_DEBUG
4574 1.96 fvdl if (ahc_debug & AHC_SHOW_MISC) {
4575 1.97 bjh21 printf("%s: hardware scb %lu bytes; kernel scb %lu bytes; "
4576 1.97 bjh21 "ahc_dma %lu bytes\n",
4577 1.96 fvdl ahc_name(ahc),
4578 1.97 bjh21 (u_long)sizeof(struct hardware_scb),
4579 1.97 bjh21 (u_long)sizeof(struct scb),
4580 1.97 bjh21 (u_long)sizeof(struct ahc_dma_seg));
4581 1.96 fvdl }
4582 1.96 fvdl #endif /* AHC_DEBUG */
4583 1.42 fvdl
4584 1.96 fvdl /* Set the SCSI Id, SXFRCTL0, SXFRCTL1, and SIMODE1, for both channels*/
4585 1.96 fvdl if (ahc->features & AHC_TWIN) {
4586 1.42 fvdl
4587 1.42 fvdl /*
4588 1.96 fvdl * The device is gated to channel B after a chip reset,
4589 1.96 fvdl * so set those values first
4590 1.42 fvdl */
4591 1.96 fvdl ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) | SELBUSB);
4592 1.96 fvdl term = (ahc->flags & AHC_TERM_ENB_B) != 0 ? STPWEN : 0;
4593 1.96 fvdl ahc_outb(ahc, SCSIID, ahc->our_id_b);
4594 1.96 fvdl scsi_conf = ahc_inb(ahc, SCSICONF + 1);
4595 1.96 fvdl ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL))
4596 1.96 fvdl |term|ahc->seltime_b|ENSTIMER|ACTNEGEN);
4597 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0)
4598 1.96 fvdl ahc_outb(ahc, SIMODE0, ahc_inb(ahc, SIMODE0)|ENIOERR);
4599 1.96 fvdl ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
4600 1.96 fvdl ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN);
4601 1.96 fvdl
4602 1.96 fvdl if ((scsi_conf & RESET_SCSI) != 0
4603 1.96 fvdl && (ahc->flags & AHC_INITIATORROLE) != 0)
4604 1.96 fvdl ahc->flags |= AHC_RESET_BUS_B;
4605 1.96 fvdl
4606 1.96 fvdl /* Select Channel A */
4607 1.96 fvdl ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~SELBUSB);
4608 1.42 fvdl }
4609 1.42 fvdl
4610 1.96 fvdl term = (ahc->flags & AHC_TERM_ENB_A) != 0 ? STPWEN : 0;
4611 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0)
4612 1.96 fvdl ahc_outb(ahc, SCSIID_ULTRA2, ahc->our_id);
4613 1.96 fvdl else
4614 1.96 fvdl ahc_outb(ahc, SCSIID, ahc->our_id);
4615 1.96 fvdl scsi_conf = ahc_inb(ahc, SCSICONF);
4616 1.96 fvdl ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL))
4617 1.96 fvdl |term|ahc->seltime
4618 1.96 fvdl |ENSTIMER|ACTNEGEN);
4619 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0)
4620 1.96 fvdl ahc_outb(ahc, SIMODE0, ahc_inb(ahc, SIMODE0)|ENIOERR);
4621 1.96 fvdl ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
4622 1.96 fvdl ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN);
4623 1.96 fvdl
4624 1.96 fvdl if ((scsi_conf & RESET_SCSI) != 0
4625 1.96 fvdl && (ahc->flags & AHC_INITIATORROLE) != 0)
4626 1.96 fvdl ahc->flags |= AHC_RESET_BUS_A;
4627 1.96 fvdl
4628 1.96 fvdl /*
4629 1.96 fvdl * Look at the information that board initialization or
4630 1.96 fvdl * the board bios has left us.
4631 1.96 fvdl */
4632 1.96 fvdl ultraenb = 0;
4633 1.96 fvdl tagenable = ALL_TARGETS_MASK;
4634 1.42 fvdl
4635 1.96 fvdl /* Grab the disconnection disable table and invert it for our needs */
4636 1.96 fvdl if ((ahc->flags & AHC_USEDEFAULTS) != 0) {
4637 1.96 fvdl printf("%s: Host Adapter Bios disabled. Using default SCSI "
4638 1.96 fvdl "device parameters\n", ahc_name(ahc));
4639 1.96 fvdl ahc->flags |= AHC_EXTENDED_TRANS_A|AHC_EXTENDED_TRANS_B|
4640 1.96 fvdl AHC_TERM_ENB_A|AHC_TERM_ENB_B;
4641 1.96 fvdl discenable = ALL_TARGETS_MASK;
4642 1.96 fvdl if ((ahc->features & AHC_ULTRA) != 0)
4643 1.96 fvdl ultraenb = ALL_TARGETS_MASK;
4644 1.96 fvdl } else {
4645 1.96 fvdl discenable = ~((ahc_inb(ahc, DISC_DSB + 1) << 8)
4646 1.96 fvdl | ahc_inb(ahc, DISC_DSB));
4647 1.96 fvdl if ((ahc->features & (AHC_ULTRA|AHC_ULTRA2)) != 0)
4648 1.96 fvdl ultraenb = (ahc_inb(ahc, ULTRA_ENB + 1) << 8)
4649 1.96 fvdl | ahc_inb(ahc, ULTRA_ENB);
4650 1.96 fvdl }
4651 1.42 fvdl
4652 1.96 fvdl if ((ahc->features & (AHC_WIDE|AHC_TWIN)) == 0)
4653 1.96 fvdl max_targ = 7;
4654 1.42 fvdl
4655 1.96 fvdl for (i = 0; i <= max_targ; i++) {
4656 1.96 fvdl struct ahc_initiator_tinfo *tinfo;
4657 1.96 fvdl struct ahc_tmode_tstate *tstate;
4658 1.96 fvdl u_int our_id;
4659 1.96 fvdl u_int target_id;
4660 1.96 fvdl char channel;
4661 1.42 fvdl
4662 1.96 fvdl channel = 'A';
4663 1.96 fvdl our_id = ahc->our_id;
4664 1.96 fvdl target_id = i;
4665 1.96 fvdl if (i > 7 && (ahc->features & AHC_TWIN) != 0) {
4666 1.96 fvdl channel = 'B';
4667 1.96 fvdl our_id = ahc->our_id_b;
4668 1.96 fvdl target_id = i % 8;
4669 1.96 fvdl }
4670 1.96 fvdl tinfo = ahc_fetch_transinfo(ahc, channel, our_id,
4671 1.96 fvdl target_id, &tstate);
4672 1.96 fvdl /* Default to async narrow across the board */
4673 1.96 fvdl memset(tinfo, 0, sizeof(*tinfo));
4674 1.96 fvdl if (ahc->flags & AHC_USEDEFAULTS) {
4675 1.96 fvdl if ((ahc->features & AHC_WIDE) != 0)
4676 1.96 fvdl tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT;
4677 1.42 fvdl
4678 1.42 fvdl /*
4679 1.96 fvdl * These will be truncated when we determine the
4680 1.96 fvdl * connection type we have with the target.
4681 1.42 fvdl */
4682 1.96 fvdl tinfo->user.period = ahc_syncrates->period;
4683 1.96 fvdl tinfo->user.offset = ~0;
4684 1.96 fvdl } else {
4685 1.96 fvdl u_int scsirate;
4686 1.96 fvdl uint16_t mask;
4687 1.42 fvdl
4688 1.96 fvdl /* Take the settings leftover in scratch RAM. */
4689 1.96 fvdl scsirate = ahc_inb(ahc, TARG_SCSIRATE + i);
4690 1.96 fvdl mask = (0x01 << i);
4691 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0) {
4692 1.96 fvdl u_int offset;
4693 1.96 fvdl u_int maxsync;
4694 1.42 fvdl
4695 1.96 fvdl if ((scsirate & SOFS) == 0x0F) {
4696 1.96 fvdl /*
4697 1.96 fvdl * Haven't negotiated yet,
4698 1.96 fvdl * so the format is different.
4699 1.96 fvdl */
4700 1.96 fvdl scsirate = (scsirate & SXFR) >> 4
4701 1.96 fvdl | (ultraenb & mask)
4702 1.96 fvdl ? 0x08 : 0x0
4703 1.96 fvdl | (scsirate & WIDEXFER);
4704 1.96 fvdl offset = MAX_OFFSET_ULTRA2;
4705 1.96 fvdl } else
4706 1.96 fvdl offset = ahc_inb(ahc, TARG_OFFSET + i);
4707 1.96 fvdl if ((scsirate & ~WIDEXFER) == 0 && offset != 0)
4708 1.96 fvdl /* Set to the lowest sync rate, 5MHz */
4709 1.96 fvdl scsirate |= 0x1c;
4710 1.96 fvdl maxsync = AHC_SYNCRATE_ULTRA2;
4711 1.96 fvdl if ((ahc->features & AHC_DT) != 0)
4712 1.96 fvdl maxsync = AHC_SYNCRATE_DT;
4713 1.96 fvdl tinfo->user.period =
4714 1.96 fvdl ahc_find_period(ahc, scsirate, maxsync);
4715 1.96 fvdl if (offset == 0)
4716 1.96 fvdl tinfo->user.period = 0;
4717 1.96 fvdl else
4718 1.96 fvdl tinfo->user.offset = ~0;
4719 1.96 fvdl if ((scsirate & SXFR_ULTRA2) <= 8/*10MHz*/
4720 1.96 fvdl && (ahc->features & AHC_DT) != 0)
4721 1.96 fvdl tinfo->user.ppr_options =
4722 1.96 fvdl MSG_EXT_PPR_DT_REQ;
4723 1.96 fvdl } else if ((scsirate & SOFS) != 0) {
4724 1.96 fvdl if ((scsirate & SXFR) == 0x40
4725 1.96 fvdl && (ultraenb & mask) != 0) {
4726 1.96 fvdl /* Treat 10MHz as a non-ultra speed */
4727 1.96 fvdl scsirate &= ~SXFR;
4728 1.96 fvdl ultraenb &= ~mask;
4729 1.96 fvdl }
4730 1.96 fvdl tinfo->user.period =
4731 1.96 fvdl ahc_find_period(ahc, scsirate,
4732 1.96 fvdl (ultraenb & mask)
4733 1.96 fvdl ? AHC_SYNCRATE_ULTRA
4734 1.96 fvdl : AHC_SYNCRATE_FAST);
4735 1.96 fvdl if (tinfo->user.period != 0)
4736 1.96 fvdl tinfo->user.offset = ~0;
4737 1.96 fvdl }
4738 1.96 fvdl if (tinfo->user.period == 0)
4739 1.96 fvdl tinfo->user.offset = 0;
4740 1.96 fvdl if ((scsirate & WIDEXFER) != 0
4741 1.96 fvdl && (ahc->features & AHC_WIDE) != 0)
4742 1.96 fvdl tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT;
4743 1.96 fvdl tinfo->user.protocol_version = 4;
4744 1.96 fvdl if ((ahc->features & AHC_DT) != 0)
4745 1.96 fvdl tinfo->user.transport_version = 3;
4746 1.96 fvdl else
4747 1.96 fvdl tinfo->user.transport_version = 2;
4748 1.96 fvdl tinfo->goal.protocol_version = 2;
4749 1.96 fvdl tinfo->goal.transport_version = 2;
4750 1.96 fvdl tinfo->curr.protocol_version = 2;
4751 1.96 fvdl tinfo->curr.transport_version = 2;
4752 1.42 fvdl }
4753 1.96 fvdl tstate->ultraenb = 0;
4754 1.96 fvdl tstate->discenable = discenable;
4755 1.42 fvdl }
4756 1.96 fvdl ahc->user_discenable = discenable;
4757 1.96 fvdl ahc->user_tagenable = tagenable;
4758 1.42 fvdl
4759 1.96 fvdl /* There are no untagged SCBs active yet. */
4760 1.96 fvdl for (i = 0; i < 16; i++) {
4761 1.96 fvdl ahc_unbusy_tcl(ahc, BUILD_TCL(i << 4, 0));
4762 1.96 fvdl if ((ahc->flags & AHC_SCB_BTT) != 0) {
4763 1.96 fvdl int lun;
4764 1.42 fvdl
4765 1.42 fvdl /*
4766 1.96 fvdl * The SCB based BTT allows an entry per
4767 1.96 fvdl * target and lun pair.
4768 1.42 fvdl */
4769 1.96 fvdl for (lun = 1; lun < AHC_NUM_LUNS; lun++)
4770 1.96 fvdl ahc_unbusy_tcl(ahc, BUILD_TCL(i << 4, lun));
4771 1.42 fvdl }
4772 1.96 fvdl }
4773 1.59 pk
4774 1.96 fvdl /* All of our queues are empty */
4775 1.96 fvdl for (i = 0; i < 256; i++)
4776 1.96 fvdl ahc->qoutfifo[i] = SCB_LIST_NULL;
4777 1.42 fvdl
4778 1.96 fvdl ahc_sync_qoutfifo(ahc, BUS_DMASYNC_PREREAD);
4779 1.9 explorer
4780 1.96 fvdl for (i = 0; i < 256; i++)
4781 1.96 fvdl ahc->qinfifo[i] = SCB_LIST_NULL;
4782 1.9 explorer
4783 1.96 fvdl if ((ahc->features & AHC_MULTI_TID) != 0) {
4784 1.96 fvdl ahc_outb(ahc, TARGID, 0);
4785 1.96 fvdl ahc_outb(ahc, TARGID + 1, 0);
4786 1.14 gibbs }
4787 1.14 gibbs
4788 1.96 fvdl /*
4789 1.96 fvdl * Tell the sequencer where it can find our arrays in memory.
4790 1.96 fvdl */
4791 1.96 fvdl physaddr = ahc->scb_data->hscb_busaddr;
4792 1.96 fvdl ahc_outb(ahc, HSCB_ADDR, physaddr & 0xFF);
4793 1.96 fvdl ahc_outb(ahc, HSCB_ADDR + 1, (physaddr >> 8) & 0xFF);
4794 1.96 fvdl ahc_outb(ahc, HSCB_ADDR + 2, (physaddr >> 16) & 0xFF);
4795 1.96 fvdl ahc_outb(ahc, HSCB_ADDR + 3, (physaddr >> 24) & 0xFF);
4796 1.14 gibbs
4797 1.96 fvdl physaddr = ahc->shared_data_busaddr;
4798 1.96 fvdl ahc_outb(ahc, SHARED_DATA_ADDR, physaddr & 0xFF);
4799 1.96 fvdl ahc_outb(ahc, SHARED_DATA_ADDR + 1, (physaddr >> 8) & 0xFF);
4800 1.96 fvdl ahc_outb(ahc, SHARED_DATA_ADDR + 2, (physaddr >> 16) & 0xFF);
4801 1.96 fvdl ahc_outb(ahc, SHARED_DATA_ADDR + 3, (physaddr >> 24) & 0xFF);
4802 1.14 gibbs
4803 1.96 fvdl /*
4804 1.96 fvdl * Initialize the group code to command length table.
4805 1.96 fvdl * This overrides the values in TARG_SCSIRATE, so only
4806 1.96 fvdl * setup the table after we have processed that information.
4807 1.96 fvdl */
4808 1.96 fvdl ahc_outb(ahc, CMDSIZE_TABLE, 5);
4809 1.96 fvdl ahc_outb(ahc, CMDSIZE_TABLE + 1, 9);
4810 1.96 fvdl ahc_outb(ahc, CMDSIZE_TABLE + 2, 9);
4811 1.96 fvdl ahc_outb(ahc, CMDSIZE_TABLE + 3, 0);
4812 1.96 fvdl ahc_outb(ahc, CMDSIZE_TABLE + 4, 15);
4813 1.96 fvdl ahc_outb(ahc, CMDSIZE_TABLE + 5, 11);
4814 1.96 fvdl ahc_outb(ahc, CMDSIZE_TABLE + 6, 0);
4815 1.96 fvdl ahc_outb(ahc, CMDSIZE_TABLE + 7, 0);
4816 1.96 fvdl
4817 1.96 fvdl /* Tell the sequencer of our initial queue positions */
4818 1.96 fvdl ahc_outb(ahc, KERNEL_QINPOS, 0);
4819 1.96 fvdl ahc_outb(ahc, QINPOS, 0);
4820 1.96 fvdl ahc_outb(ahc, QOUTPOS, 0);
4821 1.14 gibbs
4822 1.96 fvdl /*
4823 1.96 fvdl * Use the built in queue management registers
4824 1.96 fvdl * if they are available.
4825 1.96 fvdl */
4826 1.96 fvdl if ((ahc->features & AHC_QUEUE_REGS) != 0) {
4827 1.96 fvdl ahc_outb(ahc, QOFF_CTLSTA, SCB_QSIZE_256);
4828 1.96 fvdl ahc_outb(ahc, SDSCB_QOFF, 0);
4829 1.96 fvdl ahc_outb(ahc, SNSCB_QOFF, 0);
4830 1.96 fvdl ahc_outb(ahc, HNSCB_QOFF, 0);
4831 1.96 fvdl }
4832 1.14 gibbs
4833 1.42 fvdl
4834 1.96 fvdl /* We don't have any waiting selections */
4835 1.96 fvdl ahc_outb(ahc, WAITING_SCBH, SCB_LIST_NULL);
4836 1.14 gibbs
4837 1.96 fvdl /* Our disconnection list is empty too */
4838 1.96 fvdl ahc_outb(ahc, DISCONNECTED_SCBH, SCB_LIST_NULL);
4839 1.42 fvdl
4840 1.96 fvdl /* Message out buffer starts empty */
4841 1.96 fvdl ahc_outb(ahc, MSG_OUT, MSG_NOOP);
4842 1.42 fvdl
4843 1.42 fvdl /*
4844 1.96 fvdl * Setup the allowed SCSI Sequences based on operational mode.
4845 1.96 fvdl * If we are a target, we'll enalbe select in operations once
4846 1.96 fvdl * we've had a lun enabled.
4847 1.42 fvdl */
4848 1.96 fvdl scsiseq_template = ENSELO|ENAUTOATNO|ENAUTOATNP;
4849 1.96 fvdl if ((ahc->flags & AHC_INITIATORROLE) != 0)
4850 1.96 fvdl scsiseq_template |= ENRSELI;
4851 1.96 fvdl ahc_outb(ahc, SCSISEQ_TEMPLATE, scsiseq_template);
4852 1.42 fvdl
4853 1.96 fvdl /*
4854 1.96 fvdl * Load the Sequencer program and Enable the adapter
4855 1.96 fvdl * in "fast" mode.
4856 1.96 fvdl */
4857 1.96 fvdl if (bootverbose)
4858 1.96 fvdl printf("%s: Downloading Sequencer Program...",
4859 1.96 fvdl ahc_name(ahc));
4860 1.14 gibbs
4861 1.96 fvdl ahc_loadseq(ahc);
4862 1.42 fvdl
4863 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0) {
4864 1.96 fvdl int wait;
4865 1.14 gibbs
4866 1.96 fvdl /*
4867 1.96 fvdl * Wait for up to 500ms for our transceivers
4868 1.96 fvdl * to settle. If the adapter does not have
4869 1.96 fvdl * a cable attached, the tranceivers may
4870 1.96 fvdl * never settle, so don't complain if we
4871 1.96 fvdl * fail here.
4872 1.96 fvdl */
4873 1.96 fvdl ahc_pause(ahc);
4874 1.96 fvdl for (wait = 5000;
4875 1.96 fvdl (ahc_inb(ahc, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait;
4876 1.96 fvdl wait--)
4877 1.96 fvdl ahc_delay(100);
4878 1.96 fvdl ahc_unpause(ahc);
4879 1.96 fvdl }
4880 1.1 mycroft
4881 1.96 fvdl /* We have to wait until after any system dumps... */
4882 1.96 fvdl ahc->shutdown_hook = shutdownhook_establish(ahc_shutdown, ahc);
4883 1.1 mycroft
4884 1.96 fvdl return (0);
4885 1.96 fvdl }
4886 1.1 mycroft
4887 1.96 fvdl void
4888 1.96 fvdl ahc_intr_enable(struct ahc_softc *ahc, int enable)
4889 1.96 fvdl {
4890 1.96 fvdl u_int hcntrl;
4891 1.42 fvdl
4892 1.96 fvdl hcntrl = ahc_inb(ahc, HCNTRL);
4893 1.96 fvdl hcntrl &= ~INTEN;
4894 1.96 fvdl ahc->pause &= ~INTEN;
4895 1.96 fvdl ahc->unpause &= ~INTEN;
4896 1.96 fvdl if (enable) {
4897 1.96 fvdl hcntrl |= INTEN;
4898 1.96 fvdl ahc->pause |= INTEN;
4899 1.96 fvdl ahc->unpause |= INTEN;
4900 1.96 fvdl }
4901 1.96 fvdl ahc_outb(ahc, HCNTRL, hcntrl);
4902 1.96 fvdl }
4903 1.42 fvdl
4904 1.96 fvdl /*
4905 1.96 fvdl * Ensure that the card is paused in a location
4906 1.96 fvdl * outside of all critical sections and that all
4907 1.96 fvdl * pending work is completed prior to returning.
4908 1.96 fvdl * This routine should only be called from outside
4909 1.96 fvdl * an interrupt context.
4910 1.96 fvdl */
4911 1.96 fvdl void
4912 1.96 fvdl ahc_pause_and_flushwork(struct ahc_softc *ahc)
4913 1.96 fvdl {
4914 1.96 fvdl int intstat;
4915 1.96 fvdl int maxloops;
4916 1.96 fvdl int paused;
4917 1.96 fvdl
4918 1.96 fvdl maxloops = 1000;
4919 1.96 fvdl ahc->flags |= AHC_ALL_INTERRUPTS;
4920 1.96 fvdl intstat = 0;
4921 1.96 fvdl paused = FALSE;
4922 1.96 fvdl do {
4923 1.96 fvdl if (paused)
4924 1.96 fvdl ahc_unpause(ahc);
4925 1.96 fvdl ahc_intr(ahc);
4926 1.96 fvdl ahc_pause(ahc);
4927 1.96 fvdl paused = TRUE;
4928 1.96 fvdl ahc_outb(ahc, SCSISEQ, ahc_inb(ahc, SCSISEQ) & ~ENSELO);
4929 1.96 fvdl ahc_clear_critical_section(ahc);
4930 1.96 fvdl if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0)
4931 1.42 fvdl break;
4932 1.96 fvdl } while (--maxloops
4933 1.96 fvdl && (((intstat = ahc_inb(ahc, INTSTAT)) & INT_PEND) != 0
4934 1.96 fvdl || (ahc_inb(ahc, SSTAT0) & (SELDO|SELINGO))));
4935 1.96 fvdl if (maxloops == 0) {
4936 1.96 fvdl printf("Infinite interrupt loop, INTSTAT = %x",
4937 1.96 fvdl ahc_inb(ahc, INTSTAT));
4938 1.14 gibbs }
4939 1.96 fvdl ahc_platform_flushwork(ahc);
4940 1.96 fvdl ahc->flags &= ~AHC_ALL_INTERRUPTS;
4941 1.96 fvdl }
4942 1.96 fvdl
4943 1.96 fvdl int
4944 1.96 fvdl ahc_suspend(struct ahc_softc *ahc)
4945 1.96 fvdl {
4946 1.96 fvdl uint8_t *ptr;
4947 1.96 fvdl int i;
4948 1.96 fvdl
4949 1.96 fvdl ahc_pause_and_flushwork(ahc);
4950 1.42 fvdl
4951 1.96 fvdl if (LIST_FIRST(&ahc->pending_scbs) != NULL)
4952 1.96 fvdl return (EBUSY);
4953 1.42 fvdl
4954 1.96 fvdl #if AHC_TARGET_MODE
4955 1.96 fvdl /*
4956 1.96 fvdl * XXX What about ATIOs that have not yet been serviced?
4957 1.96 fvdl * Perhaps we should just refuse to be suspended if we
4958 1.96 fvdl * are acting in a target role.
4959 1.96 fvdl */
4960 1.96 fvdl if (ahc->pending_device != NULL)
4961 1.96 fvdl return (EBUSY);
4962 1.42 fvdl #endif
4963 1.96 fvdl
4964 1.96 fvdl /* Save volatile registers */
4965 1.96 fvdl if ((ahc->features & AHC_TWIN) != 0) {
4966 1.96 fvdl ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) | SELBUSB);
4967 1.96 fvdl ahc->suspend_state.channel[1].scsiseq = ahc_inb(ahc, SCSISEQ);
4968 1.96 fvdl ahc->suspend_state.channel[1].sxfrctl0 = ahc_inb(ahc, SXFRCTL0);
4969 1.96 fvdl ahc->suspend_state.channel[1].sxfrctl1 = ahc_inb(ahc, SXFRCTL1);
4970 1.96 fvdl ahc->suspend_state.channel[1].simode0 = ahc_inb(ahc, SIMODE0);
4971 1.96 fvdl ahc->suspend_state.channel[1].simode1 = ahc_inb(ahc, SIMODE1);
4972 1.96 fvdl ahc->suspend_state.channel[1].seltimer = ahc_inb(ahc, SELTIMER);
4973 1.96 fvdl ahc->suspend_state.channel[1].seqctl = ahc_inb(ahc, SEQCTL);
4974 1.96 fvdl ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~SELBUSB);
4975 1.96 fvdl }
4976 1.96 fvdl ahc->suspend_state.channel[0].scsiseq = ahc_inb(ahc, SCSISEQ);
4977 1.96 fvdl ahc->suspend_state.channel[0].sxfrctl0 = ahc_inb(ahc, SXFRCTL0);
4978 1.96 fvdl ahc->suspend_state.channel[0].sxfrctl1 = ahc_inb(ahc, SXFRCTL1);
4979 1.96 fvdl ahc->suspend_state.channel[0].simode0 = ahc_inb(ahc, SIMODE0);
4980 1.96 fvdl ahc->suspend_state.channel[0].simode1 = ahc_inb(ahc, SIMODE1);
4981 1.96 fvdl ahc->suspend_state.channel[0].seltimer = ahc_inb(ahc, SELTIMER);
4982 1.96 fvdl ahc->suspend_state.channel[0].seqctl = ahc_inb(ahc, SEQCTL);
4983 1.96 fvdl
4984 1.96 fvdl if ((ahc->chip & AHC_PCI) != 0) {
4985 1.96 fvdl ahc->suspend_state.dscommand0 = ahc_inb(ahc, DSCOMMAND0);
4986 1.96 fvdl ahc->suspend_state.dspcistatus = ahc_inb(ahc, DSPCISTATUS);
4987 1.96 fvdl }
4988 1.96 fvdl
4989 1.96 fvdl if ((ahc->features & AHC_DT) != 0) {
4990 1.96 fvdl u_int sfunct;
4991 1.96 fvdl
4992 1.96 fvdl sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
4993 1.96 fvdl ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
4994 1.96 fvdl ahc->suspend_state.optionmode = ahc_inb(ahc, OPTIONMODE);
4995 1.96 fvdl ahc_outb(ahc, SFUNCT, sfunct);
4996 1.96 fvdl ahc->suspend_state.crccontrol1 = ahc_inb(ahc, CRCCONTROL1);
4997 1.14 gibbs }
4998 1.6 mycroft
4999 1.96 fvdl if ((ahc->features & AHC_MULTI_FUNC) != 0)
5000 1.96 fvdl ahc->suspend_state.scbbaddr = ahc_inb(ahc, SCBBADDR);
5001 1.96 fvdl
5002 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0)
5003 1.96 fvdl ahc->suspend_state.dff_thrsh = ahc_inb(ahc, DFF_THRSH);
5004 1.96 fvdl
5005 1.96 fvdl ptr = ahc->suspend_state.scratch_ram;
5006 1.96 fvdl for (i = 0; i < 64; i++)
5007 1.96 fvdl *ptr++ = ahc_inb(ahc, SRAM_BASE + i);
5008 1.96 fvdl
5009 1.96 fvdl if ((ahc->features & AHC_MORE_SRAM) != 0) {
5010 1.96 fvdl for (i = 0; i < 16; i++)
5011 1.96 fvdl *ptr++ = ahc_inb(ahc, TARG_OFFSET + i);
5012 1.42 fvdl }
5013 1.1 mycroft
5014 1.96 fvdl ptr = ahc->suspend_state.btt;
5015 1.96 fvdl if ((ahc->flags & AHC_SCB_BTT) != 0) {
5016 1.96 fvdl for (i = 0;i < AHC_NUM_TARGETS; i++) {
5017 1.96 fvdl int j;
5018 1.96 fvdl
5019 1.96 fvdl for (j = 0;j < AHC_NUM_LUNS; j++) {
5020 1.96 fvdl u_int tcl;
5021 1.1 mycroft
5022 1.96 fvdl tcl = BUILD_TCL(i << 4, j);
5023 1.96 fvdl *ptr = ahc_index_busy_tcl(ahc, tcl);
5024 1.96 fvdl }
5025 1.96 fvdl }
5026 1.96 fvdl }
5027 1.96 fvdl ahc_shutdown(ahc);
5028 1.96 fvdl return (0);
5029 1.42 fvdl }
5030 1.1 mycroft
5031 1.96 fvdl int
5032 1.96 fvdl ahc_resume(struct ahc_softc *ahc)
5033 1.42 fvdl {
5034 1.96 fvdl uint8_t *ptr;
5035 1.96 fvdl int i;
5036 1.96 fvdl
5037 1.96 fvdl ahc_reset(ahc);
5038 1.96 fvdl
5039 1.96 fvdl ahc_build_free_scb_list(ahc);
5040 1.96 fvdl
5041 1.96 fvdl /* Restore volatile registers */
5042 1.96 fvdl if ((ahc->features & AHC_TWIN) != 0) {
5043 1.96 fvdl ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) | SELBUSB);
5044 1.96 fvdl ahc_outb(ahc, SCSIID, ahc->our_id);
5045 1.96 fvdl ahc_outb(ahc, SCSISEQ, ahc->suspend_state.channel[1].scsiseq);
5046 1.96 fvdl ahc_outb(ahc, SXFRCTL0, ahc->suspend_state.channel[1].sxfrctl0);
5047 1.96 fvdl ahc_outb(ahc, SXFRCTL1, ahc->suspend_state.channel[1].sxfrctl1);
5048 1.96 fvdl ahc_outb(ahc, SIMODE0, ahc->suspend_state.channel[1].simode0);
5049 1.96 fvdl ahc_outb(ahc, SIMODE1, ahc->suspend_state.channel[1].simode1);
5050 1.96 fvdl ahc_outb(ahc, SELTIMER, ahc->suspend_state.channel[1].seltimer);
5051 1.96 fvdl ahc_outb(ahc, SEQCTL, ahc->suspend_state.channel[1].seqctl);
5052 1.96 fvdl ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~SELBUSB);
5053 1.96 fvdl }
5054 1.96 fvdl ahc_outb(ahc, SCSISEQ, ahc->suspend_state.channel[0].scsiseq);
5055 1.96 fvdl ahc_outb(ahc, SXFRCTL0, ahc->suspend_state.channel[0].sxfrctl0);
5056 1.96 fvdl ahc_outb(ahc, SXFRCTL1, ahc->suspend_state.channel[0].sxfrctl1);
5057 1.96 fvdl ahc_outb(ahc, SIMODE0, ahc->suspend_state.channel[0].simode0);
5058 1.96 fvdl ahc_outb(ahc, SIMODE1, ahc->suspend_state.channel[0].simode1);
5059 1.96 fvdl ahc_outb(ahc, SELTIMER, ahc->suspend_state.channel[0].seltimer);
5060 1.96 fvdl ahc_outb(ahc, SEQCTL, ahc->suspend_state.channel[0].seqctl);
5061 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0)
5062 1.96 fvdl ahc_outb(ahc, SCSIID_ULTRA2, ahc->our_id);
5063 1.96 fvdl else
5064 1.96 fvdl ahc_outb(ahc, SCSIID, ahc->our_id);
5065 1.22 cgd
5066 1.96 fvdl if ((ahc->chip & AHC_PCI) != 0) {
5067 1.96 fvdl ahc_outb(ahc, DSCOMMAND0, ahc->suspend_state.dscommand0);
5068 1.96 fvdl ahc_outb(ahc, DSPCISTATUS, ahc->suspend_state.dspcistatus);
5069 1.96 fvdl }
5070 1.6 mycroft
5071 1.96 fvdl if ((ahc->features & AHC_DT) != 0) {
5072 1.96 fvdl u_int sfunct;
5073 1.42 fvdl
5074 1.96 fvdl sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
5075 1.96 fvdl ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
5076 1.96 fvdl ahc_outb(ahc, OPTIONMODE, ahc->suspend_state.optionmode);
5077 1.96 fvdl ahc_outb(ahc, SFUNCT, sfunct);
5078 1.96 fvdl ahc_outb(ahc, CRCCONTROL1, ahc->suspend_state.crccontrol1);
5079 1.96 fvdl }
5080 1.42 fvdl
5081 1.96 fvdl if ((ahc->features & AHC_MULTI_FUNC) != 0)
5082 1.96 fvdl ahc_outb(ahc, SCBBADDR, ahc->suspend_state.scbbaddr);
5083 1.42 fvdl
5084 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0)
5085 1.96 fvdl ahc_outb(ahc, DFF_THRSH, ahc->suspend_state.dff_thrsh);
5086 1.42 fvdl
5087 1.96 fvdl ptr = ahc->suspend_state.scratch_ram;
5088 1.96 fvdl for (i = 0; i < 64; i++)
5089 1.96 fvdl ahc_outb(ahc, SRAM_BASE + i, *ptr++);
5090 1.59 pk
5091 1.96 fvdl if ((ahc->features & AHC_MORE_SRAM) != 0) {
5092 1.96 fvdl for (i = 0; i < 16; i++)
5093 1.96 fvdl ahc_outb(ahc, TARG_OFFSET + i, *ptr++);
5094 1.6 mycroft }
5095 1.14 gibbs
5096 1.96 fvdl ptr = ahc->suspend_state.btt;
5097 1.96 fvdl if ((ahc->flags & AHC_SCB_BTT) != 0) {
5098 1.96 fvdl for (i = 0;i < AHC_NUM_TARGETS; i++) {
5099 1.96 fvdl int j;
5100 1.14 gibbs
5101 1.96 fvdl for (j = 0;j < AHC_NUM_LUNS; j++) {
5102 1.96 fvdl u_int tcl;
5103 1.59 pk
5104 1.96 fvdl tcl = BUILD_TCL(i << 4, j);
5105 1.96 fvdl ahc_busy_tcl(ahc, tcl, *ptr);
5106 1.96 fvdl }
5107 1.96 fvdl }
5108 1.96 fvdl }
5109 1.96 fvdl return (0);
5110 1.1 mycroft }
5111 1.1 mycroft
5112 1.96 fvdl /************************** Busy Target Table *********************************/
5113 1.1 mycroft /*
5114 1.96 fvdl * Return the untagged transaction id for a given target/channel lun.
5115 1.96 fvdl * Optionally, clear the entry.
5116 1.1 mycroft */
5117 1.96 fvdl u_int
5118 1.96 fvdl ahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl)
5119 1.1 mycroft {
5120 1.96 fvdl u_int scbid;
5121 1.96 fvdl u_int target_offset;
5122 1.96 fvdl
5123 1.96 fvdl if ((ahc->flags & AHC_SCB_BTT) != 0) {
5124 1.96 fvdl u_int saved_scbptr;
5125 1.96 fvdl
5126 1.96 fvdl saved_scbptr = ahc_inb(ahc, SCBPTR);
5127 1.96 fvdl ahc_outb(ahc, SCBPTR, TCL_LUN(tcl));
5128 1.96 fvdl scbid = ahc_inb(ahc, SCB_64_BTT + TCL_TARGET_OFFSET(tcl));
5129 1.96 fvdl ahc_outb(ahc, SCBPTR, saved_scbptr);
5130 1.96 fvdl } else {
5131 1.96 fvdl target_offset = TCL_TARGET_OFFSET(tcl);
5132 1.96 fvdl scbid = ahc_inb(ahc, BUSY_TARGETS + target_offset);
5133 1.96 fvdl }
5134 1.96 fvdl
5135 1.96 fvdl return (scbid);
5136 1.96 fvdl }
5137 1.59 pk
5138 1.96 fvdl void
5139 1.96 fvdl ahc_unbusy_tcl(struct ahc_softc *ahc, u_int tcl)
5140 1.96 fvdl {
5141 1.96 fvdl u_int target_offset;
5142 1.42 fvdl
5143 1.96 fvdl if ((ahc->flags & AHC_SCB_BTT) != 0) {
5144 1.96 fvdl u_int saved_scbptr;
5145 1.96 fvdl
5146 1.96 fvdl saved_scbptr = ahc_inb(ahc, SCBPTR);
5147 1.96 fvdl ahc_outb(ahc, SCBPTR, TCL_LUN(tcl));
5148 1.96 fvdl ahc_outb(ahc, SCB_64_BTT+TCL_TARGET_OFFSET(tcl), SCB_LIST_NULL);
5149 1.96 fvdl ahc_outb(ahc, SCBPTR, saved_scbptr);
5150 1.96 fvdl } else {
5151 1.96 fvdl target_offset = TCL_TARGET_OFFSET(tcl);
5152 1.96 fvdl ahc_outb(ahc, BUSY_TARGETS + target_offset, SCB_LIST_NULL);
5153 1.96 fvdl }
5154 1.96 fvdl }
5155 1.42 fvdl
5156 1.96 fvdl void
5157 1.96 fvdl ahc_busy_tcl(struct ahc_softc *ahc, u_int tcl, u_int scbid)
5158 1.96 fvdl {
5159 1.96 fvdl u_int target_offset;
5160 1.42 fvdl
5161 1.96 fvdl if ((ahc->flags & AHC_SCB_BTT) != 0) {
5162 1.96 fvdl u_int saved_scbptr;
5163 1.96 fvdl
5164 1.96 fvdl saved_scbptr = ahc_inb(ahc, SCBPTR);
5165 1.96 fvdl ahc_outb(ahc, SCBPTR, TCL_LUN(tcl));
5166 1.96 fvdl ahc_outb(ahc, SCB_64_BTT + TCL_TARGET_OFFSET(tcl), scbid);
5167 1.96 fvdl ahc_outb(ahc, SCBPTR, saved_scbptr);
5168 1.96 fvdl } else {
5169 1.96 fvdl target_offset = TCL_TARGET_OFFSET(tcl);
5170 1.96 fvdl ahc_outb(ahc, BUSY_TARGETS + target_offset, scbid);
5171 1.42 fvdl }
5172 1.96 fvdl }
5173 1.6 mycroft
5174 1.96 fvdl /************************** SCB and SCB queue management **********************/
5175 1.96 fvdl int
5176 1.96 fvdl ahc_match_scb(struct ahc_softc *ahc, struct scb *scb, int target,
5177 1.96 fvdl char channel, int lun, u_int tag, role_t role)
5178 1.96 fvdl {
5179 1.96 fvdl int targ = SCB_GET_TARGET(ahc, scb);
5180 1.96 fvdl char chan = SCB_GET_CHANNEL(ahc, scb);
5181 1.96 fvdl int slun = SCB_GET_LUN(scb);
5182 1.96 fvdl int match;
5183 1.28 leo
5184 1.96 fvdl match = ((chan == channel) || (channel == ALL_CHANNELS));
5185 1.96 fvdl if (match != 0)
5186 1.96 fvdl match = ((targ == target) || (target == CAM_TARGET_WILDCARD));
5187 1.96 fvdl if (match != 0)
5188 1.96 fvdl match = ((lun == slun) || (lun == CAM_LUN_WILDCARD));
5189 1.96 fvdl if (match != 0) {
5190 1.96 fvdl #if 0
5191 1.96 fvdl #if AHC_TARGET_MODE
5192 1.96 fvdl int group;
5193 1.42 fvdl
5194 1.96 fvdl group = XPT_FC_GROUP(scb->io_ctx->ccb_h.func_code);
5195 1.96 fvdl if (role == ROLE_INITIATOR) {
5196 1.96 fvdl match = (group != XPT_FC_GROUP_TMODE)
5197 1.96 fvdl && ((tag == scb->hscb->tag)
5198 1.96 fvdl || (tag == SCB_LIST_NULL));
5199 1.96 fvdl } else if (role == ROLE_TARGET) {
5200 1.96 fvdl match = (group == XPT_FC_GROUP_TMODE)
5201 1.96 fvdl && ((tag == scb->io_ctx->csio.tag_id)
5202 1.96 fvdl || (tag == SCB_LIST_NULL));
5203 1.96 fvdl }
5204 1.96 fvdl #else /* !AHC_TARGET_MODE */
5205 1.96 fvdl match = ((tag == scb->hscb->tag) || (tag == SCB_LIST_NULL));
5206 1.96 fvdl #endif /* AHC_TARGET_MODE */
5207 1.96 fvdl #endif
5208 1.28 leo }
5209 1.42 fvdl
5210 1.96 fvdl return match;
5211 1.96 fvdl }
5212 1.96 fvdl
5213 1.96 fvdl void
5214 1.96 fvdl ahc_freeze_devq(struct ahc_softc *ahc, struct scb *scb)
5215 1.96 fvdl {
5216 1.96 fvdl int target;
5217 1.96 fvdl char channel;
5218 1.96 fvdl int lun;
5219 1.42 fvdl
5220 1.96 fvdl target = SCB_GET_TARGET(ahc, scb);
5221 1.96 fvdl lun = SCB_GET_LUN(scb);
5222 1.96 fvdl channel = SCB_GET_CHANNEL(ahc, scb);
5223 1.96 fvdl
5224 1.96 fvdl ahc_search_qinfifo(ahc, target, channel, lun,
5225 1.96 fvdl /*tag*/SCB_LIST_NULL, ROLE_UNKNOWN,
5226 1.96 fvdl CAM_REQUEUE_REQ, SEARCH_COMPLETE);
5227 1.42 fvdl
5228 1.96 fvdl ahc_platform_freeze_devq(ahc, scb);
5229 1.96 fvdl }
5230 1.42 fvdl
5231 1.96 fvdl void
5232 1.96 fvdl ahc_qinfifo_requeue_tail(struct ahc_softc *ahc, struct scb *scb)
5233 1.96 fvdl {
5234 1.96 fvdl struct scb *prev_scb;
5235 1.42 fvdl
5236 1.96 fvdl prev_scb = NULL;
5237 1.96 fvdl if (ahc_qinfifo_count(ahc) != 0) {
5238 1.96 fvdl u_int prev_tag;
5239 1.96 fvdl uint8_t prev_pos;
5240 1.42 fvdl
5241 1.96 fvdl prev_pos = ahc->qinfifonext - 1;
5242 1.96 fvdl prev_tag = ahc->qinfifo[prev_pos];
5243 1.96 fvdl prev_scb = ahc_lookup_scb(ahc, prev_tag);
5244 1.42 fvdl }
5245 1.96 fvdl ahc_qinfifo_requeue(ahc, prev_scb, scb);
5246 1.96 fvdl if ((ahc->features & AHC_QUEUE_REGS) != 0) {
5247 1.96 fvdl ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext);
5248 1.96 fvdl } else {
5249 1.96 fvdl ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext);
5250 1.1 mycroft }
5251 1.96 fvdl }
5252 1.42 fvdl
5253 1.96 fvdl static void
5254 1.96 fvdl ahc_qinfifo_requeue(struct ahc_softc *ahc, struct scb *prev_scb,
5255 1.96 fvdl struct scb *scb)
5256 1.96 fvdl {
5257 1.96 fvdl if (prev_scb == NULL) {
5258 1.96 fvdl ahc_outb(ahc, NEXT_QUEUED_SCB, scb->hscb->tag);
5259 1.96 fvdl } else {
5260 1.96 fvdl prev_scb->hscb->next = scb->hscb->tag;
5261 1.96 fvdl ahc_sync_scb(ahc, prev_scb,
5262 1.96 fvdl BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
5263 1.96 fvdl }
5264 1.96 fvdl ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag;
5265 1.96 fvdl scb->hscb->next = ahc->next_queued_scb->hscb->tag;
5266 1.96 fvdl ahc_sync_scb(ahc, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
5267 1.42 fvdl }
5268 1.42 fvdl
5269 1.96 fvdl static int
5270 1.96 fvdl ahc_qinfifo_count(struct ahc_softc *ahc)
5271 1.96 fvdl {
5272 1.96 fvdl uint8_t qinpos;
5273 1.96 fvdl uint8_t diff;
5274 1.42 fvdl
5275 1.96 fvdl if ((ahc->features & AHC_QUEUE_REGS) != 0) {
5276 1.96 fvdl qinpos = ahc_inb(ahc, SNSCB_QOFF);
5277 1.96 fvdl ahc_outb(ahc, SNSCB_QOFF, qinpos);
5278 1.96 fvdl } else
5279 1.96 fvdl qinpos = ahc_inb(ahc, QINPOS);
5280 1.96 fvdl diff = ahc->qinfifonext - qinpos;
5281 1.96 fvdl return (diff);
5282 1.1 mycroft }
5283 1.1 mycroft
5284 1.1 mycroft int
5285 1.96 fvdl ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel,
5286 1.96 fvdl int lun, u_int tag, role_t role, uint32_t status,
5287 1.96 fvdl ahc_search_action action)
5288 1.1 mycroft {
5289 1.96 fvdl struct scb *scb;
5290 1.96 fvdl struct scb *prev_scb;
5291 1.96 fvdl uint8_t qinstart;
5292 1.96 fvdl uint8_t qinpos;
5293 1.96 fvdl uint8_t qintail;
5294 1.96 fvdl uint8_t next;
5295 1.96 fvdl uint8_t prev;
5296 1.96 fvdl uint8_t curscbptr;
5297 1.96 fvdl int found;
5298 1.96 fvdl int have_qregs;
5299 1.96 fvdl
5300 1.96 fvdl qintail = ahc->qinfifonext;
5301 1.96 fvdl have_qregs = (ahc->features & AHC_QUEUE_REGS) != 0;
5302 1.96 fvdl if (have_qregs) {
5303 1.96 fvdl qinstart = ahc_inb(ahc, SNSCB_QOFF);
5304 1.96 fvdl ahc_outb(ahc, SNSCB_QOFF, qinstart);
5305 1.96 fvdl } else
5306 1.96 fvdl qinstart = ahc_inb(ahc, QINPOS);
5307 1.96 fvdl qinpos = qinstart;
5308 1.96 fvdl found = 0;
5309 1.96 fvdl prev_scb = NULL;
5310 1.42 fvdl
5311 1.96 fvdl if (action == SEARCH_COMPLETE) {
5312 1.96 fvdl /*
5313 1.96 fvdl * Don't attempt to run any queued untagged transactions
5314 1.96 fvdl * until we are done with the abort process.
5315 1.96 fvdl */
5316 1.96 fvdl ahc_freeze_untagged_queues(ahc);
5317 1.42 fvdl }
5318 1.28 leo
5319 1.1 mycroft /*
5320 1.96 fvdl * Start with an empty queue. Entries that are not chosen
5321 1.96 fvdl * for removal will be re-added to the queue as we go.
5322 1.1 mycroft */
5323 1.96 fvdl ahc->qinfifonext = qinpos;
5324 1.96 fvdl ahc_outb(ahc, NEXT_QUEUED_SCB, ahc->next_queued_scb->hscb->tag);
5325 1.59 pk
5326 1.96 fvdl while (qinpos != qintail) {
5327 1.96 fvdl scb = ahc_lookup_scb(ahc, ahc->qinfifo[qinpos]);
5328 1.96 fvdl if (scb == NULL) {
5329 1.96 fvdl printf("qinpos = %d, SCB index = %d\n",
5330 1.96 fvdl qinpos, ahc->qinfifo[qinpos]);
5331 1.96 fvdl panic("Loop 1\n");
5332 1.96 fvdl }
5333 1.1 mycroft
5334 1.96 fvdl if (ahc_match_scb(ahc, scb, target, channel, lun, tag, role)) {
5335 1.96 fvdl /*
5336 1.96 fvdl * We found an scb that needs to be acted on.
5337 1.96 fvdl */
5338 1.96 fvdl found++;
5339 1.96 fvdl switch (action) {
5340 1.96 fvdl case SEARCH_COMPLETE:
5341 1.96 fvdl {
5342 1.96 fvdl cam_status ostat;
5343 1.96 fvdl cam_status cstat;
5344 1.6 mycroft
5345 1.96 fvdl ostat = ahc_get_transaction_status(scb);
5346 1.96 fvdl if (ostat == CAM_REQ_INPROG)
5347 1.96 fvdl ahc_set_transaction_status(scb, status);
5348 1.96 fvdl cstat = ahc_get_transaction_status(scb);
5349 1.96 fvdl if (cstat != CAM_REQ_CMP)
5350 1.96 fvdl ahc_freeze_scb(scb);
5351 1.96 fvdl if ((scb->flags & SCB_ACTIVE) == 0)
5352 1.96 fvdl printf("Inactive SCB in qinfifo\n");
5353 1.96 fvdl ahc_done(ahc, scb);
5354 1.1 mycroft
5355 1.96 fvdl /* FALLTHROUGH */
5356 1.96 fvdl }
5357 1.96 fvdl case SEARCH_REMOVE:
5358 1.96 fvdl break;
5359 1.96 fvdl case SEARCH_COUNT:
5360 1.96 fvdl ahc_qinfifo_requeue(ahc, prev_scb, scb);
5361 1.96 fvdl prev_scb = scb;
5362 1.96 fvdl break;
5363 1.96 fvdl }
5364 1.96 fvdl } else {
5365 1.96 fvdl ahc_qinfifo_requeue(ahc, prev_scb, scb);
5366 1.96 fvdl prev_scb = scb;
5367 1.96 fvdl }
5368 1.96 fvdl qinpos++;
5369 1.96 fvdl }
5370 1.1 mycroft
5371 1.96 fvdl if ((ahc->features & AHC_QUEUE_REGS) != 0) {
5372 1.96 fvdl ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext);
5373 1.96 fvdl } else {
5374 1.96 fvdl ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext);
5375 1.96 fvdl }
5376 1.1 mycroft
5377 1.96 fvdl if (action != SEARCH_COUNT
5378 1.96 fvdl && (found != 0)
5379 1.96 fvdl && (qinstart != ahc->qinfifonext)) {
5380 1.96 fvdl /*
5381 1.105 wiz * The sequencer may be in the process of DMA'ing
5382 1.96 fvdl * down the SCB at the beginning of the queue.
5383 1.96 fvdl * This could be problematic if either the first,
5384 1.96 fvdl * or the second SCB is removed from the queue
5385 1.96 fvdl * (the first SCB includes a pointer to the "next"
5386 1.105 wiz * SCB to DMA). If we have removed any entries, swap
5387 1.96 fvdl * the first element in the queue with the next HSCB
5388 1.96 fvdl * so the sequencer will notice that NEXT_QUEUED_SCB
5389 1.105 wiz * has changed during its DMA attempt and will retry
5390 1.96 fvdl * the DMA.
5391 1.96 fvdl */
5392 1.96 fvdl scb = ahc_lookup_scb(ahc, ahc->qinfifo[qinstart]);
5393 1.6 mycroft
5394 1.96 fvdl if (scb == NULL) {
5395 1.96 fvdl printf("found = %d, qinstart = %d, qinfifionext = %d\n",
5396 1.96 fvdl found, qinstart, ahc->qinfifonext);
5397 1.96 fvdl panic("First/Second Qinfifo fixup\n");
5398 1.96 fvdl }
5399 1.96 fvdl /*
5400 1.96 fvdl * ahc_swap_with_next_hscb forces our next pointer to
5401 1.96 fvdl * point to the reserved SCB for future commands. Save
5402 1.96 fvdl * and restore our original next pointer to maintain
5403 1.96 fvdl * queue integrity.
5404 1.96 fvdl */
5405 1.96 fvdl next = scb->hscb->next;
5406 1.96 fvdl ahc->scb_data->scbindex[scb->hscb->tag] = NULL;
5407 1.96 fvdl ahc_swap_with_next_hscb(ahc, scb);
5408 1.96 fvdl scb->hscb->next = next;
5409 1.96 fvdl ahc->qinfifo[qinstart] = scb->hscb->tag;
5410 1.96 fvdl
5411 1.96 fvdl /* Tell the card about the new head of the qinfifo. */
5412 1.96 fvdl ahc_outb(ahc, NEXT_QUEUED_SCB, scb->hscb->tag);
5413 1.96 fvdl
5414 1.96 fvdl /* Fixup the tail "next" pointer. */
5415 1.96 fvdl qintail = ahc->qinfifonext - 1;
5416 1.96 fvdl scb = ahc_lookup_scb(ahc, ahc->qinfifo[qintail]);
5417 1.96 fvdl scb->hscb->next = ahc->next_queued_scb->hscb->tag;
5418 1.96 fvdl }
5419 1.6 mycroft
5420 1.28 leo /*
5421 1.96 fvdl * Search waiting for selection list.
5422 1.28 leo */
5423 1.96 fvdl curscbptr = ahc_inb(ahc, SCBPTR);
5424 1.96 fvdl next = ahc_inb(ahc, WAITING_SCBH); /* Start at head of list. */
5425 1.96 fvdl prev = SCB_LIST_NULL;
5426 1.96 fvdl
5427 1.96 fvdl while (next != SCB_LIST_NULL) {
5428 1.96 fvdl uint8_t scb_index;
5429 1.42 fvdl
5430 1.96 fvdl ahc_outb(ahc, SCBPTR, next);
5431 1.96 fvdl scb_index = ahc_inb(ahc, SCB_TAG);
5432 1.96 fvdl if (scb_index >= ahc->scb_data->numscbs) {
5433 1.96 fvdl printf("Waiting List inconsistency. "
5434 1.96 fvdl "SCB index == %d, yet numscbs == %d.",
5435 1.96 fvdl scb_index, ahc->scb_data->numscbs);
5436 1.96 fvdl ahc_dump_card_state(ahc);
5437 1.96 fvdl panic("for safety");
5438 1.96 fvdl }
5439 1.96 fvdl scb = ahc_lookup_scb(ahc, scb_index);
5440 1.96 fvdl if (scb == NULL) {
5441 1.96 fvdl printf("scb_index = %d, next = %d\n",
5442 1.96 fvdl scb_index, next);
5443 1.96 fvdl panic("Waiting List traversal\n");
5444 1.42 fvdl }
5445 1.96 fvdl if (ahc_match_scb(ahc, scb, target, channel,
5446 1.96 fvdl lun, SCB_LIST_NULL, role)) {
5447 1.96 fvdl /*
5448 1.96 fvdl * We found an scb that needs to be acted on.
5449 1.96 fvdl */
5450 1.96 fvdl found++;
5451 1.96 fvdl switch (action) {
5452 1.96 fvdl case SEARCH_COMPLETE:
5453 1.96 fvdl {
5454 1.96 fvdl cam_status ostat;
5455 1.96 fvdl cam_status cstat;
5456 1.96 fvdl
5457 1.96 fvdl ostat = ahc_get_transaction_status(scb);
5458 1.96 fvdl if (ostat == CAM_REQ_INPROG)
5459 1.96 fvdl ahc_set_transaction_status(scb, status);
5460 1.96 fvdl cstat = ahc_get_transaction_status(scb);
5461 1.96 fvdl if (cstat != CAM_REQ_CMP)
5462 1.96 fvdl ahc_freeze_scb(scb);
5463 1.96 fvdl if ((scb->flags & SCB_ACTIVE) == 0)
5464 1.96 fvdl printf("Inactive SCB in Waiting List\n");
5465 1.96 fvdl ahc_done(ahc, scb);
5466 1.96 fvdl /* FALLTHROUGH */
5467 1.96 fvdl }
5468 1.96 fvdl case SEARCH_REMOVE:
5469 1.96 fvdl next = ahc_rem_wscb(ahc, next, prev);
5470 1.96 fvdl break;
5471 1.96 fvdl case SEARCH_COUNT:
5472 1.96 fvdl prev = next;
5473 1.96 fvdl next = ahc_inb(ahc, SCB_NEXT);
5474 1.96 fvdl break;
5475 1.96 fvdl }
5476 1.42 fvdl } else {
5477 1.96 fvdl
5478 1.96 fvdl prev = next;
5479 1.96 fvdl next = ahc_inb(ahc, SCB_NEXT);
5480 1.42 fvdl }
5481 1.28 leo }
5482 1.96 fvdl ahc_outb(ahc, SCBPTR, curscbptr);
5483 1.42 fvdl
5484 1.96 fvdl found += ahc_search_untagged_queues(ahc, /*ahc_io_ctx_t*/NULL, target,
5485 1.96 fvdl channel, lun, status, action);
5486 1.42 fvdl
5487 1.96 fvdl if (action == SEARCH_COMPLETE)
5488 1.96 fvdl ahc_release_untagged_queues(ahc);
5489 1.96 fvdl return (found);
5490 1.96 fvdl }
5491 1.6 mycroft
5492 1.96 fvdl int
5493 1.96 fvdl ahc_search_untagged_queues(struct ahc_softc *ahc, struct scsipi_xfer *xs, /*ahc_io_ctx_t ctx,*/
5494 1.96 fvdl int target, char channel, int lun, uint32_t status,
5495 1.96 fvdl ahc_search_action action)
5496 1.96 fvdl {
5497 1.96 fvdl struct scb *scb;
5498 1.96 fvdl int maxtarget;
5499 1.96 fvdl int found;
5500 1.96 fvdl int i;
5501 1.42 fvdl
5502 1.96 fvdl if (action == SEARCH_COMPLETE) {
5503 1.1 mycroft /*
5504 1.96 fvdl * Don't attempt to run any queued untagged transactions
5505 1.96 fvdl * until we are done with the abort process.
5506 1.1 mycroft */
5507 1.96 fvdl ahc_freeze_untagged_queues(ahc);
5508 1.6 mycroft }
5509 1.42 fvdl
5510 1.96 fvdl found = 0;
5511 1.96 fvdl i = 0;
5512 1.96 fvdl if ((ahc->flags & AHC_SCB_BTT) == 0) {
5513 1.6 mycroft
5514 1.96 fvdl maxtarget = 16;
5515 1.96 fvdl if (target != CAM_TARGET_WILDCARD) {
5516 1.1 mycroft
5517 1.96 fvdl i = target;
5518 1.96 fvdl if (channel == 'B')
5519 1.96 fvdl i += 8;
5520 1.96 fvdl maxtarget = i + 1;
5521 1.96 fvdl }
5522 1.42 fvdl } else {
5523 1.96 fvdl maxtarget = 0;
5524 1.6 mycroft }
5525 1.6 mycroft
5526 1.96 fvdl for (; i < maxtarget; i++) {
5527 1.96 fvdl struct scb_tailq *untagged_q;
5528 1.96 fvdl struct scb *next_scb;
5529 1.6 mycroft
5530 1.96 fvdl untagged_q = &(ahc->untagged_queues[i]);
5531 1.96 fvdl next_scb = TAILQ_FIRST(untagged_q);
5532 1.96 fvdl while (next_scb != NULL) {
5533 1.42 fvdl
5534 1.96 fvdl scb = next_scb;
5535 1.96 fvdl next_scb = TAILQ_NEXT(scb, links.tqe);
5536 1.42 fvdl
5537 1.42 fvdl /*
5538 1.96 fvdl * The head of the list may be the currently
5539 1.96 fvdl * active untagged command for a device.
5540 1.96 fvdl * We're only searching for commands that
5541 1.96 fvdl * have not been started. A transaction
5542 1.96 fvdl * marked active but still in the qinfifo
5543 1.96 fvdl * is removed by the qinfifo scanning code
5544 1.96 fvdl * above.
5545 1.42 fvdl */
5546 1.96 fvdl if ((scb->flags & SCB_ACTIVE) != 0)
5547 1.96 fvdl continue;
5548 1.96 fvdl
5549 1.96 fvdl if (ahc_match_scb(ahc, scb, target, channel, lun,
5550 1.96 fvdl SCB_LIST_NULL, ROLE_INITIATOR) == 0
5551 1.96 fvdl /*|| (ctx != NULL && ctx != scb->io_ctx)*/)
5552 1.96 fvdl continue;
5553 1.42 fvdl
5554 1.96 fvdl /*
5555 1.96 fvdl * We found an scb that needs to be acted on.
5556 1.96 fvdl */
5557 1.96 fvdl found++;
5558 1.96 fvdl switch (action) {
5559 1.96 fvdl case SEARCH_COMPLETE:
5560 1.96 fvdl {
5561 1.96 fvdl cam_status ostat;
5562 1.96 fvdl cam_status cstat;
5563 1.6 mycroft
5564 1.96 fvdl ostat = ahc_get_transaction_status(scb);
5565 1.96 fvdl if (ostat == CAM_REQ_INPROG)
5566 1.96 fvdl ahc_set_transaction_status(scb, status);
5567 1.96 fvdl cstat = ahc_get_transaction_status(scb);
5568 1.96 fvdl if (cstat != CAM_REQ_CMP)
5569 1.96 fvdl ahc_freeze_scb(scb);
5570 1.96 fvdl if ((scb->flags & SCB_ACTIVE) == 0)
5571 1.96 fvdl printf("Inactive SCB in untaggedQ\n");
5572 1.96 fvdl ahc_done(ahc, scb);
5573 1.96 fvdl break;
5574 1.96 fvdl }
5575 1.96 fvdl case SEARCH_REMOVE:
5576 1.96 fvdl scb->flags &= ~SCB_UNTAGGEDQ;
5577 1.96 fvdl TAILQ_REMOVE(untagged_q, scb, links.tqe);
5578 1.96 fvdl break;
5579 1.96 fvdl case SEARCH_COUNT:
5580 1.96 fvdl break;
5581 1.6 mycroft }
5582 1.42 fvdl }
5583 1.42 fvdl }
5584 1.42 fvdl
5585 1.96 fvdl if (action == SEARCH_COMPLETE)
5586 1.96 fvdl ahc_release_untagged_queues(ahc);
5587 1.96 fvdl return (found);
5588 1.96 fvdl }
5589 1.42 fvdl
5590 1.96 fvdl int
5591 1.96 fvdl ahc_search_disc_list(struct ahc_softc *ahc, int target, char channel,
5592 1.96 fvdl int lun, u_int tag, int stop_on_first, int remove,
5593 1.96 fvdl int save_state)
5594 1.96 fvdl {
5595 1.96 fvdl struct scb *scbp;
5596 1.96 fvdl u_int next;
5597 1.96 fvdl u_int prev;
5598 1.96 fvdl u_int count;
5599 1.96 fvdl u_int active_scb;
5600 1.42 fvdl
5601 1.96 fvdl count = 0;
5602 1.96 fvdl next = ahc_inb(ahc, DISCONNECTED_SCBH);
5603 1.96 fvdl prev = SCB_LIST_NULL;
5604 1.59 pk
5605 1.96 fvdl if (save_state) {
5606 1.96 fvdl /* restore this when we're done */
5607 1.96 fvdl active_scb = ahc_inb(ahc, SCBPTR);
5608 1.96 fvdl } else
5609 1.96 fvdl /* Silence compiler */
5610 1.96 fvdl active_scb = SCB_LIST_NULL;
5611 1.9 explorer
5612 1.96 fvdl while (next != SCB_LIST_NULL) {
5613 1.96 fvdl u_int scb_index;
5614 1.1 mycroft
5615 1.96 fvdl ahc_outb(ahc, SCBPTR, next);
5616 1.96 fvdl scb_index = ahc_inb(ahc, SCB_TAG);
5617 1.96 fvdl if (scb_index >= ahc->scb_data->numscbs) {
5618 1.96 fvdl printf("Disconnected List inconsistency. "
5619 1.96 fvdl "SCB index == %d, yet numscbs == %d.",
5620 1.96 fvdl scb_index, ahc->scb_data->numscbs);
5621 1.96 fvdl ahc_dump_card_state(ahc);
5622 1.96 fvdl panic("for safety");
5623 1.96 fvdl }
5624 1.1 mycroft
5625 1.96 fvdl if (next == prev) {
5626 1.96 fvdl panic("Disconnected List Loop. "
5627 1.96 fvdl "cur SCBPTR == %x, prev SCBPTR == %x.",
5628 1.96 fvdl next, prev);
5629 1.96 fvdl }
5630 1.96 fvdl scbp = ahc_lookup_scb(ahc, scb_index);
5631 1.96 fvdl if (ahc_match_scb(ahc, scbp, target, channel, lun,
5632 1.96 fvdl tag, ROLE_INITIATOR)) {
5633 1.96 fvdl count++;
5634 1.96 fvdl if (remove) {
5635 1.96 fvdl next =
5636 1.96 fvdl ahc_rem_scb_from_disc_list(ahc, prev, next);
5637 1.96 fvdl } else {
5638 1.96 fvdl prev = next;
5639 1.96 fvdl next = ahc_inb(ahc, SCB_NEXT);
5640 1.96 fvdl }
5641 1.96 fvdl if (stop_on_first)
5642 1.96 fvdl break;
5643 1.96 fvdl } else {
5644 1.96 fvdl prev = next;
5645 1.96 fvdl next = ahc_inb(ahc, SCB_NEXT);
5646 1.96 fvdl }
5647 1.42 fvdl }
5648 1.96 fvdl if (save_state)
5649 1.96 fvdl ahc_outb(ahc, SCBPTR, active_scb);
5650 1.96 fvdl return (count);
5651 1.96 fvdl }
5652 1.1 mycroft
5653 1.96 fvdl /*
5654 1.96 fvdl * Remove an SCB from the on chip list of disconnected transactions.
5655 1.96 fvdl * This is empty/unused if we are not performing SCB paging.
5656 1.96 fvdl */
5657 1.96 fvdl static u_int
5658 1.96 fvdl ahc_rem_scb_from_disc_list(struct ahc_softc *ahc, u_int prev, u_int scbptr)
5659 1.96 fvdl {
5660 1.96 fvdl u_int next;
5661 1.96 fvdl
5662 1.96 fvdl ahc_outb(ahc, SCBPTR, scbptr);
5663 1.96 fvdl next = ahc_inb(ahc, SCB_NEXT);
5664 1.96 fvdl
5665 1.96 fvdl ahc_outb(ahc, SCB_CONTROL, 0);
5666 1.6 mycroft
5667 1.96 fvdl ahc_add_curscb_to_free_list(ahc);
5668 1.6 mycroft
5669 1.96 fvdl if (prev != SCB_LIST_NULL) {
5670 1.96 fvdl ahc_outb(ahc, SCBPTR, prev);
5671 1.96 fvdl ahc_outb(ahc, SCB_NEXT, next);
5672 1.96 fvdl } else
5673 1.96 fvdl ahc_outb(ahc, DISCONNECTED_SCBH, next);
5674 1.6 mycroft
5675 1.96 fvdl return (next);
5676 1.96 fvdl }
5677 1.42 fvdl
5678 1.96 fvdl /*
5679 1.96 fvdl * Add the SCB as selected by SCBPTR onto the on chip list of
5680 1.96 fvdl * free hardware SCBs. This list is empty/unused if we are not
5681 1.96 fvdl * performing SCB paging.
5682 1.96 fvdl */
5683 1.96 fvdl static void
5684 1.96 fvdl ahc_add_curscb_to_free_list(struct ahc_softc *ahc)
5685 1.96 fvdl {
5686 1.42 fvdl /*
5687 1.96 fvdl * Invalidate the tag so that our abort
5688 1.96 fvdl * routines don't think it's active.
5689 1.42 fvdl */
5690 1.96 fvdl ahc_outb(ahc, SCB_TAG, SCB_LIST_NULL);
5691 1.96 fvdl
5692 1.96 fvdl if ((ahc->flags & AHC_PAGESCBS) != 0) {
5693 1.96 fvdl ahc_outb(ahc, SCB_NEXT, ahc_inb(ahc, FREE_SCBH));
5694 1.96 fvdl ahc_outb(ahc, FREE_SCBH, ahc_inb(ahc, SCBPTR));
5695 1.96 fvdl }
5696 1.96 fvdl }
5697 1.96 fvdl
5698 1.96 fvdl /*
5699 1.96 fvdl * Manipulate the waiting for selection list and return the
5700 1.96 fvdl * scb that follows the one that we remove.
5701 1.96 fvdl */
5702 1.96 fvdl static u_int
5703 1.96 fvdl ahc_rem_wscb(struct ahc_softc *ahc, u_int scbpos, u_int prev)
5704 1.96 fvdl {
5705 1.96 fvdl u_int curscb, next;
5706 1.6 mycroft
5707 1.6 mycroft /*
5708 1.96 fvdl * Select the SCB we want to abort and
5709 1.96 fvdl * pull the next pointer out of it.
5710 1.96 fvdl */
5711 1.96 fvdl curscb = ahc_inb(ahc, SCBPTR);
5712 1.96 fvdl ahc_outb(ahc, SCBPTR, scbpos);
5713 1.96 fvdl next = ahc_inb(ahc, SCB_NEXT);
5714 1.6 mycroft
5715 1.96 fvdl /* Clear the necessary fields */
5716 1.96 fvdl ahc_outb(ahc, SCB_CONTROL, 0);
5717 1.6 mycroft
5718 1.96 fvdl ahc_add_curscb_to_free_list(ahc);
5719 1.1 mycroft
5720 1.96 fvdl /* update the waiting list */
5721 1.96 fvdl if (prev == SCB_LIST_NULL) {
5722 1.96 fvdl /* First in the list */
5723 1.96 fvdl ahc_outb(ahc, WAITING_SCBH, next);
5724 1.52 fvdl
5725 1.96 fvdl /*
5726 1.96 fvdl * Ensure we aren't attempting to perform
5727 1.96 fvdl * selection for this entry.
5728 1.96 fvdl */
5729 1.96 fvdl ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO));
5730 1.96 fvdl } else {
5731 1.96 fvdl /*
5732 1.96 fvdl * Select the scb that pointed to us
5733 1.96 fvdl * and update its next pointer.
5734 1.96 fvdl */
5735 1.96 fvdl ahc_outb(ahc, SCBPTR, prev);
5736 1.96 fvdl ahc_outb(ahc, SCB_NEXT, next);
5737 1.52 fvdl }
5738 1.52 fvdl
5739 1.96 fvdl /*
5740 1.96 fvdl * Point us back at the original scb position.
5741 1.96 fvdl */
5742 1.96 fvdl ahc_outb(ahc, SCBPTR, curscb);
5743 1.96 fvdl return next;
5744 1.52 fvdl }
5745 1.52 fvdl
5746 1.96 fvdl /******************************** Error Handling ******************************/
5747 1.1 mycroft /*
5748 1.96 fvdl * Abort all SCBs that match the given description (target/channel/lun/tag),
5749 1.96 fvdl * setting their status to the passed in status if the status has not already
5750 1.96 fvdl * been modified from CAM_REQ_INPROG. This routine assumes that the sequencer
5751 1.96 fvdl * is paused before it is called.
5752 1.1 mycroft */
5753 1.96 fvdl int
5754 1.96 fvdl ahc_abort_scbs(struct ahc_softc *ahc, int target, char channel,
5755 1.96 fvdl int lun, u_int tag, role_t role, uint32_t status)
5756 1.1 mycroft {
5757 1.96 fvdl struct scb *scbp;
5758 1.96 fvdl struct scb *scbp_next;
5759 1.96 fvdl u_int active_scb;
5760 1.96 fvdl int i, j;
5761 1.96 fvdl int maxtarget;
5762 1.96 fvdl int minlun;
5763 1.96 fvdl int maxlun;
5764 1.42 fvdl
5765 1.96 fvdl int found;
5766 1.18 thorpej
5767 1.96 fvdl /*
5768 1.96 fvdl * Don't attempt to run any queued untagged transactions
5769 1.96 fvdl * until we are done with the abort process.
5770 1.96 fvdl */
5771 1.96 fvdl ahc_freeze_untagged_queues(ahc);
5772 1.18 thorpej
5773 1.96 fvdl /* restore this when we're done */
5774 1.96 fvdl active_scb = ahc_inb(ahc, SCBPTR);
5775 1.18 thorpej
5776 1.96 fvdl found = ahc_search_qinfifo(ahc, target, channel, lun, SCB_LIST_NULL,
5777 1.96 fvdl role, CAM_REQUEUE_REQ, SEARCH_COMPLETE);
5778 1.42 fvdl
5779 1.96 fvdl /*
5780 1.96 fvdl * Clean out the busy target table for any untagged commands.
5781 1.96 fvdl */
5782 1.96 fvdl i = 0;
5783 1.96 fvdl maxtarget = 16;
5784 1.96 fvdl if (target != CAM_TARGET_WILDCARD) {
5785 1.96 fvdl i = target;
5786 1.96 fvdl if (channel == 'B')
5787 1.96 fvdl i += 8;
5788 1.96 fvdl maxtarget = i + 1;
5789 1.96 fvdl }
5790 1.96 fvdl
5791 1.96 fvdl if (lun == CAM_LUN_WILDCARD) {
5792 1.96 fvdl
5793 1.96 fvdl /*
5794 1.96 fvdl * Unless we are using an SCB based
5795 1.96 fvdl * busy targets table, there is only
5796 1.96 fvdl * one table entry for all luns of
5797 1.96 fvdl * a target.
5798 1.96 fvdl */
5799 1.96 fvdl minlun = 0;
5800 1.96 fvdl maxlun = 1;
5801 1.96 fvdl if ((ahc->flags & AHC_SCB_BTT) != 0)
5802 1.96 fvdl maxlun = AHC_NUM_LUNS;
5803 1.96 fvdl } else {
5804 1.96 fvdl minlun = lun;
5805 1.96 fvdl maxlun = lun + 1;
5806 1.96 fvdl }
5807 1.42 fvdl
5808 1.96 fvdl if (role != ROLE_TARGET) {
5809 1.96 fvdl for (;i < maxtarget; i++) {
5810 1.96 fvdl for (j = minlun;j < maxlun; j++) {
5811 1.96 fvdl u_int scbid;
5812 1.96 fvdl u_int tcl;
5813 1.96 fvdl
5814 1.96 fvdl tcl = BUILD_TCL(i << 4, j);
5815 1.96 fvdl scbid = ahc_index_busy_tcl(ahc, tcl);
5816 1.96 fvdl scbp = ahc_lookup_scb(ahc, scbid);
5817 1.96 fvdl if (scbp == NULL
5818 1.96 fvdl || ahc_match_scb(ahc, scbp, target, channel,
5819 1.96 fvdl lun, tag, role) == 0)
5820 1.96 fvdl continue;
5821 1.96 fvdl ahc_unbusy_tcl(ahc, BUILD_TCL(i << 4, j));
5822 1.70 bouyer }
5823 1.18 thorpej }
5824 1.18 thorpej
5825 1.18 thorpej /*
5826 1.96 fvdl * Go through the disconnected list and remove any entries we
5827 1.96 fvdl * have queued for completion, 0'ing their control byte too.
5828 1.96 fvdl * We save the active SCB and restore it ourselves, so there
5829 1.96 fvdl * is no reason for this search to restore it too.
5830 1.96 fvdl */
5831 1.96 fvdl ahc_search_disc_list(ahc, target, channel, lun, tag,
5832 1.96 fvdl /*stop_on_first*/FALSE, /*remove*/TRUE,
5833 1.96 fvdl /*save_state*/FALSE);
5834 1.96 fvdl }
5835 1.42 fvdl
5836 1.96 fvdl /*
5837 1.96 fvdl * Go through the hardware SCB array looking for commands that
5838 1.96 fvdl * were active but not on any list. In some cases, these remnants
5839 1.96 fvdl * might not still have mappings in the scbindex array (e.g. unexpected
5840 1.96 fvdl * bus free with the same scb queued for an abort). Don't hold this
5841 1.96 fvdl * against them.
5842 1.96 fvdl */
5843 1.96 fvdl for (i = 0; i < ahc->scb_data->maxhscbs; i++) {
5844 1.96 fvdl u_int scbid;
5845 1.42 fvdl
5846 1.96 fvdl ahc_outb(ahc, SCBPTR, i);
5847 1.96 fvdl scbid = ahc_inb(ahc, SCB_TAG);
5848 1.96 fvdl scbp = ahc_lookup_scb(ahc, scbid);
5849 1.96 fvdl if ((scbp == NULL && scbid != SCB_LIST_NULL)
5850 1.96 fvdl || (scbp != NULL
5851 1.96 fvdl && ahc_match_scb(ahc, scbp, target, channel, lun, tag, role)))
5852 1.96 fvdl ahc_add_curscb_to_free_list(ahc);
5853 1.96 fvdl }
5854 1.42 fvdl
5855 1.96 fvdl /*
5856 1.96 fvdl * Go through the pending CCB list and look for
5857 1.96 fvdl * commands for this target that are still active.
5858 1.96 fvdl * These are other tagged commands that were
5859 1.96 fvdl * disconnected when the reset occurred.
5860 1.96 fvdl */
5861 1.96 fvdl scbp_next = LIST_FIRST(&ahc->pending_scbs);
5862 1.96 fvdl while (scbp_next != NULL) {
5863 1.96 fvdl scbp = scbp_next;
5864 1.96 fvdl scbp_next = LIST_NEXT(scbp, pending_links);
5865 1.96 fvdl if (ahc_match_scb(ahc, scbp, target, channel, lun, tag, role)) {
5866 1.96 fvdl cam_status ostat;
5867 1.96 fvdl
5868 1.96 fvdl ostat = ahc_get_transaction_status(scbp);
5869 1.96 fvdl if (ostat == CAM_REQ_INPROG)
5870 1.96 fvdl ahc_set_transaction_status(scbp, status);
5871 1.96 fvdl if (ahc_get_transaction_status(scbp) != CAM_REQ_CMP)
5872 1.96 fvdl ahc_freeze_scb(scbp);
5873 1.96 fvdl if ((scbp->flags & SCB_ACTIVE) == 0)
5874 1.96 fvdl printf("Inactive SCB on pending list\n");
5875 1.96 fvdl ahc_done(ahc, scbp);
5876 1.96 fvdl found++;
5877 1.70 bouyer }
5878 1.42 fvdl }
5879 1.96 fvdl ahc_outb(ahc, SCBPTR, active_scb);
5880 1.96 fvdl ahc_platform_abort_scbs(ahc, target, channel, lun, tag, role, status);
5881 1.96 fvdl ahc_release_untagged_queues(ahc);
5882 1.96 fvdl return found;
5883 1.42 fvdl }
5884 1.42 fvdl
5885 1.70 bouyer static void
5886 1.96 fvdl ahc_reset_current_bus(struct ahc_softc *ahc)
5887 1.42 fvdl {
5888 1.96 fvdl uint8_t scsiseq;
5889 1.96 fvdl
5890 1.96 fvdl ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENSCSIRST);
5891 1.96 fvdl scsiseq = ahc_inb(ahc, SCSISEQ);
5892 1.96 fvdl ahc_outb(ahc, SCSISEQ, scsiseq | SCSIRSTO);
5893 1.96 fvdl ahc_flush_device_writes(ahc);
5894 1.96 fvdl ahc_delay(AHC_BUSRESET_DELAY);
5895 1.96 fvdl /* Turn off the bus reset */
5896 1.96 fvdl ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO);
5897 1.42 fvdl
5898 1.96 fvdl ahc_clear_intstat(ahc);
5899 1.42 fvdl
5900 1.96 fvdl /* Re-enable reset interrupts */
5901 1.96 fvdl ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) | ENSCSIRST);
5902 1.96 fvdl }
5903 1.42 fvdl
5904 1.96 fvdl int
5905 1.96 fvdl ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset)
5906 1.96 fvdl {
5907 1.96 fvdl struct ahc_devinfo devinfo;
5908 1.96 fvdl u_int initiator, target, max_scsiid;
5909 1.96 fvdl u_int sblkctl;
5910 1.96 fvdl u_int scsiseq;
5911 1.96 fvdl u_int simode1;
5912 1.96 fvdl int found;
5913 1.96 fvdl int restart_needed;
5914 1.96 fvdl char cur_channel;
5915 1.18 thorpej
5916 1.96 fvdl ahc->pending_device = NULL;
5917 1.59 pk
5918 1.96 fvdl ahc_compile_devinfo(&devinfo,
5919 1.96 fvdl CAM_TARGET_WILDCARD,
5920 1.96 fvdl CAM_TARGET_WILDCARD,
5921 1.96 fvdl CAM_LUN_WILDCARD,
5922 1.96 fvdl channel, ROLE_UNKNOWN);
5923 1.96 fvdl ahc_pause(ahc);
5924 1.18 thorpej
5925 1.96 fvdl /* Make sure the sequencer is in a safe location. */
5926 1.96 fvdl ahc_clear_critical_section(ahc);
5927 1.18 thorpej
5928 1.9 explorer /*
5929 1.96 fvdl * Run our command complete fifos to ensure that we perform
5930 1.96 fvdl * completion processing on any commands that 'completed'
5931 1.96 fvdl * before the reset occurred.
5932 1.96 fvdl */
5933 1.96 fvdl ahc_run_qoutfifo(ahc);
5934 1.96 fvdl #if AHC_TARGET_MODE
5935 1.96 fvdl /*
5936 1.96 fvdl * XXX - In Twin mode, the tqinfifo may have commands
5937 1.96 fvdl * for an unaffected channel in it. However, if
5938 1.96 fvdl * we have run out of ATIO resources to drain that
5939 1.96 fvdl * queue, we may not get them all out here. Further,
5940 1.96 fvdl * the blocked transactions for the reset channel
5941 1.96 fvdl * should just be killed off, irrespecitve of whether
5942 1.96 fvdl * we are blocked on ATIO resources. Write a routine
5943 1.96 fvdl * to compact the tqinfifo appropriately.
5944 1.9 explorer */
5945 1.96 fvdl if ((ahc->flags & AHC_TARGETROLE) != 0) {
5946 1.96 fvdl ahc_run_tqinfifo(ahc, /*paused*/TRUE);
5947 1.42 fvdl }
5948 1.96 fvdl #endif
5949 1.6 mycroft
5950 1.96 fvdl /*
5951 1.96 fvdl * Reset the bus if we are initiating this reset
5952 1.96 fvdl */
5953 1.96 fvdl sblkctl = ahc_inb(ahc, SBLKCTL);
5954 1.96 fvdl cur_channel = 'A';
5955 1.96 fvdl if ((ahc->features & AHC_TWIN) != 0
5956 1.96 fvdl && ((sblkctl & SELBUSB) != 0))
5957 1.96 fvdl cur_channel = 'B';
5958 1.96 fvdl scsiseq = ahc_inb(ahc, SCSISEQ_TEMPLATE);
5959 1.96 fvdl if (cur_channel != channel) {
5960 1.96 fvdl /* Case 1: Command for another bus is active
5961 1.96 fvdl * Stealthily reset the other bus without
5962 1.96 fvdl * upsetting the current bus.
5963 1.96 fvdl */
5964 1.96 fvdl ahc_outb(ahc, SBLKCTL, sblkctl ^ SELBUSB);
5965 1.96 fvdl simode1 = ahc_inb(ahc, SIMODE1) & ~(ENBUSFREE|ENSCSIRST);
5966 1.96 fvdl #if AHC_TARGET_MODE
5967 1.96 fvdl /*
5968 1.96 fvdl * Bus resets clear ENSELI, so we cannot
5969 1.96 fvdl * defer re-enabling bus reset interrupts
5970 1.96 fvdl * if we are in target mode.
5971 1.96 fvdl */
5972 1.96 fvdl if ((ahc->flags & AHC_TARGETROLE) != 0)
5973 1.96 fvdl simode1 |= ENSCSIRST;
5974 1.96 fvdl #endif
5975 1.96 fvdl ahc_outb(ahc, SIMODE1, simode1);
5976 1.96 fvdl if (initiate_reset)
5977 1.96 fvdl ahc_reset_current_bus(ahc);
5978 1.96 fvdl ahc_clear_intstat(ahc);
5979 1.96 fvdl ahc_outb(ahc, SCSISEQ, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP));
5980 1.96 fvdl ahc_outb(ahc, SBLKCTL, sblkctl);
5981 1.96 fvdl restart_needed = FALSE;
5982 1.96 fvdl } else {
5983 1.96 fvdl /* Case 2: A command from this bus is active or we're idle */
5984 1.96 fvdl simode1 = ahc_inb(ahc, SIMODE1) & ~(ENBUSFREE|ENSCSIRST);
5985 1.96 fvdl #if AHC_TARGET_MODE
5986 1.96 fvdl /*
5987 1.96 fvdl * Bus resets clear ENSELI, so we cannot
5988 1.96 fvdl * defer re-enabling bus reset interrupts
5989 1.96 fvdl * if we are in target mode.
5990 1.96 fvdl */
5991 1.96 fvdl if ((ahc->flags & AHC_TARGETROLE) != 0)
5992 1.96 fvdl simode1 |= ENSCSIRST;
5993 1.29 leo #endif
5994 1.96 fvdl ahc_outb(ahc, SIMODE1, simode1);
5995 1.96 fvdl if (initiate_reset)
5996 1.96 fvdl ahc_reset_current_bus(ahc);
5997 1.96 fvdl ahc_clear_intstat(ahc);
5998 1.96 fvdl ahc_outb(ahc, SCSISEQ, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP));
5999 1.96 fvdl restart_needed = TRUE;
6000 1.96 fvdl }
6001 1.6 mycroft
6002 1.96 fvdl /*
6003 1.96 fvdl * Clean up all the state information for the
6004 1.96 fvdl * pending transactions on this bus.
6005 1.96 fvdl */
6006 1.96 fvdl found = ahc_abort_scbs(ahc, CAM_TARGET_WILDCARD, channel,
6007 1.96 fvdl CAM_LUN_WILDCARD, SCB_LIST_NULL,
6008 1.96 fvdl ROLE_UNKNOWN, CAM_SCSI_BUS_RESET);
6009 1.59 pk
6010 1.96 fvdl max_scsiid = (ahc->features & AHC_WIDE) ? 15 : 7;
6011 1.6 mycroft
6012 1.96 fvdl #ifdef AHC_TARGET_MODE
6013 1.96 fvdl /*
6014 1.96 fvdl * Send an immediate notify ccb to all target more peripheral
6015 1.96 fvdl * drivers affected by this action.
6016 1.96 fvdl */
6017 1.96 fvdl for (target = 0; target <= max_scsiid; target++) {
6018 1.96 fvdl struct ahc_tmode_tstate* tstate;
6019 1.96 fvdl u_int lun;
6020 1.6 mycroft
6021 1.96 fvdl tstate = ahc->enabled_targets[target];
6022 1.96 fvdl if (tstate == NULL)
6023 1.96 fvdl continue;
6024 1.96 fvdl for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
6025 1.96 fvdl struct ahc_tmode_lstate* lstate;
6026 1.42 fvdl
6027 1.96 fvdl lstate = tstate->enabled_luns[lun];
6028 1.96 fvdl if (lstate == NULL)
6029 1.96 fvdl continue;
6030 1.6 mycroft
6031 1.96 fvdl ahc_queue_lstate_event(ahc, lstate, CAM_TARGET_WILDCARD,
6032 1.96 fvdl EVENT_TYPE_BUS_RESET, /*arg*/0);
6033 1.96 fvdl ahc_send_lstate_events(ahc, lstate);
6034 1.42 fvdl }
6035 1.42 fvdl }
6036 1.1 mycroft #endif
6037 1.1 mycroft /*
6038 1.96 fvdl * Revert to async/narrow transfers until we renegotiate.
6039 1.1 mycroft */
6040 1.96 fvdl for (target = 0; target <= max_scsiid; target++) {
6041 1.1 mycroft
6042 1.96 fvdl if (ahc->enabled_targets[target] == NULL)
6043 1.96 fvdl continue;
6044 1.96 fvdl for (initiator = 0; initiator <= max_scsiid; initiator++) {
6045 1.96 fvdl struct ahc_devinfo devinfo;
6046 1.42 fvdl
6047 1.96 fvdl ahc_compile_devinfo(&devinfo, target, initiator,
6048 1.96 fvdl CAM_LUN_WILDCARD,
6049 1.96 fvdl channel, ROLE_UNKNOWN);
6050 1.96 fvdl ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
6051 1.96 fvdl AHC_TRANS_CUR, /*paused*/TRUE);
6052 1.96 fvdl ahc_set_syncrate(ahc, &devinfo, /*syncrate*/NULL,
6053 1.96 fvdl /*period*/0, /*offset*/0,
6054 1.96 fvdl /*ppr_options*/0, AHC_TRANS_CUR,
6055 1.96 fvdl /*paused*/TRUE);
6056 1.96 fvdl }
6057 1.42 fvdl }
6058 1.59 pk
6059 1.96 fvdl if (restart_needed)
6060 1.96 fvdl ahc_restart(ahc);
6061 1.96 fvdl else
6062 1.96 fvdl ahc_unpause(ahc);
6063 1.96 fvdl return found;
6064 1.42 fvdl }
6065 1.42 fvdl
6066 1.96 fvdl
6067 1.96 fvdl /***************************** Residual Processing ****************************/
6068 1.96 fvdl /*
6069 1.96 fvdl * Calculate the residual for a just completed SCB.
6070 1.96 fvdl */
6071 1.96 fvdl void
6072 1.96 fvdl ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb)
6073 1.42 fvdl {
6074 1.42 fvdl struct hardware_scb *hscb;
6075 1.96 fvdl struct status_pkt *spkt;
6076 1.96 fvdl uint32_t sgptr;
6077 1.96 fvdl uint32_t resid_sgptr;
6078 1.96 fvdl uint32_t resid;
6079 1.96 fvdl
6080 1.96 fvdl /*
6081 1.96 fvdl * 5 cases.
6082 1.96 fvdl * 1) No residual.
6083 1.96 fvdl * SG_RESID_VALID clear in sgptr.
6084 1.96 fvdl * 2) Transferless command
6085 1.96 fvdl * 3) Never performed any transfers.
6086 1.96 fvdl * sgptr has SG_FULL_RESID set.
6087 1.96 fvdl * 4) No residual but target did not
6088 1.96 fvdl * save data pointers after the
6089 1.96 fvdl * last transfer, so sgptr was
6090 1.96 fvdl * never updated.
6091 1.96 fvdl * 5) We have a partial residual.
6092 1.96 fvdl * Use residual_sgptr to determine
6093 1.96 fvdl * where we are.
6094 1.96 fvdl */
6095 1.59 pk
6096 1.42 fvdl hscb = scb->hscb;
6097 1.96 fvdl sgptr = ahc_le32toh(hscb->sgptr);
6098 1.96 fvdl if ((sgptr & SG_RESID_VALID) == 0)
6099 1.96 fvdl /* Case 1 */
6100 1.96 fvdl return;
6101 1.96 fvdl sgptr &= ~SG_RESID_VALID;
6102 1.59 pk
6103 1.96 fvdl if ((sgptr & SG_LIST_NULL) != 0)
6104 1.96 fvdl /* Case 2 */
6105 1.96 fvdl return;
6106 1.42 fvdl
6107 1.96 fvdl spkt = &hscb->shared_data.status;
6108 1.96 fvdl resid_sgptr = ahc_le32toh(spkt->residual_sg_ptr);
6109 1.96 fvdl if ((sgptr & SG_FULL_RESID) != 0) {
6110 1.96 fvdl /* Case 3 */
6111 1.96 fvdl resid = ahc_get_transfer_length(scb);
6112 1.96 fvdl } else if ((resid_sgptr & SG_LIST_NULL) != 0) {
6113 1.96 fvdl /* Case 4 */
6114 1.96 fvdl return;
6115 1.96 fvdl } else if ((resid_sgptr & ~SG_PTR_MASK) != 0) {
6116 1.96 fvdl panic("Bogus resid sgptr value 0x%x\n", resid_sgptr);
6117 1.42 fvdl } else {
6118 1.96 fvdl struct ahc_dma_seg *sg;
6119 1.42 fvdl
6120 1.96 fvdl /*
6121 1.96 fvdl * Remainder of the SG where the transfer
6122 1.96 fvdl * stopped.
6123 1.96 fvdl */
6124 1.96 fvdl resid = ahc_le32toh(spkt->residual_datacnt) & AHC_SG_LEN_MASK;
6125 1.96 fvdl sg = ahc_sg_bus_to_virt(scb, resid_sgptr & SG_PTR_MASK);
6126 1.42 fvdl
6127 1.96 fvdl /* The residual sg_ptr always points to the next sg */
6128 1.96 fvdl sg--;
6129 1.42 fvdl
6130 1.96 fvdl /*
6131 1.96 fvdl * Add up the contents of all residual
6132 1.96 fvdl * SG segments that are after the SG where
6133 1.96 fvdl * the transfer stopped.
6134 1.96 fvdl */
6135 1.96 fvdl while ((ahc_le32toh(sg->len) & AHC_DMA_LAST_SEG) == 0) {
6136 1.96 fvdl sg++;
6137 1.96 fvdl resid += ahc_le32toh(sg->len) & AHC_SG_LEN_MASK;
6138 1.96 fvdl }
6139 1.96 fvdl }
6140 1.96 fvdl if ((scb->flags & SCB_SENSE) == 0)
6141 1.96 fvdl ahc_set_residual(scb, resid);
6142 1.96 fvdl else
6143 1.96 fvdl ahc_set_sense_residual(scb, resid);
6144 1.42 fvdl
6145 1.96 fvdl #ifdef AHC_DEBUG
6146 1.96 fvdl if ((ahc_debug & AHC_SHOW_MISC) != 0) {
6147 1.96 fvdl ahc_print_path(ahc, scb);
6148 1.96 fvdl printf("Handled %sResidual of %d bytes\n",
6149 1.96 fvdl (scb->flags & SCB_SENSE) ? "Sense " : "", resid);
6150 1.42 fvdl }
6151 1.96 fvdl #endif
6152 1.96 fvdl }
6153 1.96 fvdl
6154 1.96 fvdl /******************************* Target Mode **********************************/
6155 1.96 fvdl #ifdef AHC_TARGET_MODE
6156 1.96 fvdl /*
6157 1.96 fvdl * Add a target mode event to this lun's queue
6158 1.96 fvdl */
6159 1.96 fvdl static void
6160 1.96 fvdl ahc_queue_lstate_event(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate,
6161 1.96 fvdl u_int initiator_id, u_int event_type, u_int event_arg)
6162 1.96 fvdl {
6163 1.96 fvdl struct ahc_tmode_event *event;
6164 1.96 fvdl int pending;
6165 1.1 mycroft
6166 1.96 fvdl xpt_freeze_devq(lstate->path, /*count*/1);
6167 1.96 fvdl if (lstate->event_w_idx >= lstate->event_r_idx)
6168 1.96 fvdl pending = lstate->event_w_idx - lstate->event_r_idx;
6169 1.96 fvdl else
6170 1.96 fvdl pending = AHC_TMODE_EVENT_BUFFER_SIZE + 1
6171 1.96 fvdl - (lstate->event_r_idx - lstate->event_w_idx);
6172 1.42 fvdl
6173 1.96 fvdl if (event_type == EVENT_TYPE_BUS_RESET
6174 1.96 fvdl || event_type == MSG_BUS_DEV_RESET) {
6175 1.96 fvdl /*
6176 1.96 fvdl * Any earlier events are irrelevant, so reset our buffer.
6177 1.96 fvdl * This has the effect of allowing us to deal with reset
6178 1.96 fvdl * floods (an external device holding down the reset line)
6179 1.96 fvdl * without losing the event that is really interesting.
6180 1.96 fvdl */
6181 1.96 fvdl lstate->event_r_idx = 0;
6182 1.96 fvdl lstate->event_w_idx = 0;
6183 1.96 fvdl xpt_release_devq(lstate->path, pending, /*runqueue*/FALSE);
6184 1.96 fvdl }
6185 1.96 fvdl
6186 1.96 fvdl if (pending == AHC_TMODE_EVENT_BUFFER_SIZE) {
6187 1.96 fvdl xpt_print_path(lstate->path);
6188 1.96 fvdl printf("immediate event %x:%x lost\n",
6189 1.96 fvdl lstate->event_buffer[lstate->event_r_idx].event_type,
6190 1.96 fvdl lstate->event_buffer[lstate->event_r_idx].event_arg);
6191 1.96 fvdl lstate->event_r_idx++;
6192 1.96 fvdl if (lstate->event_r_idx == AHC_TMODE_EVENT_BUFFER_SIZE)
6193 1.96 fvdl lstate->event_r_idx = 0;
6194 1.96 fvdl xpt_release_devq(lstate->path, /*count*/1, /*runqueue*/FALSE);
6195 1.96 fvdl }
6196 1.96 fvdl
6197 1.96 fvdl event = &lstate->event_buffer[lstate->event_w_idx];
6198 1.96 fvdl event->initiator_id = initiator_id;
6199 1.96 fvdl event->event_type = event_type;
6200 1.96 fvdl event->event_arg = event_arg;
6201 1.96 fvdl lstate->event_w_idx++;
6202 1.96 fvdl if (lstate->event_w_idx == AHC_TMODE_EVENT_BUFFER_SIZE)
6203 1.96 fvdl lstate->event_w_idx = 0;
6204 1.96 fvdl }
6205 1.1 mycroft
6206 1.96 fvdl /*
6207 1.96 fvdl * Send any target mode events queued up waiting
6208 1.96 fvdl * for immediate notify resources.
6209 1.96 fvdl */
6210 1.96 fvdl void
6211 1.96 fvdl ahc_send_lstate_events(struct ahc_softc *ahc, struct ahc_tmode_lstate *lstate)
6212 1.96 fvdl {
6213 1.96 fvdl struct ccb_hdr *ccbh;
6214 1.96 fvdl struct ccb_immed_notify *inot;
6215 1.9 explorer
6216 1.96 fvdl while (lstate->event_r_idx != lstate->event_w_idx
6217 1.96 fvdl && (ccbh = SLIST_FIRST(&lstate->immed_notifies)) != NULL) {
6218 1.96 fvdl struct ahc_tmode_event *event;
6219 1.96 fvdl
6220 1.96 fvdl event = &lstate->event_buffer[lstate->event_r_idx];
6221 1.96 fvdl SLIST_REMOVE_HEAD(&lstate->immed_notifies, sim_links.sle);
6222 1.96 fvdl inot = (struct ccb_immed_notify *)ccbh;
6223 1.96 fvdl switch (event->event_type) {
6224 1.96 fvdl case EVENT_TYPE_BUS_RESET:
6225 1.96 fvdl ccbh->status = CAM_SCSI_BUS_RESET|CAM_DEV_QFRZN;
6226 1.96 fvdl break;
6227 1.96 fvdl default:
6228 1.96 fvdl ccbh->status = CAM_MESSAGE_RECV|CAM_DEV_QFRZN;
6229 1.96 fvdl inot->message_args[0] = event->event_type;
6230 1.96 fvdl inot->message_args[1] = event->event_arg;
6231 1.42 fvdl break;
6232 1.96 fvdl }
6233 1.96 fvdl inot->initiator_id = event->initiator_id;
6234 1.96 fvdl inot->sense_len = 0;
6235 1.96 fvdl xpt_done((union ccb *)inot);
6236 1.96 fvdl lstate->event_r_idx++;
6237 1.96 fvdl if (lstate->event_r_idx == AHC_TMODE_EVENT_BUFFER_SIZE)
6238 1.96 fvdl lstate->event_r_idx = 0;
6239 1.6 mycroft }
6240 1.96 fvdl }
6241 1.42 fvdl #endif
6242 1.96 fvdl
6243 1.96 fvdl /******************** Sequencer Program Patching/Download *********************/
6244 1.42 fvdl
6245 1.42 fvdl #ifdef AHC_DUMP_SEQ
6246 1.96 fvdl void
6247 1.42 fvdl ahc_dumpseq(struct ahc_softc* ahc)
6248 1.42 fvdl {
6249 1.42 fvdl int i;
6250 1.42 fvdl int max_prog;
6251 1.42 fvdl
6252 1.42 fvdl if ((ahc->chip & AHC_BUS_MASK) < AHC_PCI)
6253 1.42 fvdl max_prog = 448;
6254 1.42 fvdl else if ((ahc->features & AHC_ULTRA2) != 0)
6255 1.42 fvdl max_prog = 768;
6256 1.42 fvdl else
6257 1.42 fvdl max_prog = 512;
6258 1.42 fvdl
6259 1.42 fvdl ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
6260 1.42 fvdl ahc_outb(ahc, SEQADDR0, 0);
6261 1.42 fvdl ahc_outb(ahc, SEQADDR1, 0);
6262 1.42 fvdl for (i = 0; i < max_prog; i++) {
6263 1.96 fvdl uint8_t ins_bytes[4];
6264 1.42 fvdl
6265 1.42 fvdl ahc_insb(ahc, SEQRAM, ins_bytes, 4);
6266 1.42 fvdl printf("0x%08x\n", ins_bytes[0] << 24
6267 1.42 fvdl | ins_bytes[1] << 16
6268 1.42 fvdl | ins_bytes[2] << 8
6269 1.42 fvdl | ins_bytes[3]);
6270 1.6 mycroft }
6271 1.42 fvdl }
6272 1.42 fvdl #endif
6273 1.42 fvdl
6274 1.42 fvdl static void
6275 1.42 fvdl ahc_loadseq(struct ahc_softc *ahc)
6276 1.42 fvdl {
6277 1.96 fvdl struct cs cs_table[num_critical_sections];
6278 1.96 fvdl u_int begin_set[num_critical_sections];
6279 1.96 fvdl u_int end_set[num_critical_sections];
6280 1.96 fvdl struct patch *cur_patch;
6281 1.96 fvdl u_int cs_count;
6282 1.96 fvdl u_int cur_cs;
6283 1.96 fvdl u_int i;
6284 1.96 fvdl int downloaded;
6285 1.96 fvdl u_int skip_addr;
6286 1.96 fvdl u_int sg_prefetch_cnt;
6287 1.96 fvdl uint8_t download_consts[7];
6288 1.96 fvdl
6289 1.96 fvdl /*
6290 1.96 fvdl * Start out with 0 critical sections
6291 1.96 fvdl * that apply to this firmware load.
6292 1.96 fvdl */
6293 1.96 fvdl cs_count = 0;
6294 1.96 fvdl cur_cs = 0;
6295 1.96 fvdl memset(begin_set, 0, sizeof(begin_set));
6296 1.96 fvdl memset(end_set, 0, sizeof(end_set));
6297 1.42 fvdl
6298 1.42 fvdl /* Setup downloadable constant table */
6299 1.96 fvdl download_consts[QOUTFIFO_OFFSET] = 0;
6300 1.96 fvdl if (ahc->targetcmds != NULL)
6301 1.96 fvdl download_consts[QOUTFIFO_OFFSET] += 32;
6302 1.96 fvdl download_consts[QINFIFO_OFFSET] = download_consts[QOUTFIFO_OFFSET] + 1;
6303 1.96 fvdl download_consts[CACHESIZE_MASK] = ahc->pci_cachesize - 1;
6304 1.96 fvdl download_consts[INVERTED_CACHESIZE_MASK] = ~(ahc->pci_cachesize - 1);
6305 1.96 fvdl sg_prefetch_cnt = ahc->pci_cachesize;
6306 1.96 fvdl if (sg_prefetch_cnt < (2 * sizeof(struct ahc_dma_seg)))
6307 1.96 fvdl sg_prefetch_cnt = 2 * sizeof(struct ahc_dma_seg);
6308 1.96 fvdl download_consts[SG_PREFETCH_CNT] = sg_prefetch_cnt;
6309 1.96 fvdl download_consts[SG_PREFETCH_ALIGN_MASK] = ~(sg_prefetch_cnt - 1);
6310 1.96 fvdl download_consts[SG_PREFETCH_ADDR_MASK] = (sg_prefetch_cnt - 1);
6311 1.42 fvdl
6312 1.42 fvdl cur_patch = patches;
6313 1.42 fvdl downloaded = 0;
6314 1.42 fvdl skip_addr = 0;
6315 1.42 fvdl ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
6316 1.42 fvdl ahc_outb(ahc, SEQADDR0, 0);
6317 1.42 fvdl ahc_outb(ahc, SEQADDR1, 0);
6318 1.42 fvdl
6319 1.42 fvdl for (i = 0; i < sizeof(seqprog)/4; i++) {
6320 1.42 fvdl if (ahc_check_patch(ahc, &cur_patch, i, &skip_addr) == 0) {
6321 1.6 mycroft /*
6322 1.42 fvdl * Don't download this instruction as it
6323 1.42 fvdl * is in a patch that was removed.
6324 1.6 mycroft */
6325 1.96 fvdl continue;
6326 1.96 fvdl }
6327 1.96 fvdl /*
6328 1.96 fvdl * Move through the CS table until we find a CS
6329 1.96 fvdl * that might apply to this instruction.
6330 1.96 fvdl */
6331 1.96 fvdl for (; cur_cs < num_critical_sections; cur_cs++) {
6332 1.96 fvdl if (critical_sections[cur_cs].end <= i) {
6333 1.96 fvdl if (begin_set[cs_count] == TRUE
6334 1.96 fvdl && end_set[cs_count] == FALSE) {
6335 1.96 fvdl cs_table[cs_count].end = downloaded;
6336 1.96 fvdl end_set[cs_count] = TRUE;
6337 1.96 fvdl cs_count++;
6338 1.96 fvdl }
6339 1.96 fvdl continue;
6340 1.96 fvdl }
6341 1.96 fvdl if (critical_sections[cur_cs].begin <= i
6342 1.96 fvdl && begin_set[cs_count] == FALSE) {
6343 1.96 fvdl cs_table[cs_count].begin = downloaded;
6344 1.96 fvdl begin_set[cs_count] = TRUE;
6345 1.96 fvdl }
6346 1.96 fvdl break;
6347 1.42 fvdl }
6348 1.42 fvdl ahc_download_instr(ahc, i, download_consts);
6349 1.42 fvdl downloaded++;
6350 1.6 mycroft }
6351 1.96 fvdl
6352 1.96 fvdl ahc->num_critical_sections = cs_count;
6353 1.96 fvdl if (cs_count != 0) {
6354 1.96 fvdl
6355 1.96 fvdl cs_count *= sizeof(struct cs);
6356 1.96 fvdl ahc->critical_sections = malloc(cs_count, M_DEVBUF, M_NOWAIT);
6357 1.96 fvdl if (ahc->critical_sections == NULL)
6358 1.96 fvdl panic("ahc_loadseq: Could not malloc");
6359 1.96 fvdl memcpy(ahc->critical_sections, cs_table, cs_count);
6360 1.96 fvdl }
6361 1.42 fvdl ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE);
6362 1.96 fvdl ahc_restart(ahc);
6363 1.42 fvdl
6364 1.96 fvdl if (bootverbose) {
6365 1.96 fvdl printf(" %d instructions downloaded\n", downloaded);
6366 1.96 fvdl printf("%s: Features 0x%x, Bugs 0x%x, Flags 0x%x\n",
6367 1.96 fvdl ahc_name(ahc), ahc->features, ahc->bugs, ahc->flags);
6368 1.96 fvdl }
6369 1.1 mycroft }
6370 1.1 mycroft
6371 1.42 fvdl static int
6372 1.96 fvdl ahc_check_patch(struct ahc_softc *ahc, struct patch **start_patch,
6373 1.96 fvdl u_int start_instr, u_int *skip_addr)
6374 1.42 fvdl {
6375 1.96 fvdl struct patch *cur_patch;
6376 1.96 fvdl struct patch *last_patch;
6377 1.96 fvdl u_int num_patches;
6378 1.42 fvdl
6379 1.42 fvdl num_patches = sizeof(patches)/sizeof(struct patch);
6380 1.42 fvdl last_patch = &patches[num_patches];
6381 1.42 fvdl cur_patch = *start_patch;
6382 1.42 fvdl
6383 1.42 fvdl while (cur_patch < last_patch && start_instr == cur_patch->begin) {
6384 1.42 fvdl
6385 1.42 fvdl if (cur_patch->patch_func(ahc) == 0) {
6386 1.42 fvdl
6387 1.42 fvdl /* Start rejecting code */
6388 1.42 fvdl *skip_addr = start_instr + cur_patch->skip_instr;
6389 1.42 fvdl cur_patch += cur_patch->skip_patch;
6390 1.42 fvdl } else {
6391 1.42 fvdl /* Accepted this patch. Advance to the next
6392 1.42 fvdl * one and wait for our intruction pointer to
6393 1.42 fvdl * hit this point.
6394 1.42 fvdl */
6395 1.42 fvdl cur_patch++;
6396 1.28 leo }
6397 1.28 leo }
6398 1.42 fvdl
6399 1.42 fvdl *start_patch = cur_patch;
6400 1.42 fvdl if (start_instr < *skip_addr)
6401 1.42 fvdl /* Still skipping */
6402 1.42 fvdl return (0);
6403 1.42 fvdl
6404 1.42 fvdl return (1);
6405 1.28 leo }
6406 1.28 leo
6407 1.42 fvdl static void
6408 1.96 fvdl ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts)
6409 1.1 mycroft {
6410 1.42 fvdl union ins_formats instr;
6411 1.42 fvdl struct ins_format1 *fmt1_ins;
6412 1.42 fvdl struct ins_format3 *fmt3_ins;
6413 1.42 fvdl u_int opcode;
6414 1.42 fvdl
6415 1.96 fvdl /*
6416 1.96 fvdl * The firmware is always compiled into a little endian format.
6417 1.96 fvdl */
6418 1.96 fvdl instr.integer = ahc_le32toh(*(uint32_t*)&seqprog[instrptr * 4]);
6419 1.42 fvdl
6420 1.42 fvdl fmt1_ins = &instr.format1;
6421 1.42 fvdl fmt3_ins = NULL;
6422 1.42 fvdl
6423 1.42 fvdl /* Pull the opcode */
6424 1.42 fvdl opcode = instr.format1.opcode;
6425 1.42 fvdl switch (opcode) {
6426 1.42 fvdl case AIC_OP_JMP:
6427 1.42 fvdl case AIC_OP_JC:
6428 1.42 fvdl case AIC_OP_JNC:
6429 1.42 fvdl case AIC_OP_CALL:
6430 1.42 fvdl case AIC_OP_JNE:
6431 1.42 fvdl case AIC_OP_JNZ:
6432 1.42 fvdl case AIC_OP_JE:
6433 1.42 fvdl case AIC_OP_JZ:
6434 1.42 fvdl {
6435 1.96 fvdl struct patch *cur_patch;
6436 1.42 fvdl int address_offset;
6437 1.42 fvdl u_int address;
6438 1.96 fvdl u_int skip_addr;
6439 1.96 fvdl u_int i;
6440 1.42 fvdl
6441 1.42 fvdl fmt3_ins = &instr.format3;
6442 1.42 fvdl address_offset = 0;
6443 1.42 fvdl address = fmt3_ins->address;
6444 1.42 fvdl cur_patch = patches;
6445 1.42 fvdl skip_addr = 0;
6446 1.42 fvdl for (i = 0; i < address;) {
6447 1.42 fvdl ahc_check_patch(ahc, &cur_patch, i, &skip_addr);
6448 1.42 fvdl
6449 1.42 fvdl if (skip_addr > i) {
6450 1.42 fvdl int end_addr;
6451 1.42 fvdl
6452 1.42 fvdl end_addr = MIN(address, skip_addr);
6453 1.42 fvdl address_offset += end_addr - i;
6454 1.42 fvdl i = skip_addr;
6455 1.42 fvdl } else {
6456 1.42 fvdl i++;
6457 1.42 fvdl }
6458 1.1 mycroft }
6459 1.42 fvdl address -= address_offset;
6460 1.42 fvdl fmt3_ins->address = address;
6461 1.42 fvdl /* FALLTHROUGH */
6462 1.42 fvdl }
6463 1.42 fvdl case AIC_OP_OR:
6464 1.42 fvdl case AIC_OP_AND:
6465 1.42 fvdl case AIC_OP_XOR:
6466 1.42 fvdl case AIC_OP_ADD:
6467 1.42 fvdl case AIC_OP_ADC:
6468 1.42 fvdl case AIC_OP_BMOV:
6469 1.42 fvdl if (fmt1_ins->parity != 0) {
6470 1.42 fvdl fmt1_ins->immediate = dconsts[fmt1_ins->immediate];
6471 1.42 fvdl }
6472 1.42 fvdl fmt1_ins->parity = 0;
6473 1.96 fvdl if ((ahc->features & AHC_CMD_CHAN) == 0
6474 1.96 fvdl && opcode == AIC_OP_BMOV) {
6475 1.96 fvdl /*
6476 1.96 fvdl * Block move was added at the same time
6477 1.96 fvdl * as the command channel. Verify that
6478 1.96 fvdl * this is only a move of a single element
6479 1.96 fvdl * and convert the BMOV to a MOV
6480 1.96 fvdl * (AND with an immediate of FF).
6481 1.96 fvdl */
6482 1.96 fvdl if (fmt1_ins->immediate != 1)
6483 1.96 fvdl panic("%s: BMOV not supported\n",
6484 1.96 fvdl ahc_name(ahc));
6485 1.96 fvdl fmt1_ins->opcode = AIC_OP_AND;
6486 1.96 fvdl fmt1_ins->immediate = 0xff;
6487 1.96 fvdl }
6488 1.42 fvdl /* FALLTHROUGH */
6489 1.42 fvdl case AIC_OP_ROL:
6490 1.42 fvdl if ((ahc->features & AHC_ULTRA2) != 0) {
6491 1.42 fvdl int i, count;
6492 1.42 fvdl
6493 1.42 fvdl /* Calculate odd parity for the instruction */
6494 1.42 fvdl for (i = 0, count = 0; i < 31; i++) {
6495 1.96 fvdl uint32_t mask;
6496 1.42 fvdl
6497 1.42 fvdl mask = 0x01 << i;
6498 1.42 fvdl if ((instr.integer & mask) != 0)
6499 1.42 fvdl count++;
6500 1.42 fvdl }
6501 1.42 fvdl if ((count & 0x01) == 0)
6502 1.42 fvdl instr.format1.parity = 1;
6503 1.42 fvdl } else {
6504 1.42 fvdl /* Compress the instruction for older sequencers */
6505 1.42 fvdl if (fmt3_ins != NULL) {
6506 1.42 fvdl instr.integer =
6507 1.42 fvdl fmt3_ins->immediate
6508 1.42 fvdl | (fmt3_ins->source << 8)
6509 1.42 fvdl | (fmt3_ins->address << 16)
6510 1.42 fvdl | (fmt3_ins->opcode << 25);
6511 1.42 fvdl } else {
6512 1.42 fvdl instr.integer =
6513 1.42 fvdl fmt1_ins->immediate
6514 1.42 fvdl | (fmt1_ins->source << 8)
6515 1.42 fvdl | (fmt1_ins->destination << 16)
6516 1.42 fvdl | (fmt1_ins->ret << 24)
6517 1.42 fvdl | (fmt1_ins->opcode << 25);
6518 1.1 mycroft }
6519 1.1 mycroft }
6520 1.96 fvdl /* The sequencer is a little endian cpu */
6521 1.96 fvdl instr.integer = ahc_htole32(instr.integer);
6522 1.42 fvdl ahc_outsb(ahc, SEQRAM, instr.bytes, 4);
6523 1.42 fvdl break;
6524 1.42 fvdl default:
6525 1.42 fvdl panic("Unknown opcode encountered in seq program");
6526 1.6 mycroft break;
6527 1.1 mycroft }
6528 1.1 mycroft }
6529 1.1 mycroft
6530 1.96 fvdl int
6531 1.96 fvdl ahc_print_register(ahc_reg_parse_entry_t *table, u_int num_entries,
6532 1.96 fvdl const char *name, u_int address, u_int value,
6533 1.96 fvdl u_int *cur_column, u_int wrap_point)
6534 1.96 fvdl {
6535 1.96 fvdl int printed;
6536 1.96 fvdl u_int printed_mask;
6537 1.98 fvdl char line[1024];
6538 1.96 fvdl
6539 1.99 fvdl line[0] = 0;
6540 1.96 fvdl
6541 1.96 fvdl if (cur_column != NULL && *cur_column >= wrap_point) {
6542 1.96 fvdl printf("\n");
6543 1.96 fvdl *cur_column = 0;
6544 1.96 fvdl }
6545 1.99 fvdl printed = snprintf(line, sizeof(line), "%s[0x%x]", name, value);
6546 1.96 fvdl if (table == NULL) {
6547 1.99 fvdl printed += snprintf(&line[printed], (sizeof line) - printed,
6548 1.99 fvdl " ");
6549 1.98 fvdl printf("%s", line);
6550 1.98 fvdl if (cur_column != NULL)
6551 1.98 fvdl *cur_column += printed;
6552 1.96 fvdl return (printed);
6553 1.96 fvdl }
6554 1.96 fvdl printed_mask = 0;
6555 1.96 fvdl while (printed_mask != 0xFF) {
6556 1.96 fvdl int entry;
6557 1.96 fvdl
6558 1.96 fvdl for (entry = 0; entry < num_entries; entry++) {
6559 1.96 fvdl if (((value & table[entry].mask)
6560 1.96 fvdl != table[entry].value)
6561 1.96 fvdl || ((printed_mask & table[entry].mask)
6562 1.96 fvdl == table[entry].mask))
6563 1.96 fvdl continue;
6564 1.98 fvdl printed += snprintf(&line[printed],
6565 1.98 fvdl (sizeof line) - printed, "%s%s",
6566 1.96 fvdl printed_mask == 0 ? ":(" : "|",
6567 1.96 fvdl table[entry].name);
6568 1.96 fvdl printed_mask |= table[entry].mask;
6569 1.96 fvdl
6570 1.96 fvdl break;
6571 1.42 fvdl }
6572 1.96 fvdl if (entry >= num_entries)
6573 1.96 fvdl break;
6574 1.6 mycroft }
6575 1.96 fvdl if (printed_mask != 0)
6576 1.98 fvdl printed += snprintf(&line[printed],
6577 1.98 fvdl (sizeof line) - printed, ") ");
6578 1.96 fvdl else
6579 1.98 fvdl printed += snprintf(&line[printed],
6580 1.98 fvdl (sizeof line) - printed, " ");
6581 1.96 fvdl if (cur_column != NULL)
6582 1.96 fvdl *cur_column += printed;
6583 1.98 fvdl printf("%s", line);
6584 1.96 fvdl
6585 1.96 fvdl return (printed);
6586 1.6 mycroft }
6587 1.6 mycroft
6588 1.96 fvdl void
6589 1.96 fvdl ahc_dump_card_state(struct ahc_softc *ahc)
6590 1.6 mycroft {
6591 1.42 fvdl struct scb *scb;
6592 1.96 fvdl struct scb_tailq *untagged_q;
6593 1.96 fvdl u_int cur_col;
6594 1.96 fvdl int paused;
6595 1.42 fvdl int target;
6596 1.96 fvdl int maxtarget;
6597 1.42 fvdl int i;
6598 1.96 fvdl uint8_t last_phase;
6599 1.96 fvdl uint8_t qinpos;
6600 1.96 fvdl uint8_t qintail;
6601 1.96 fvdl uint8_t qoutpos;
6602 1.96 fvdl uint8_t scb_index;
6603 1.96 fvdl uint8_t saved_scbptr;
6604 1.6 mycroft
6605 1.96 fvdl if (ahc_is_paused(ahc)) {
6606 1.96 fvdl paused = 1;
6607 1.96 fvdl } else {
6608 1.96 fvdl paused = 0;
6609 1.96 fvdl ahc_pause(ahc);
6610 1.6 mycroft }
6611 1.6 mycroft
6612 1.96 fvdl saved_scbptr = ahc_inb(ahc, SCBPTR);
6613 1.42 fvdl last_phase = ahc_inb(ahc, LASTPHASE);
6614 1.96 fvdl printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n"
6615 1.96 fvdl "%s: Dumping Card State %s, at SEQADDR 0x%x\n",
6616 1.96 fvdl ahc_name(ahc), ahc_lookup_phase_entry(last_phase)->phasemsg,
6617 1.42 fvdl ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
6618 1.96 fvdl if (paused)
6619 1.96 fvdl printf("Card was paused\n");
6620 1.96 fvdl printf("ACCUM = 0x%x, SINDEX = 0x%x, DINDEX = 0x%x, ARG_2 = 0x%x\n",
6621 1.96 fvdl ahc_inb(ahc, ACCUM), ahc_inb(ahc, SINDEX), ahc_inb(ahc, DINDEX),
6622 1.96 fvdl ahc_inb(ahc, ARG_2));
6623 1.96 fvdl printf("HCNT = 0x%x SCBPTR = 0x%x\n", ahc_inb(ahc, HCNT),
6624 1.96 fvdl ahc_inb(ahc, SCBPTR));
6625 1.96 fvdl cur_col = 0;
6626 1.96 fvdl if ((ahc->features & AHC_DT) != 0)
6627 1.96 fvdl ahc_scsiphase_print(ahc_inb(ahc, SCSIPHASE), &cur_col, 50);
6628 1.96 fvdl ahc_scsisigi_print(ahc_inb(ahc, SCSISIGI), &cur_col, 50);
6629 1.96 fvdl ahc_error_print(ahc_inb(ahc, ERROR), &cur_col, 50);
6630 1.96 fvdl ahc_scsibusl_print(ahc_inb(ahc, SCSIBUSL), &cur_col, 50);
6631 1.96 fvdl ahc_lastphase_print(ahc_inb(ahc, LASTPHASE), &cur_col, 50);
6632 1.96 fvdl ahc_scsiseq_print(ahc_inb(ahc, SCSISEQ), &cur_col, 50);
6633 1.96 fvdl ahc_sblkctl_print(ahc_inb(ahc, SBLKCTL), &cur_col, 50);
6634 1.96 fvdl ahc_scsirate_print(ahc_inb(ahc, SCSIRATE), &cur_col, 50);
6635 1.96 fvdl ahc_seqctl_print(ahc_inb(ahc, SEQCTL), &cur_col, 50);
6636 1.96 fvdl ahc_seq_flags_print(ahc_inb(ahc, SEQ_FLAGS), &cur_col, 50);
6637 1.96 fvdl ahc_sstat0_print(ahc_inb(ahc, SSTAT0), &cur_col, 50);
6638 1.96 fvdl ahc_sstat1_print(ahc_inb(ahc, SSTAT1), &cur_col, 50);
6639 1.96 fvdl ahc_sstat2_print(ahc_inb(ahc, SSTAT2), &cur_col, 50);
6640 1.96 fvdl ahc_sstat3_print(ahc_inb(ahc, SSTAT3), &cur_col, 50);
6641 1.96 fvdl ahc_simode0_print(ahc_inb(ahc, SIMODE0), &cur_col, 50);
6642 1.96 fvdl ahc_simode1_print(ahc_inb(ahc, SIMODE1), &cur_col, 50);
6643 1.96 fvdl ahc_sxfrctl0_print(ahc_inb(ahc, SXFRCTL0), &cur_col, 50);
6644 1.96 fvdl ahc_dfcntrl_print(ahc_inb(ahc, DFCNTRL), &cur_col, 50);
6645 1.96 fvdl ahc_dfstatus_print(ahc_inb(ahc, DFSTATUS), &cur_col, 50);
6646 1.96 fvdl if (cur_col != 0)
6647 1.96 fvdl printf("\n");
6648 1.96 fvdl printf("STACK:");
6649 1.96 fvdl for (i = 0; i < STACK_SIZE; i++)
6650 1.96 fvdl printf(" 0x%x", ahc_inb(ahc, STACK)|(ahc_inb(ahc, STACK) << 8));
6651 1.96 fvdl printf("\nSCB count = %d\n", ahc->scb_data->numscbs);
6652 1.96 fvdl printf("Kernel NEXTQSCB = %d\n", ahc->next_queued_scb->hscb->tag);
6653 1.96 fvdl printf("Card NEXTQSCB = %d\n", ahc_inb(ahc, NEXT_QUEUED_SCB));
6654 1.96 fvdl /* QINFIFO */
6655 1.96 fvdl printf("QINFIFO entries: ");
6656 1.96 fvdl if ((ahc->features & AHC_QUEUE_REGS) != 0) {
6657 1.96 fvdl qinpos = ahc_inb(ahc, SNSCB_QOFF);
6658 1.96 fvdl ahc_outb(ahc, SNSCB_QOFF, qinpos);
6659 1.96 fvdl } else
6660 1.96 fvdl qinpos = ahc_inb(ahc, QINPOS);
6661 1.42 fvdl qintail = ahc->qinfifonext;
6662 1.42 fvdl while (qinpos != qintail) {
6663 1.96 fvdl printf("%d ", ahc->qinfifo[qinpos]);
6664 1.42 fvdl qinpos++;
6665 1.42 fvdl }
6666 1.96 fvdl printf("\n");
6667 1.42 fvdl
6668 1.96 fvdl printf("Waiting Queue entries: ");
6669 1.96 fvdl scb_index = ahc_inb(ahc, WAITING_SCBH);
6670 1.96 fvdl i = 0;
6671 1.96 fvdl while (scb_index != SCB_LIST_NULL && i++ < 256) {
6672 1.96 fvdl ahc_outb(ahc, SCBPTR, scb_index);
6673 1.96 fvdl printf("%d:%d ", scb_index, ahc_inb(ahc, SCB_TAG));
6674 1.96 fvdl scb_index = ahc_inb(ahc, SCB_NEXT);
6675 1.6 mycroft }
6676 1.96 fvdl printf("\n");
6677 1.1 mycroft
6678 1.96 fvdl printf("Disconnected Queue entries: ");
6679 1.96 fvdl scb_index = ahc_inb(ahc, DISCONNECTED_SCBH);
6680 1.96 fvdl i = 0;
6681 1.96 fvdl while (scb_index != SCB_LIST_NULL && i++ < 256) {
6682 1.96 fvdl ahc_outb(ahc, SCBPTR, scb_index);
6683 1.96 fvdl printf("%d:%d ", scb_index, ahc_inb(ahc, SCB_TAG));
6684 1.96 fvdl scb_index = ahc_inb(ahc, SCB_NEXT);
6685 1.96 fvdl }
6686 1.96 fvdl printf("\n");
6687 1.96 fvdl
6688 1.96 fvdl ahc_sync_qoutfifo(ahc, BUS_DMASYNC_POSTREAD);
6689 1.96 fvdl printf("QOUTFIFO entries: ");
6690 1.96 fvdl qoutpos = ahc->qoutfifonext;
6691 1.96 fvdl i = 0;
6692 1.96 fvdl while (ahc->qoutfifo[qoutpos] != SCB_LIST_NULL && i++ < 256) {
6693 1.96 fvdl printf("%d ", ahc->qoutfifo[qoutpos]);
6694 1.96 fvdl qoutpos++;
6695 1.1 mycroft }
6696 1.96 fvdl printf("\n");
6697 1.42 fvdl
6698 1.96 fvdl printf("Sequencer Free SCB List: ");
6699 1.96 fvdl scb_index = ahc_inb(ahc, FREE_SCBH);
6700 1.96 fvdl i = 0;
6701 1.96 fvdl while (scb_index != SCB_LIST_NULL && i++ < 256) {
6702 1.96 fvdl ahc_outb(ahc, SCBPTR, scb_index);
6703 1.96 fvdl printf("%d ", scb_index);
6704 1.96 fvdl scb_index = ahc_inb(ahc, SCB_NEXT);
6705 1.96 fvdl }
6706 1.96 fvdl printf("\n");
6707 1.42 fvdl
6708 1.96 fvdl printf("Sequencer SCB Info: ");
6709 1.96 fvdl for (i = 0; i < ahc->scb_data->maxhscbs; i++) {
6710 1.42 fvdl ahc_outb(ahc, SCBPTR, i);
6711 1.96 fvdl /*cur_col =*/ printf("\n%3d ", i);
6712 1.96 fvdl
6713 1.96 fvdl ahc_scb_control_print(ahc_inb(ahc, SCB_CONTROL), &cur_col, 60);
6714 1.96 fvdl ahc_scb_scsiid_print(ahc_inb(ahc, SCB_SCSIID), &cur_col, 60);
6715 1.96 fvdl ahc_scb_lun_print(ahc_inb(ahc, SCB_LUN), &cur_col, 60);
6716 1.96 fvdl ahc_scb_tag_print(ahc_inb(ahc, SCB_TAG), &cur_col, 60);
6717 1.42 fvdl }
6718 1.96 fvdl printf("\n");
6719 1.42 fvdl
6720 1.96 fvdl printf("Pending list: ");
6721 1.96 fvdl i = 0;
6722 1.96 fvdl LIST_FOREACH(scb, &ahc->pending_scbs, pending_links) {
6723 1.96 fvdl if (i++ > 256)
6724 1.96 fvdl break;
6725 1.96 fvdl /*cur_col =*/ printf("\n%3d ", scb->hscb->tag);
6726 1.96 fvdl ahc_scb_control_print(scb->hscb->control, &cur_col, 60);
6727 1.96 fvdl ahc_scb_scsiid_print(scb->hscb->scsiid, &cur_col, 60);
6728 1.96 fvdl ahc_scb_lun_print(scb->hscb->lun, &cur_col, 60);
6729 1.96 fvdl if ((ahc->flags & AHC_PAGESCBS) == 0) {
6730 1.96 fvdl ahc_outb(ahc, SCBPTR, scb->hscb->tag);
6731 1.96 fvdl printf("(");
6732 1.96 fvdl ahc_scb_control_print(ahc_inb(ahc, SCB_CONTROL),
6733 1.96 fvdl &cur_col, 60);
6734 1.96 fvdl ahc_scb_tag_print(ahc_inb(ahc, SCB_TAG), &cur_col, 60);
6735 1.96 fvdl printf(")");
6736 1.6 mycroft }
6737 1.42 fvdl }
6738 1.96 fvdl printf("\n");
6739 1.6 mycroft
6740 1.96 fvdl printf("Kernel Free SCB list: ");
6741 1.96 fvdl i = 0;
6742 1.96 fvdl SLIST_FOREACH(scb, &ahc->scb_data->free_scbs, links.sle) {
6743 1.96 fvdl if (i++ > 256)
6744 1.96 fvdl break;
6745 1.96 fvdl printf("%d ", scb->hscb->tag);
6746 1.96 fvdl }
6747 1.96 fvdl printf("\n");
6748 1.42 fvdl
6749 1.96 fvdl maxtarget = (ahc->features & (AHC_WIDE|AHC_TWIN)) ? 15 : 7;
6750 1.96 fvdl for (target = 0; target <= maxtarget; target++) {
6751 1.96 fvdl untagged_q = &ahc->untagged_queues[target];
6752 1.96 fvdl if (TAILQ_FIRST(untagged_q) == NULL)
6753 1.96 fvdl continue;
6754 1.96 fvdl printf("Untagged Q(%d): ", target);
6755 1.96 fvdl i = 0;
6756 1.96 fvdl TAILQ_FOREACH(scb, untagged_q, links.tqe) {
6757 1.96 fvdl if (i++ > 256)
6758 1.42 fvdl break;
6759 1.96 fvdl printf("%d ", scb->hscb->tag);
6760 1.42 fvdl }
6761 1.96 fvdl printf("\n");
6762 1.42 fvdl }
6763 1.96 fvdl
6764 1.96 fvdl ahc_platform_dump_card_state(ahc);
6765 1.96 fvdl printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n");
6766 1.96 fvdl ahc_outb(ahc, SCBPTR, saved_scbptr);
6767 1.96 fvdl if (paused == 0)
6768 1.96 fvdl ahc_unpause(ahc);
6769 1.42 fvdl }
6770 1.42 fvdl
6771 1.96 fvdl /************************* Target Mode ****************************************/
6772 1.96 fvdl #ifdef AHC_TARGET_MODE
6773 1.96 fvdl cam_status
6774 1.96 fvdl ahc_find_tmode_devs(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb,
6775 1.96 fvdl struct ahc_tmode_tstate **tstate,
6776 1.96 fvdl struct ahc_tmode_lstate **lstate,
6777 1.96 fvdl int notfound_failure)
6778 1.42 fvdl {
6779 1.42 fvdl
6780 1.96 fvdl if ((ahc->features & AHC_TARGETMODE) == 0)
6781 1.96 fvdl return (CAM_REQ_INVALID);
6782 1.42 fvdl
6783 1.96 fvdl /*
6784 1.96 fvdl * Handle the 'black hole' device that sucks up
6785 1.96 fvdl * requests to unattached luns on enabled targets.
6786 1.96 fvdl */
6787 1.96 fvdl if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD
6788 1.96 fvdl && ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) {
6789 1.96 fvdl *tstate = NULL;
6790 1.96 fvdl *lstate = ahc->black_hole;
6791 1.96 fvdl } else {
6792 1.96 fvdl u_int max_id;
6793 1.42 fvdl
6794 1.96 fvdl max_id = (ahc->features & AHC_WIDE) ? 15 : 7;
6795 1.96 fvdl if (ccb->ccb_h.target_id > max_id)
6796 1.96 fvdl return (CAM_TID_INVALID);
6797 1.42 fvdl
6798 1.96 fvdl if (ccb->ccb_h.target_lun >= AHC_NUM_LUNS)
6799 1.96 fvdl return (CAM_LUN_INVALID);
6800 1.42 fvdl
6801 1.96 fvdl *tstate = ahc->enabled_targets[ccb->ccb_h.target_id];
6802 1.96 fvdl *lstate = NULL;
6803 1.96 fvdl if (*tstate != NULL)
6804 1.96 fvdl *lstate =
6805 1.96 fvdl (*tstate)->enabled_luns[ccb->ccb_h.target_lun];
6806 1.96 fvdl }
6807 1.42 fvdl
6808 1.96 fvdl if (notfound_failure != 0 && *lstate == NULL)
6809 1.96 fvdl return (CAM_PATH_INVALID);
6810 1.42 fvdl
6811 1.96 fvdl return (CAM_REQ_CMP);
6812 1.42 fvdl }
6813 1.42 fvdl
6814 1.96 fvdl void
6815 1.96 fvdl ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
6816 1.59 pk {
6817 1.96 fvdl struct ahc_tmode_tstate *tstate;
6818 1.96 fvdl struct ahc_tmode_lstate *lstate;
6819 1.96 fvdl struct ccb_en_lun *cel;
6820 1.96 fvdl cam_status status;
6821 1.96 fvdl u_int target;
6822 1.96 fvdl u_int lun;
6823 1.96 fvdl u_int target_mask;
6824 1.96 fvdl u_int our_id;
6825 1.96 fvdl u_long s;
6826 1.96 fvdl char channel;
6827 1.6 mycroft
6828 1.96 fvdl status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate, &lstate,
6829 1.96 fvdl /*notfound_failure*/FALSE);
6830 1.42 fvdl
6831 1.96 fvdl if (status != CAM_REQ_CMP) {
6832 1.96 fvdl ccb->ccb_h.status = status;
6833 1.96 fvdl return;
6834 1.96 fvdl }
6835 1.6 mycroft
6836 1.96 fvdl if (cam_sim_bus(sim) == 0)
6837 1.96 fvdl our_id = ahc->our_id;
6838 1.96 fvdl else
6839 1.96 fvdl our_id = ahc->our_id_b;
6840 1.42 fvdl
6841 1.96 fvdl if (ccb->ccb_h.target_id != our_id) {
6842 1.42 fvdl /*
6843 1.96 fvdl * our_id represents our initiator ID, or
6844 1.96 fvdl * the ID of the first target to have an
6845 1.96 fvdl * enabled lun in target mode. There are
6846 1.96 fvdl * two cases that may preclude enabling a
6847 1.96 fvdl * target id other than our_id.
6848 1.96 fvdl *
6849 1.96 fvdl * o our_id is for an active initiator role.
6850 1.96 fvdl * Since the hardware does not support
6851 1.96 fvdl * reselections to the initiator role at
6852 1.96 fvdl * anything other than our_id, and our_id
6853 1.96 fvdl * is used by the hardware to indicate the
6854 1.96 fvdl * ID to use for both select-out and
6855 1.96 fvdl * reselect-out operations, the only target
6856 1.96 fvdl * ID we can support in this mode is our_id.
6857 1.96 fvdl *
6858 1.96 fvdl * o The MULTARGID feature is not available and
6859 1.96 fvdl * a previous target mode ID has been enabled.
6860 1.42 fvdl */
6861 1.96 fvdl if ((ahc->features & AHC_MULTIROLE) != 0) {
6862 1.96 fvdl
6863 1.96 fvdl if ((ahc->features & AHC_MULTI_TID) != 0
6864 1.96 fvdl && (ahc->flags & AHC_INITIATORROLE) != 0) {
6865 1.96 fvdl /*
6866 1.96 fvdl * Only allow additional targets if
6867 1.96 fvdl * the initiator role is disabled.
6868 1.96 fvdl * The hardware cannot handle a re-select-in
6869 1.96 fvdl * on the initiator id during a re-select-out
6870 1.96 fvdl * on a different target id.
6871 1.96 fvdl */
6872 1.96 fvdl status = CAM_TID_INVALID;
6873 1.96 fvdl } else if ((ahc->flags & AHC_INITIATORROLE) != 0
6874 1.96 fvdl || ahc->enabled_luns > 0) {
6875 1.96 fvdl /*
6876 1.96 fvdl * Only allow our target id to change
6877 1.96 fvdl * if the initiator role is not configured
6878 1.96 fvdl * and there are no enabled luns which
6879 1.96 fvdl * are attached to the currently registered
6880 1.96 fvdl * scsi id.
6881 1.96 fvdl */
6882 1.96 fvdl status = CAM_TID_INVALID;
6883 1.96 fvdl }
6884 1.96 fvdl } else if ((ahc->features & AHC_MULTI_TID) == 0
6885 1.96 fvdl && ahc->enabled_luns > 0) {
6886 1.96 fvdl
6887 1.96 fvdl status = CAM_TID_INVALID;
6888 1.96 fvdl }
6889 1.96 fvdl }
6890 1.96 fvdl
6891 1.96 fvdl if (status != CAM_REQ_CMP) {
6892 1.96 fvdl ccb->ccb_h.status = status;
6893 1.96 fvdl return;
6894 1.1 mycroft }
6895 1.42 fvdl
6896 1.1 mycroft /*
6897 1.96 fvdl * We now have an id that is valid.
6898 1.96 fvdl * If we aren't in target mode, switch modes.
6899 1.42 fvdl */
6900 1.96 fvdl if ((ahc->flags & AHC_TARGETROLE) == 0
6901 1.96 fvdl && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
6902 1.96 fvdl u_long s;
6903 1.96 fvdl
6904 1.96 fvdl printf("Configuring Target Mode\n");
6905 1.96 fvdl ahc_lock(ahc, &s);
6906 1.96 fvdl if (LIST_FIRST(&ahc->pending_scbs) != NULL) {
6907 1.96 fvdl ccb->ccb_h.status = CAM_BUSY;
6908 1.96 fvdl ahc_unlock(ahc, &s);
6909 1.96 fvdl return;
6910 1.96 fvdl }
6911 1.96 fvdl ahc->flags |= AHC_TARGETROLE;
6912 1.96 fvdl if ((ahc->features & AHC_MULTIROLE) == 0)
6913 1.96 fvdl ahc->flags &= ~AHC_INITIATORROLE;
6914 1.96 fvdl ahc_pause(ahc);
6915 1.96 fvdl ahc_loadseq(ahc);
6916 1.96 fvdl ahc_unlock(ahc, &s);
6917 1.96 fvdl }
6918 1.96 fvdl cel = &ccb->cel;
6919 1.96 fvdl target = ccb->ccb_h.target_id;
6920 1.96 fvdl lun = ccb->ccb_h.target_lun;
6921 1.96 fvdl channel = SIM_CHANNEL(ahc, sim);
6922 1.96 fvdl target_mask = 0x01 << target;
6923 1.96 fvdl if (channel == 'B')
6924 1.96 fvdl target_mask <<= 8;
6925 1.42 fvdl
6926 1.96 fvdl if (cel->enable != 0) {
6927 1.96 fvdl u_int scsiseq;
6928 1.42 fvdl
6929 1.96 fvdl /* Are we already enabled?? */
6930 1.96 fvdl if (lstate != NULL) {
6931 1.96 fvdl xpt_print_path(ccb->ccb_h.path);
6932 1.96 fvdl printf("Lun already enabled\n");
6933 1.96 fvdl ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
6934 1.96 fvdl return;
6935 1.96 fvdl }
6936 1.42 fvdl
6937 1.96 fvdl if (cel->grp6_len != 0
6938 1.96 fvdl || cel->grp7_len != 0) {
6939 1.96 fvdl /*
6940 1.96 fvdl * Don't (yet?) support vendor
6941 1.96 fvdl * specific commands.
6942 1.96 fvdl */
6943 1.96 fvdl ccb->ccb_h.status = CAM_REQ_INVALID;
6944 1.96 fvdl printf("Non-zero Group Codes\n");
6945 1.96 fvdl return;
6946 1.96 fvdl }
6947 1.42 fvdl
6948 1.96 fvdl /*
6949 1.96 fvdl * Seems to be okay.
6950 1.96 fvdl * Setup our data structures.
6951 1.96 fvdl */
6952 1.96 fvdl if (target != CAM_TARGET_WILDCARD && tstate == NULL) {
6953 1.96 fvdl tstate = ahc_alloc_tstate(ahc, target, channel);
6954 1.96 fvdl if (tstate == NULL) {
6955 1.96 fvdl xpt_print_path(ccb->ccb_h.path);
6956 1.96 fvdl printf("Couldn't allocate tstate\n");
6957 1.96 fvdl ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
6958 1.96 fvdl return;
6959 1.96 fvdl }
6960 1.96 fvdl }
6961 1.96 fvdl lstate = malloc(sizeof(*lstate), M_DEVBUF, M_NOWAIT);
6962 1.96 fvdl if (lstate == NULL) {
6963 1.96 fvdl xpt_print_path(ccb->ccb_h.path);
6964 1.96 fvdl printf("Couldn't allocate lstate\n");
6965 1.96 fvdl ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
6966 1.96 fvdl return;
6967 1.96 fvdl }
6968 1.96 fvdl memset(lstate, 0, sizeof(*lstate));
6969 1.96 fvdl status = xpt_create_path(&lstate->path, /*periph*/NULL,
6970 1.96 fvdl xpt_path_path_id(ccb->ccb_h.path),
6971 1.96 fvdl xpt_path_target_id(ccb->ccb_h.path),
6972 1.96 fvdl xpt_path_lun_id(ccb->ccb_h.path));
6973 1.96 fvdl if (status != CAM_REQ_CMP) {
6974 1.96 fvdl free(lstate, M_DEVBUF);
6975 1.96 fvdl xpt_print_path(ccb->ccb_h.path);
6976 1.96 fvdl printf("Couldn't allocate path\n");
6977 1.96 fvdl ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
6978 1.96 fvdl return;
6979 1.96 fvdl }
6980 1.96 fvdl SLIST_INIT(&lstate->accept_tios);
6981 1.96 fvdl SLIST_INIT(&lstate->immed_notifies);
6982 1.96 fvdl ahc_lock(ahc, &s);
6983 1.96 fvdl ahc_pause(ahc);
6984 1.96 fvdl if (target != CAM_TARGET_WILDCARD) {
6985 1.96 fvdl tstate->enabled_luns[lun] = lstate;
6986 1.96 fvdl ahc->enabled_luns++;
6987 1.96 fvdl
6988 1.96 fvdl if ((ahc->features & AHC_MULTI_TID) != 0) {
6989 1.96 fvdl u_int targid_mask;
6990 1.96 fvdl
6991 1.96 fvdl targid_mask = ahc_inb(ahc, TARGID)
6992 1.96 fvdl | (ahc_inb(ahc, TARGID + 1) << 8);
6993 1.96 fvdl
6994 1.96 fvdl targid_mask |= target_mask;
6995 1.96 fvdl ahc_outb(ahc, TARGID, targid_mask);
6996 1.96 fvdl ahc_outb(ahc, TARGID+1, (targid_mask >> 8));
6997 1.96 fvdl
6998 1.96 fvdl ahc_update_scsiid(ahc, targid_mask);
6999 1.96 fvdl } else {
7000 1.96 fvdl u_int our_id;
7001 1.96 fvdl char channel;
7002 1.42 fvdl
7003 1.96 fvdl channel = SIM_CHANNEL(ahc, sim);
7004 1.96 fvdl our_id = SIM_SCSI_ID(ahc, sim);
7005 1.42 fvdl
7006 1.96 fvdl /*
7007 1.96 fvdl * This can only happen if selections
7008 1.96 fvdl * are not enabled
7009 1.96 fvdl */
7010 1.96 fvdl if (target != our_id) {
7011 1.96 fvdl u_int sblkctl;
7012 1.96 fvdl char cur_channel;
7013 1.96 fvdl int swap;
7014 1.96 fvdl
7015 1.96 fvdl sblkctl = ahc_inb(ahc, SBLKCTL);
7016 1.96 fvdl cur_channel = (sblkctl & SELBUSB)
7017 1.96 fvdl ? 'B' : 'A';
7018 1.96 fvdl if ((ahc->features & AHC_TWIN) == 0)
7019 1.96 fvdl cur_channel = 'A';
7020 1.96 fvdl swap = cur_channel != channel;
7021 1.96 fvdl if (channel == 'A')
7022 1.96 fvdl ahc->our_id = target;
7023 1.96 fvdl else
7024 1.96 fvdl ahc->our_id_b = target;
7025 1.96 fvdl
7026 1.96 fvdl if (swap)
7027 1.96 fvdl ahc_outb(ahc, SBLKCTL,
7028 1.96 fvdl sblkctl ^ SELBUSB);
7029 1.42 fvdl
7030 1.96 fvdl ahc_outb(ahc, SCSIID, target);
7031 1.42 fvdl
7032 1.96 fvdl if (swap)
7033 1.96 fvdl ahc_outb(ahc, SBLKCTL, sblkctl);
7034 1.96 fvdl }
7035 1.96 fvdl }
7036 1.96 fvdl } else
7037 1.96 fvdl ahc->black_hole = lstate;
7038 1.96 fvdl /* Allow select-in operations */
7039 1.96 fvdl if (ahc->black_hole != NULL && ahc->enabled_luns > 0) {
7040 1.96 fvdl scsiseq = ahc_inb(ahc, SCSISEQ_TEMPLATE);
7041 1.96 fvdl scsiseq |= ENSELI;
7042 1.96 fvdl ahc_outb(ahc, SCSISEQ_TEMPLATE, scsiseq);
7043 1.96 fvdl scsiseq = ahc_inb(ahc, SCSISEQ);
7044 1.96 fvdl scsiseq |= ENSELI;
7045 1.96 fvdl ahc_outb(ahc, SCSISEQ, scsiseq);
7046 1.96 fvdl }
7047 1.96 fvdl ahc_unpause(ahc);
7048 1.96 fvdl ahc_unlock(ahc, &s);
7049 1.96 fvdl ccb->ccb_h.status = CAM_REQ_CMP;
7050 1.96 fvdl xpt_print_path(ccb->ccb_h.path);
7051 1.96 fvdl printf("Lun now enabled for target mode\n");
7052 1.42 fvdl } else {
7053 1.96 fvdl struct scb *scb;
7054 1.96 fvdl int i, empty;
7055 1.6 mycroft
7056 1.96 fvdl if (lstate == NULL) {
7057 1.96 fvdl ccb->ccb_h.status = CAM_LUN_INVALID;
7058 1.96 fvdl return;
7059 1.96 fvdl }
7060 1.42 fvdl
7061 1.96 fvdl ahc_lock(ahc, &s);
7062 1.96 fvdl
7063 1.96 fvdl ccb->ccb_h.status = CAM_REQ_CMP;
7064 1.96 fvdl LIST_FOREACH(scb, &ahc->pending_scbs, pending_links) {
7065 1.96 fvdl struct ccb_hdr *ccbh;
7066 1.96 fvdl
7067 1.96 fvdl ccbh = &scb->io_ctx->ccb_h;
7068 1.96 fvdl if (ccbh->func_code == XPT_CONT_TARGET_IO
7069 1.96 fvdl && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){
7070 1.96 fvdl printf("CTIO pending\n");
7071 1.96 fvdl ccb->ccb_h.status = CAM_REQ_INVALID;
7072 1.96 fvdl ahc_unlock(ahc, &s);
7073 1.96 fvdl return;
7074 1.96 fvdl }
7075 1.96 fvdl }
7076 1.42 fvdl
7077 1.96 fvdl if (SLIST_FIRST(&lstate->accept_tios) != NULL) {
7078 1.96 fvdl printf("ATIOs pending\n");
7079 1.96 fvdl ccb->ccb_h.status = CAM_REQ_INVALID;
7080 1.96 fvdl }
7081 1.42 fvdl
7082 1.96 fvdl if (SLIST_FIRST(&lstate->immed_notifies) != NULL) {
7083 1.96 fvdl printf("INOTs pending\n");
7084 1.96 fvdl ccb->ccb_h.status = CAM_REQ_INVALID;
7085 1.96 fvdl }
7086 1.42 fvdl
7087 1.96 fvdl if (ccb->ccb_h.status != CAM_REQ_CMP) {
7088 1.96 fvdl ahc_unlock(ahc, &s);
7089 1.96 fvdl return;
7090 1.42 fvdl }
7091 1.42 fvdl
7092 1.96 fvdl xpt_print_path(ccb->ccb_h.path);
7093 1.96 fvdl printf("Target mode disabled\n");
7094 1.96 fvdl xpt_free_path(lstate->path);
7095 1.96 fvdl free(lstate, M_DEVBUF);
7096 1.96 fvdl
7097 1.96 fvdl ahc_pause(ahc);
7098 1.96 fvdl /* Can we clean up the target too? */
7099 1.96 fvdl if (target != CAM_TARGET_WILDCARD) {
7100 1.96 fvdl tstate->enabled_luns[lun] = NULL;
7101 1.96 fvdl ahc->enabled_luns--;
7102 1.96 fvdl for (empty = 1, i = 0; i < 8; i++)
7103 1.96 fvdl if (tstate->enabled_luns[i] != NULL) {
7104 1.96 fvdl empty = 0;
7105 1.96 fvdl break;
7106 1.96 fvdl }
7107 1.42 fvdl
7108 1.96 fvdl if (empty) {
7109 1.96 fvdl ahc_free_tstate(ahc, target, channel,
7110 1.96 fvdl /*force*/FALSE);
7111 1.96 fvdl if (ahc->features & AHC_MULTI_TID) {
7112 1.96 fvdl u_int targid_mask;
7113 1.96 fvdl
7114 1.96 fvdl targid_mask = ahc_inb(ahc, TARGID)
7115 1.96 fvdl | (ahc_inb(ahc, TARGID + 1)
7116 1.96 fvdl << 8);
7117 1.96 fvdl
7118 1.96 fvdl targid_mask &= ~target_mask;
7119 1.96 fvdl ahc_outb(ahc, TARGID, targid_mask);
7120 1.96 fvdl ahc_outb(ahc, TARGID+1,
7121 1.96 fvdl (targid_mask >> 8));
7122 1.96 fvdl ahc_update_scsiid(ahc, targid_mask);
7123 1.96 fvdl }
7124 1.96 fvdl }
7125 1.96 fvdl } else {
7126 1.42 fvdl
7127 1.96 fvdl ahc->black_hole = NULL;
7128 1.42 fvdl
7129 1.96 fvdl /*
7130 1.96 fvdl * We can't allow selections without
7131 1.96 fvdl * our black hole device.
7132 1.96 fvdl */
7133 1.96 fvdl empty = TRUE;
7134 1.96 fvdl }
7135 1.96 fvdl if (ahc->enabled_luns == 0) {
7136 1.96 fvdl /* Disallow select-in */
7137 1.96 fvdl u_int scsiseq;
7138 1.96 fvdl
7139 1.96 fvdl scsiseq = ahc_inb(ahc, SCSISEQ_TEMPLATE);
7140 1.96 fvdl scsiseq &= ~ENSELI;
7141 1.96 fvdl ahc_outb(ahc, SCSISEQ_TEMPLATE, scsiseq);
7142 1.96 fvdl scsiseq = ahc_inb(ahc, SCSISEQ);
7143 1.96 fvdl scsiseq &= ~ENSELI;
7144 1.96 fvdl ahc_outb(ahc, SCSISEQ, scsiseq);
7145 1.96 fvdl
7146 1.96 fvdl if ((ahc->features & AHC_MULTIROLE) == 0) {
7147 1.96 fvdl printf("Configuring Initiator Mode\n");
7148 1.96 fvdl ahc->flags &= ~AHC_TARGETROLE;
7149 1.96 fvdl ahc->flags |= AHC_INITIATORROLE;
7150 1.96 fvdl ahc_pause(ahc);
7151 1.96 fvdl ahc_loadseq(ahc);
7152 1.96 fvdl }
7153 1.96 fvdl }
7154 1.96 fvdl ahc_unpause(ahc);
7155 1.96 fvdl ahc_unlock(ahc, &s);
7156 1.96 fvdl }
7157 1.6 mycroft }
7158 1.6 mycroft
7159 1.6 mycroft static void
7160 1.96 fvdl ahc_update_scsiid(struct ahc_softc *ahc, u_int targid_mask)
7161 1.6 mycroft {
7162 1.96 fvdl u_int scsiid_mask;
7163 1.96 fvdl u_int scsiid;
7164 1.96 fvdl
7165 1.96 fvdl if ((ahc->features & AHC_MULTI_TID) == 0)
7166 1.96 fvdl panic("ahc_update_scsiid called on non-multitid unit\n");
7167 1.96 fvdl
7168 1.96 fvdl /*
7169 1.96 fvdl * Since we will rely on the TARGID mask
7170 1.96 fvdl * for selection enables, ensure that OID
7171 1.96 fvdl * in SCSIID is not set to some other ID
7172 1.96 fvdl * that we don't want to allow selections on.
7173 1.96 fvdl */
7174 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0)
7175 1.96 fvdl scsiid = ahc_inb(ahc, SCSIID_ULTRA2);
7176 1.96 fvdl else
7177 1.96 fvdl scsiid = ahc_inb(ahc, SCSIID);
7178 1.96 fvdl scsiid_mask = 0x1 << (scsiid & OID);
7179 1.96 fvdl if ((targid_mask & scsiid_mask) == 0) {
7180 1.96 fvdl u_int our_id;
7181 1.1 mycroft
7182 1.96 fvdl /* ffs counts from 1 */
7183 1.96 fvdl our_id = ffs(targid_mask);
7184 1.96 fvdl if (our_id == 0)
7185 1.96 fvdl our_id = ahc->our_id;
7186 1.96 fvdl else
7187 1.96 fvdl our_id--;
7188 1.96 fvdl scsiid &= TID;
7189 1.96 fvdl scsiid |= our_id;
7190 1.96 fvdl }
7191 1.96 fvdl if ((ahc->features & AHC_ULTRA2) != 0)
7192 1.96 fvdl ahc_outb(ahc, SCSIID_ULTRA2, scsiid);
7193 1.96 fvdl else
7194 1.96 fvdl ahc_outb(ahc, SCSIID, scsiid);
7195 1.1 mycroft }
7196 1.1 mycroft
7197 1.96 fvdl void
7198 1.96 fvdl ahc_run_tqinfifo(struct ahc_softc *ahc, int paused)
7199 1.1 mycroft {
7200 1.96 fvdl struct target_cmd *cmd;
7201 1.6 mycroft
7202 1.6 mycroft /*
7203 1.96 fvdl * If the card supports auto-access pause,
7204 1.96 fvdl * we can access the card directly regardless
7205 1.96 fvdl * of whether it is paused or not.
7206 1.96 fvdl */
7207 1.96 fvdl if ((ahc->features & AHC_AUTOPAUSE) != 0)
7208 1.96 fvdl paused = TRUE;
7209 1.59 pk
7210 1.96 fvdl ahc_sync_tqinfifo(ahc, BUS_DMASYNC_POSTREAD);
7211 1.96 fvdl while ((cmd = &ahc->targetcmds[ahc->tqinfifonext])->cmd_valid != 0) {
7212 1.1 mycroft
7213 1.6 mycroft /*
7214 1.96 fvdl * Only advance through the queue if we
7215 1.96 fvdl * have the resources to process the command.
7216 1.6 mycroft */
7217 1.96 fvdl if (ahc_handle_target_cmd(ahc, cmd) != 0)
7218 1.96 fvdl break;
7219 1.42 fvdl
7220 1.96 fvdl cmd->cmd_valid = 0;
7221 1.96 fvdl ahc_dmamap_sync(ahc, ahc->parent_dmat/*shared_data_dmat*/,
7222 1.96 fvdl ahc->shared_data_dmamap,
7223 1.96 fvdl ahc_targetcmd_offset(ahc, ahc->tqinfifonext),
7224 1.96 fvdl sizeof(struct target_cmd),
7225 1.96 fvdl BUS_DMASYNC_PREREAD);
7226 1.96 fvdl ahc->tqinfifonext++;
7227 1.96 fvdl
7228 1.96 fvdl /*
7229 1.96 fvdl * Lazily update our position in the target mode incoming
7230 1.96 fvdl * command queue as seen by the sequencer.
7231 1.96 fvdl */
7232 1.96 fvdl if ((ahc->tqinfifonext & (HOST_TQINPOS - 1)) == 1) {
7233 1.96 fvdl if ((ahc->features & AHC_HS_MAILBOX) != 0) {
7234 1.96 fvdl u_int hs_mailbox;
7235 1.96 fvdl
7236 1.96 fvdl hs_mailbox = ahc_inb(ahc, HS_MAILBOX);
7237 1.96 fvdl hs_mailbox &= ~HOST_TQINPOS;
7238 1.96 fvdl hs_mailbox |= ahc->tqinfifonext & HOST_TQINPOS;
7239 1.96 fvdl ahc_outb(ahc, HS_MAILBOX, hs_mailbox);
7240 1.96 fvdl } else {
7241 1.96 fvdl if (!paused)
7242 1.96 fvdl ahc_pause(ahc);
7243 1.96 fvdl ahc_outb(ahc, KERNEL_TQINPOS,
7244 1.96 fvdl ahc->tqinfifonext & HOST_TQINPOS);
7245 1.96 fvdl if (!paused)
7246 1.96 fvdl ahc_unpause(ahc);
7247 1.96 fvdl }
7248 1.6 mycroft }
7249 1.42 fvdl }
7250 1.96 fvdl }
7251 1.96 fvdl
7252 1.96 fvdl static int
7253 1.96 fvdl ahc_handle_target_cmd(struct ahc_softc *ahc, struct target_cmd *cmd)
7254 1.96 fvdl {
7255 1.96 fvdl struct ahc_tmode_tstate *tstate;
7256 1.96 fvdl struct ahc_tmode_lstate *lstate;
7257 1.96 fvdl struct ccb_accept_tio *atio;
7258 1.96 fvdl uint8_t *byte;
7259 1.96 fvdl int initiator;
7260 1.96 fvdl int target;
7261 1.96 fvdl int lun;
7262 1.96 fvdl
7263 1.96 fvdl initiator = SCSIID_TARGET(ahc, cmd->scsiid);
7264 1.96 fvdl target = SCSIID_OUR_ID(cmd->scsiid);
7265 1.96 fvdl lun = (cmd->identify & MSG_IDENTIFY_LUNMASK);
7266 1.96 fvdl
7267 1.96 fvdl byte = cmd->bytes;
7268 1.96 fvdl tstate = ahc->enabled_targets[target];
7269 1.96 fvdl lstate = NULL;
7270 1.96 fvdl if (tstate != NULL)
7271 1.96 fvdl lstate = tstate->enabled_luns[lun];
7272 1.42 fvdl
7273 1.42 fvdl /*
7274 1.96 fvdl * Commands for disabled luns go to the black hole driver.
7275 1.42 fvdl */
7276 1.96 fvdl if (lstate == NULL)
7277 1.96 fvdl lstate = ahc->black_hole;
7278 1.42 fvdl
7279 1.96 fvdl atio = (struct ccb_accept_tio*)SLIST_FIRST(&lstate->accept_tios);
7280 1.96 fvdl if (atio == NULL) {
7281 1.96 fvdl ahc->flags |= AHC_TQINFIFO_BLOCKED;
7282 1.96 fvdl /*
7283 1.96 fvdl * Wait for more ATIOs from the peripheral driver for this lun.
7284 1.96 fvdl */
7285 1.96 fvdl if (bootverbose)
7286 1.96 fvdl printf("%s: ATIOs exhausted\n", ahc_name(ahc));
7287 1.96 fvdl return (1);
7288 1.96 fvdl } else
7289 1.96 fvdl ahc->flags &= ~AHC_TQINFIFO_BLOCKED;
7290 1.96 fvdl #if 0
7291 1.96 fvdl printf("Incoming command from %d for %d:%d%s\n",
7292 1.96 fvdl initiator, target, lun,
7293 1.96 fvdl lstate == ahc->black_hole ? "(Black Holed)" : "");
7294 1.42 fvdl #endif
7295 1.96 fvdl SLIST_REMOVE_HEAD(&lstate->accept_tios, sim_links.sle);
7296 1.42 fvdl
7297 1.96 fvdl if (lstate == ahc->black_hole) {
7298 1.96 fvdl /* Fill in the wildcards */
7299 1.96 fvdl atio->ccb_h.target_id = target;
7300 1.96 fvdl atio->ccb_h.target_lun = lun;
7301 1.96 fvdl }
7302 1.42 fvdl
7303 1.42 fvdl /*
7304 1.96 fvdl * Package it up and send it off to
7305 1.96 fvdl * whomever has this lun enabled.
7306 1.42 fvdl */
7307 1.96 fvdl atio->sense_len = 0;
7308 1.96 fvdl atio->init_id = initiator;
7309 1.96 fvdl if (byte[0] != 0xFF) {
7310 1.96 fvdl /* Tag was included */
7311 1.96 fvdl atio->tag_action = *byte++;
7312 1.96 fvdl atio->tag_id = *byte++;
7313 1.96 fvdl atio->ccb_h.flags = CAM_TAG_ACTION_VALID;
7314 1.96 fvdl } else {
7315 1.96 fvdl atio->ccb_h.flags = 0;
7316 1.42 fvdl }
7317 1.96 fvdl byte++;
7318 1.42 fvdl
7319 1.96 fvdl /* Okay. Now determine the cdb size based on the command code */
7320 1.96 fvdl switch (*byte >> CMD_GROUP_CODE_SHIFT) {
7321 1.96 fvdl case 0:
7322 1.96 fvdl atio->cdb_len = 6;
7323 1.96 fvdl break;
7324 1.96 fvdl case 1:
7325 1.96 fvdl case 2:
7326 1.96 fvdl atio->cdb_len = 10;
7327 1.96 fvdl break;
7328 1.96 fvdl case 4:
7329 1.96 fvdl atio->cdb_len = 16;
7330 1.96 fvdl break;
7331 1.96 fvdl case 5:
7332 1.96 fvdl atio->cdb_len = 12;
7333 1.96 fvdl break;
7334 1.96 fvdl case 3:
7335 1.96 fvdl default:
7336 1.96 fvdl /* Only copy the opcode. */
7337 1.96 fvdl atio->cdb_len = 1;
7338 1.96 fvdl printf("Reserved or VU command code type encountered\n");
7339 1.96 fvdl break;
7340 1.1 mycroft }
7341 1.96 fvdl
7342 1.96 fvdl memcpy(atio->cdb_io.cdb_bytes, byte, atio->cdb_len);
7343 1.42 fvdl
7344 1.96 fvdl atio->ccb_h.status |= CAM_CDB_RECVD;
7345 1.42 fvdl
7346 1.96 fvdl if ((cmd->identify & MSG_IDENTIFY_DISCFLAG) == 0) {
7347 1.96 fvdl /*
7348 1.96 fvdl * We weren't allowed to disconnect.
7349 1.96 fvdl * We're hanging on the bus until a
7350 1.96 fvdl * continue target I/O comes in response
7351 1.96 fvdl * to this accept tio.
7352 1.96 fvdl */
7353 1.96 fvdl #if 0
7354 1.96 fvdl printf("Received Immediate Command %d:%d:%d - %p\n",
7355 1.96 fvdl initiator, target, lun, ahc->pending_device);
7356 1.96 fvdl #endif
7357 1.96 fvdl ahc->pending_device = lstate;
7358 1.96 fvdl ahc_freeze_ccb((union ccb *)atio);
7359 1.96 fvdl atio->ccb_h.flags |= CAM_DIS_DISCONNECT;
7360 1.1 mycroft }
7361 1.96 fvdl xpt_done((union ccb*)atio);
7362 1.96 fvdl return (0);
7363 1.6 mycroft }
7364 1.42 fvdl #endif
7365 1.42 fvdl
7366 1.96 fvdl static int
7367 1.96 fvdl ahc_createdmamem(tag, size, flags, mapp, vaddr, baddr, seg, nseg, myname, what)
7368 1.96 fvdl bus_dma_tag_t tag;
7369 1.96 fvdl int size;
7370 1.96 fvdl int flags;
7371 1.96 fvdl bus_dmamap_t *mapp;
7372 1.96 fvdl caddr_t *vaddr;
7373 1.96 fvdl bus_addr_t *baddr;
7374 1.96 fvdl bus_dma_segment_t *seg;
7375 1.96 fvdl int *nseg;
7376 1.96 fvdl const char *myname, *what;
7377 1.6 mycroft {
7378 1.96 fvdl int error, level = 0;
7379 1.42 fvdl
7380 1.96 fvdl if ((error = bus_dmamem_alloc(tag, size, PAGE_SIZE, 0,
7381 1.96 fvdl seg, 1, nseg, BUS_DMA_NOWAIT)) != 0) {
7382 1.96 fvdl printf("%s: failed to allocate DMA mem for %s, error = %d\n",
7383 1.96 fvdl myname, what, error);
7384 1.96 fvdl goto out;
7385 1.96 fvdl }
7386 1.96 fvdl level++;
7387 1.42 fvdl
7388 1.96 fvdl if ((error = bus_dmamem_map(tag, seg, *nseg, size, vaddr,
7389 1.96 fvdl BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
7390 1.96 fvdl printf("%s: failed to map DMA mem for %s, error = %d\n",
7391 1.96 fvdl myname, what, error);
7392 1.96 fvdl goto out;
7393 1.96 fvdl }
7394 1.96 fvdl level++;
7395 1.42 fvdl
7396 1.96 fvdl if ((error = bus_dmamap_create(tag, size, 1, size, 0,
7397 1.96 fvdl BUS_DMA_NOWAIT | flags, mapp)) != 0) {
7398 1.96 fvdl printf("%s: failed to create DMA map for %s, error = %d\n",
7399 1.96 fvdl myname, what, error);
7400 1.96 fvdl goto out;
7401 1.96 fvdl }
7402 1.96 fvdl level++;
7403 1.42 fvdl
7404 1.42 fvdl
7405 1.96 fvdl if ((error = bus_dmamap_load(tag, *mapp, *vaddr, size, NULL,
7406 1.96 fvdl BUS_DMA_NOWAIT)) != 0) {
7407 1.96 fvdl printf("%s: failed to load DMA map for %s, error = %d\n",
7408 1.96 fvdl myname, what, error);
7409 1.96 fvdl goto out;
7410 1.96 fvdl }
7411 1.42 fvdl
7412 1.96 fvdl *baddr = (*mapp)->dm_segs[0].ds_addr;
7413 1.1 mycroft
7414 1.96 fvdl return 0;
7415 1.96 fvdl out:
7416 1.96 fvdl printf("ahc_createdmamem error (%d)\n", level);
7417 1.96 fvdl switch (level) {
7418 1.96 fvdl case 3:
7419 1.96 fvdl bus_dmamap_destroy(tag, *mapp);
7420 1.96 fvdl /* FALLTHROUGH */
7421 1.96 fvdl case 2:
7422 1.96 fvdl bus_dmamem_unmap(tag, *vaddr, size);
7423 1.96 fvdl /* FALLTHROUGH */
7424 1.96 fvdl case 1:
7425 1.96 fvdl bus_dmamem_free(tag, seg, *nseg);
7426 1.96 fvdl break;
7427 1.96 fvdl default:
7428 1.96 fvdl break;
7429 1.42 fvdl }
7430 1.14 gibbs
7431 1.96 fvdl return error;
7432 1.14 gibbs }
7433 1.14 gibbs
7434 1.14 gibbs static void
7435 1.96 fvdl ahc_freedmamem(tag, size, map, vaddr, seg, nseg)
7436 1.96 fvdl bus_dma_tag_t tag;
7437 1.96 fvdl int size;
7438 1.96 fvdl bus_dmamap_t map;
7439 1.96 fvdl caddr_t vaddr;
7440 1.96 fvdl bus_dma_segment_t *seg;
7441 1.96 fvdl int nseg;
7442 1.14 gibbs {
7443 1.42 fvdl
7444 1.96 fvdl bus_dmamap_unload(tag, map);
7445 1.96 fvdl bus_dmamap_destroy(tag, map);
7446 1.96 fvdl bus_dmamem_unmap(tag, vaddr, size);
7447 1.96 fvdl bus_dmamem_free(tag, seg, nseg);
7448 1.45 fvdl }
7449