aic7xxx.c revision 1.55 1 1.55 fvdl /* $NetBSD: aic7xxx.c,v 1.55 2000/06/04 11:42:55 fvdl Exp $ */
2 1.8 thorpej
3 1.1 mycroft /*
4 1.1 mycroft * Generic driver for the aic7xxx based adaptec SCSI controllers
5 1.1 mycroft * Product specific probe and attach routines can be found in:
6 1.42 fvdl * i386/eisa/ahc_eisa.c 27/284X and aic7770 motherboard controllers
7 1.42 fvdl * pci/ahc_pci.c 3985, 3980, 3940, 2940, aic7895, aic7890,
8 1.42 fvdl * aic7880, aic7870, aic7860, and aic7850 controllers
9 1.1 mycroft *
10 1.42 fvdl * Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999, 2000 Justin T. Gibbs.
11 1.6 mycroft * All rights reserved.
12 1.1 mycroft *
13 1.6 mycroft * Redistribution and use in source and binary forms, with or without
14 1.6 mycroft * modification, are permitted provided that the following conditions
15 1.6 mycroft * are met:
16 1.6 mycroft * 1. Redistributions of source code must retain the above copyright
17 1.42 fvdl * notice, this list of conditions, and the following disclaimer,
18 1.42 fvdl * without modification.
19 1.42 fvdl * 2. The name of the author may not be used to endorse or promote products
20 1.6 mycroft * derived from this software without specific prior written permission.
21 1.1 mycroft *
22 1.42 fvdl * Alternatively, this software may be distributed under the terms of the
23 1.42 fvdl * the GNU Public License ("GPL").
24 1.42 fvdl *
25 1.6 mycroft * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
26 1.6 mycroft * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 1.6 mycroft * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 1.6 mycroft * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
29 1.6 mycroft * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 1.6 mycroft * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 1.6 mycroft * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 1.6 mycroft * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 1.6 mycroft * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 1.6 mycroft * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 1.6 mycroft * SUCH DAMAGE.
36 1.9 explorer *
37 1.45 fvdl * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.c,v 1.42 2000/03/18 22:28:18 gibbs Exp $
38 1.1 mycroft */
39 1.1 mycroft /*
40 1.42 fvdl * A few notes on features of the driver.
41 1.6 mycroft *
42 1.6 mycroft * SCB paging takes advantage of the fact that devices stay disconnected
43 1.6 mycroft * from the bus a relatively long time and that while they're disconnected,
44 1.42 fvdl * having the SCBs for these transactions down on the host adapter is of
45 1.42 fvdl * little use. Instead of leaving this idle SCB down on the card we copy
46 1.42 fvdl * it back up into kernel memory and reuse the SCB slot on the card to
47 1.42 fvdl * schedule another transaction. This can be a real payoff when doing random
48 1.42 fvdl * I/O to tagged queueing devices since there are more transactions active at
49 1.42 fvdl * once for the device to sort for optimal seek reduction. The algorithm goes
50 1.42 fvdl * like this...
51 1.6 mycroft *
52 1.42 fvdl * The sequencer maintains two lists of its hardware SCBs. The first is the
53 1.42 fvdl * singly linked free list which tracks all SCBs that are not currently in
54 1.42 fvdl * use. The second is the doubly linked disconnected list which holds the
55 1.42 fvdl * SCBs of transactions that are in the disconnected state sorted most
56 1.42 fvdl * recently disconnected first. When the kernel queues a transaction to
57 1.42 fvdl * the card, a hardware SCB to "house" this transaction is retrieved from
58 1.42 fvdl * either of these two lists. If the SCB came from the disconnected list,
59 1.42 fvdl * a check is made to see if any data transfer or SCB linking (more on linking
60 1.42 fvdl * in a bit) information has been changed since it was copied from the host
61 1.42 fvdl * and if so, DMAs the SCB back up before it can be used. Once a hardware
62 1.42 fvdl * SCB has been obtained, the SCB is DMAed from the host. Before any work
63 1.42 fvdl * can begin on this SCB, the sequencer must ensure that either the SCB is
64 1.42 fvdl * for a tagged transaction or the target is not already working on another
65 1.42 fvdl * non-tagged transaction. If a conflict arises in the non-tagged case, the
66 1.42 fvdl * sequencer finds the SCB for the active transactions and sets the SCB_LINKED
67 1.42 fvdl * field in that SCB to this next SCB to execute. To facilitate finding
68 1.42 fvdl * active non-tagged SCBs, the last four bytes of up to the first four hardware
69 1.42 fvdl * SCBs serve as a storage area for the currently active SCB ID for each
70 1.42 fvdl * target.
71 1.6 mycroft *
72 1.42 fvdl * When a device reconnects, a search is made of the hardware SCBs to find
73 1.42 fvdl * the SCB for this transaction. If the search fails, a hardware SCB is
74 1.42 fvdl * pulled from either the free or disconnected SCB list and the proper
75 1.42 fvdl * SCB is DMAed from the host. If the MK_MESSAGE control bit is set
76 1.42 fvdl * in the control byte of the SCB while it was disconnected, the sequencer
77 1.42 fvdl * will assert ATN and attempt to issue a message to the host.
78 1.6 mycroft *
79 1.42 fvdl * When a command completes, a check for non-zero status and residuals is
80 1.42 fvdl * made. If either of these conditions exists, the SCB is DMAed back up to
81 1.42 fvdl * the host so that it can interpret this information. Additionally, in the
82 1.42 fvdl * case of bad status, the sequencer generates a special interrupt and pauses
83 1.42 fvdl * itself. This allows the host to setup a request sense command if it
84 1.42 fvdl * chooses for this target synchronously with the error so that sense
85 1.42 fvdl * information isn't lost.
86 1.6 mycroft *
87 1.1 mycroft */
88 1.1 mycroft
89 1.42 fvdl #include "opt_ddb.h"
90 1.42 fvdl
91 1.1 mycroft #include <sys/param.h>
92 1.42 fvdl #include <sys/kernel.h>
93 1.1 mycroft #include <sys/systm.h>
94 1.1 mycroft #include <sys/device.h>
95 1.1 mycroft #include <sys/malloc.h>
96 1.1 mycroft #include <sys/buf.h>
97 1.1 mycroft #include <sys/proc.h>
98 1.52 fvdl #include <sys/scsiio.h>
99 1.1 mycroft
100 1.42 fvdl #include <machine/bus.h>
101 1.42 fvdl #include <machine/intr.h>
102 1.42 fvdl
103 1.25 bouyer #include <dev/scsipi/scsi_all.h>
104 1.25 bouyer #include <dev/scsipi/scsipi_all.h>
105 1.25 bouyer #include <dev/scsipi/scsi_message.h>
106 1.25 bouyer #include <dev/scsipi/scsipi_debug.h>
107 1.25 bouyer #include <dev/scsipi/scsiconf.h>
108 1.1 mycroft
109 1.6 mycroft #include <vm/vm.h>
110 1.6 mycroft #include <vm/vm_param.h>
111 1.6 mycroft #include <vm/pmap.h>
112 1.1 mycroft
113 1.6 mycroft #include <dev/ic/aic7xxxvar.h>
114 1.42 fvdl #include <dev/microcode/aic7xxx/sequencer.h>
115 1.42 fvdl #include <dev/microcode/aic7xxx/aic7xxx_reg.h>
116 1.42 fvdl #include <dev/microcode/aic7xxx/aic7xxx_seq.h>
117 1.42 fvdl
118 1.55 fvdl #define XS_STS_DEBUG 0x00000002
119 1.55 fvdl
120 1.42 fvdl #define MAX(a,b) (((a) > (b)) ? (a) : (b))
121 1.42 fvdl #define MIN(a,b) (((a) < (b)) ? (a) : (b))
122 1.42 fvdl #define ALL_CHANNELS '\0'
123 1.42 fvdl #define ALL_TARGETS_MASK 0xFFFF
124 1.42 fvdl #define INITIATOR_WILDCARD (~0)
125 1.1 mycroft
126 1.42 fvdl #define SIM_IS_SCSIBUS_B(ahc, sc_link) \
127 1.42 fvdl ((sc_link)->scsipi_scsi.scsibus == (ahc)->sc_link_b.scsipi_scsi.scsibus)
128 1.42 fvdl #define SIM_CHANNEL(ahc, sc_link) \
129 1.42 fvdl (SIM_IS_SCSIBUS_B(ahc, sc_link) ? 'B' : 'A')
130 1.42 fvdl #define SIM_SCSI_ID(ahc, sc_link) \
131 1.42 fvdl (SIM_IS_SCSIBUS_B(ahc, sc_link) ? ahc->our_id_b : ahc->our_id)
132 1.42 fvdl #define SCB_IS_SCSIBUS_B(scb) \
133 1.42 fvdl (((scb)->hscb->tcl & SELBUSB) != 0)
134 1.42 fvdl #define SCB_TARGET(scb) \
135 1.42 fvdl (((scb)->hscb->tcl & TID) >> 4)
136 1.42 fvdl #define SCB_CHANNEL(scb) \
137 1.42 fvdl (SCB_IS_SCSIBUS_B(scb) ? 'B' : 'A')
138 1.42 fvdl #define SCB_LUN(scb) \
139 1.42 fvdl ((scb)->hscb->tcl & LID)
140 1.42 fvdl #define SCB_TARGET_OFFSET(scb) \
141 1.42 fvdl (SCB_TARGET(scb) + (SCB_IS_SCSIBUS_B(scb) ? 8 : 0))
142 1.42 fvdl #define SCB_TARGET_MASK(scb) \
143 1.42 fvdl (0x01 << (SCB_TARGET_OFFSET(scb)))
144 1.42 fvdl #define TCL_CHANNEL(ahc, tcl) \
145 1.42 fvdl ((((ahc)->features & AHC_TWIN) && ((tcl) & SELBUSB)) ? 'B' : 'A')
146 1.42 fvdl #define TCL_SCSI_ID(ahc, tcl) \
147 1.42 fvdl (TCL_CHANNEL((ahc), (tcl)) == 'B' ? (ahc)->our_id_b : (ahc)->our_id)
148 1.42 fvdl #define TCL_TARGET(tcl) (((tcl) & TID) >> TCL_TARGET_SHIFT)
149 1.42 fvdl #define TCL_LUN(tcl) ((tcl) & LID)
150 1.42 fvdl
151 1.42 fvdl #define XS_TCL(ahc, xs) \
152 1.42 fvdl ((((xs)->sc_link->scsipi_scsi.target << 4) & 0xF0) \
153 1.42 fvdl | (SIM_IS_SCSIBUS_B((ahc), (xs)->sc_link) ? SELBUSB : 0) \
154 1.42 fvdl | ((xs)->sc_link->scsipi_scsi.lun & 0x07))
155 1.1 mycroft
156 1.42 fvdl char *ahc_chip_names[] =
157 1.42 fvdl {
158 1.42 fvdl "NONE",
159 1.42 fvdl "aic7770",
160 1.42 fvdl "aic7850",
161 1.42 fvdl "aic7855",
162 1.42 fvdl "aic7859",
163 1.42 fvdl "aic7860",
164 1.42 fvdl "aic7870",
165 1.42 fvdl "aic7880",
166 1.42 fvdl "aic7890/91",
167 1.42 fvdl "aic7892",
168 1.42 fvdl "aic7895",
169 1.42 fvdl "aic7896/97",
170 1.42 fvdl "aic7899"
171 1.42 fvdl };
172 1.1 mycroft
173 1.42 fvdl typedef enum {
174 1.42 fvdl ROLE_UNKNOWN,
175 1.42 fvdl ROLE_INITIATOR,
176 1.42 fvdl ROLE_TARGET
177 1.42 fvdl } role_t;
178 1.42 fvdl
179 1.42 fvdl struct ahc_devinfo {
180 1.42 fvdl int our_scsiid;
181 1.42 fvdl int target_offset;
182 1.42 fvdl u_int16_t target_mask;
183 1.42 fvdl u_int8_t target;
184 1.42 fvdl u_int8_t lun;
185 1.42 fvdl char channel;
186 1.42 fvdl role_t role; /*
187 1.42 fvdl * Only guaranteed to be correct if not
188 1.42 fvdl * in the busfree state.
189 1.42 fvdl */
190 1.42 fvdl };
191 1.28 leo
192 1.42 fvdl typedef enum {
193 1.42 fvdl SEARCH_COMPLETE,
194 1.42 fvdl SEARCH_COUNT,
195 1.42 fvdl SEARCH_REMOVE
196 1.42 fvdl } ahc_search_action;
197 1.1 mycroft
198 1.6 mycroft #ifdef AHC_DEBUG
199 1.9 explorer static int ahc_debug = AHC_DEBUG;
200 1.6 mycroft #endif
201 1.1 mycroft
202 1.42 fvdl static int ahcinitscbdata(struct ahc_softc *);
203 1.42 fvdl static void ahcfiniscbdata(struct ahc_softc *);
204 1.1 mycroft
205 1.42 fvdl #if UNUSED
206 1.42 fvdl static void ahc_dump_targcmd(struct target_cmd *);
207 1.42 fvdl #endif
208 1.42 fvdl static void ahc_shutdown(void *arg);
209 1.42 fvdl static int32_t ahc_action(struct scsipi_xfer *);
210 1.52 fvdl static int ahc_ioctl(struct scsipi_link *, u_long, caddr_t, int,
211 1.52 fvdl struct proc *);
212 1.42 fvdl static int ahc_execute_scb(void *, bus_dma_segment_t *, int);
213 1.42 fvdl static int ahc_poll(struct ahc_softc *, int);
214 1.42 fvdl static int ahc_setup_data(struct ahc_softc *, struct scsipi_xfer *,
215 1.42 fvdl struct scb *);
216 1.42 fvdl static void ahc_freeze_devq(struct ahc_softc *, struct scsipi_link *);
217 1.42 fvdl static void ahcallocscbs(struct ahc_softc *);
218 1.42 fvdl #if UNUSED
219 1.42 fvdl static void ahc_scb_devinfo(struct ahc_softc *, struct ahc_devinfo *,
220 1.42 fvdl struct scb *);
221 1.42 fvdl #endif
222 1.42 fvdl static void ahc_fetch_devinfo(struct ahc_softc *, struct ahc_devinfo *);
223 1.42 fvdl static void ahc_compile_devinfo(struct ahc_devinfo *, u_int, u_int, u_int,
224 1.42 fvdl char, role_t);
225 1.42 fvdl static u_int ahc_abort_wscb(struct ahc_softc *, u_int, u_int);
226 1.42 fvdl static void ahc_done(struct ahc_softc *, struct scb *);
227 1.42 fvdl static struct tmode_tstate *
228 1.42 fvdl ahc_alloc_tstate(struct ahc_softc *, u_int, char);
229 1.42 fvdl #if UNUSED
230 1.42 fvdl static void ahc_free_tstate(struct ahc_softc *, u_int, char, int);
231 1.42 fvdl #endif
232 1.42 fvdl static void ahc_handle_seqint(struct ahc_softc *, u_int);
233 1.42 fvdl static void ahc_handle_scsiint(struct ahc_softc *, u_int);
234 1.42 fvdl static void ahc_build_transfer_msg(struct ahc_softc *,
235 1.42 fvdl struct ahc_devinfo *);
236 1.42 fvdl static void ahc_setup_initiator_msgout(struct ahc_softc *,
237 1.42 fvdl struct ahc_devinfo *,
238 1.42 fvdl struct scb *);
239 1.42 fvdl static void ahc_setup_target_msgin(struct ahc_softc *,
240 1.42 fvdl struct ahc_devinfo *);
241 1.42 fvdl static void ahc_clear_msg_state(struct ahc_softc *);
242 1.42 fvdl static void ahc_handle_message_phase(struct ahc_softc *,
243 1.42 fvdl struct scsipi_link *);
244 1.42 fvdl static int ahc_sent_msg(struct ahc_softc *, u_int, int);
245 1.42 fvdl
246 1.42 fvdl static int ahc_parse_msg(struct ahc_softc *, struct scsipi_link *,
247 1.42 fvdl struct ahc_devinfo *);
248 1.42 fvdl static void ahc_handle_ign_wide_residue(struct ahc_softc *,
249 1.42 fvdl struct ahc_devinfo *);
250 1.42 fvdl static void ahc_handle_devreset(struct ahc_softc *, struct ahc_devinfo *,
251 1.42 fvdl int, char *, int);
252 1.42 fvdl #ifdef AHC_DUMP_SEQ
253 1.42 fvdl static void ahc_dumpseq(struct ahc_softc *);
254 1.42 fvdl #endif
255 1.42 fvdl static void ahc_loadseq(struct ahc_softc *);
256 1.42 fvdl static int ahc_check_patch(struct ahc_softc *, struct patch **,
257 1.42 fvdl int, int *);
258 1.42 fvdl static void ahc_download_instr(struct ahc_softc *, int, u_int8_t *);
259 1.42 fvdl static int ahc_match_scb(struct scb *, int, char, int, u_int, role_t);
260 1.42 fvdl #if defined(AHC_DEBUG)
261 1.42 fvdl static void ahc_print_scb(struct scb *);
262 1.42 fvdl #endif
263 1.42 fvdl static int ahc_search_qinfifo(struct ahc_softc *, int, char, int, u_int,
264 1.42 fvdl role_t, scb_flag, ahc_search_action);
265 1.42 fvdl static int ahc_reset_channel(struct ahc_softc *, char, int);
266 1.42 fvdl static int ahc_abort_scbs(struct ahc_softc *, int, char, int, u_int,
267 1.42 fvdl role_t, int);
268 1.42 fvdl static int ahc_search_disc_list(struct ahc_softc *, int,
269 1.42 fvdl char, int, u_int, int, int, int);
270 1.42 fvdl static u_int ahc_rem_scb_from_disc_list(struct ahc_softc *, u_int, u_int);
271 1.42 fvdl static void ahc_add_curscb_to_free_list(struct ahc_softc *);
272 1.42 fvdl static void ahc_clear_intstat(struct ahc_softc *);
273 1.42 fvdl static void ahc_reset_current_bus(struct ahc_softc *);
274 1.42 fvdl static struct ahc_syncrate *
275 1.42 fvdl ahc_devlimited_syncrate(struct ahc_softc *, u_int *);
276 1.42 fvdl static struct ahc_syncrate *
277 1.42 fvdl ahc_find_syncrate(struct ahc_softc *, u_int *, u_int);
278 1.42 fvdl static u_int ahc_find_period(struct ahc_softc *, u_int, u_int);
279 1.42 fvdl static void ahc_validate_offset(struct ahc_softc *, struct ahc_syncrate *,
280 1.42 fvdl u_int *, int);
281 1.42 fvdl static void ahc_update_target_msg_request(struct ahc_softc *,
282 1.42 fvdl struct ahc_devinfo *,
283 1.42 fvdl struct ahc_initiator_tinfo *,
284 1.42 fvdl int, int);
285 1.42 fvdl static void ahc_set_syncrate(struct ahc_softc *, struct ahc_devinfo *,
286 1.42 fvdl struct ahc_syncrate *, u_int, u_int, u_int,
287 1.42 fvdl int, int);
288 1.42 fvdl static void ahc_set_width(struct ahc_softc *, struct ahc_devinfo *,
289 1.42 fvdl u_int, u_int, int, int);
290 1.42 fvdl static void ahc_set_tags(struct ahc_softc *, struct ahc_devinfo *,
291 1.42 fvdl int);
292 1.42 fvdl static void ahc_construct_sdtr(struct ahc_softc *, u_int, u_int);
293 1.42 fvdl
294 1.42 fvdl static void ahc_construct_wdtr(struct ahc_softc *, u_int);
295 1.42 fvdl
296 1.42 fvdl static void ahc_calc_residual(struct scb *);
297 1.42 fvdl
298 1.42 fvdl static void ahc_update_pending_syncrates(struct ahc_softc *);
299 1.42 fvdl
300 1.42 fvdl static void ahc_set_recoveryscb(struct ahc_softc *, struct scb *);
301 1.42 fvdl
302 1.42 fvdl static void ahc_timeout (void *);
303 1.42 fvdl static __inline int sequencer_paused(struct ahc_softc *);
304 1.42 fvdl static __inline void pause_sequencer(struct ahc_softc *);
305 1.42 fvdl static __inline void unpause_sequencer(struct ahc_softc *);
306 1.42 fvdl static void restart_sequencer(struct ahc_softc *);
307 1.42 fvdl static __inline u_int ahc_index_busy_tcl(struct ahc_softc *, u_int, int);
308 1.42 fvdl
309 1.42 fvdl static __inline void ahc_busy_tcl(struct ahc_softc *, struct scb *);
310 1.42 fvdl static __inline int ahc_isbusy_tcl(struct ahc_softc *, struct scb *);
311 1.42 fvdl
312 1.42 fvdl static __inline void ahc_freeze_ccb(struct scb *);
313 1.42 fvdl static __inline void ahcsetccbstatus(struct scsipi_xfer *, int);
314 1.42 fvdl static void ahc_run_qoutfifo(struct ahc_softc *);
315 1.42 fvdl
316 1.42 fvdl static __inline struct ahc_initiator_tinfo *
317 1.42 fvdl ahc_fetch_transinfo(struct ahc_softc *,
318 1.42 fvdl char, u_int, u_int,
319 1.42 fvdl struct tmode_tstate **);
320 1.42 fvdl static void ahcfreescb(struct ahc_softc *, struct scb *);
321 1.42 fvdl static __inline struct scb *ahcgetscb(struct ahc_softc *);
322 1.42 fvdl
323 1.42 fvdl static int ahc_createdmamem(bus_dma_tag_t, int, int, bus_dmamap_t *,
324 1.42 fvdl caddr_t *, bus_addr_t *, bus_dma_segment_t *,
325 1.42 fvdl int *, const char *, const char *);
326 1.42 fvdl static void ahc_freedmamem(bus_dma_tag_t, int, bus_dmamap_t,
327 1.42 fvdl caddr_t, bus_dma_segment_t *, int);
328 1.42 fvdl static void ahcminphys(struct buf *);
329 1.42 fvdl
330 1.42 fvdl static __inline struct scsipi_xfer *ahc_first_xs(struct ahc_softc *);
331 1.42 fvdl static __inline void ahc_swap_hscb(struct hardware_scb *);
332 1.42 fvdl static __inline void ahc_swap_sg(struct ahc_dma_seg *);
333 1.45 fvdl static void ahc_check_tags(struct ahc_softc *, struct scsipi_xfer *);
334 1.51 fvdl static int ahc_istagged_device(struct ahc_softc *, struct scsipi_xfer *, int);
335 1.1 mycroft
336 1.42 fvdl #if defined(AHC_DEBUG) && 0
337 1.42 fvdl static void ahc_dumptinfo(struct ahc_softc *, struct ahc_initiator_tinfo *);
338 1.6 mycroft #endif
339 1.1 mycroft
340 1.25 bouyer static struct scsipi_device ahc_dev =
341 1.6 mycroft {
342 1.6 mycroft NULL, /* Use default error handler */
343 1.6 mycroft NULL, /* have a queue, served by this */
344 1.6 mycroft NULL, /* have no async handler */
345 1.6 mycroft NULL, /* Use default 'done' routine */
346 1.6 mycroft };
347 1.1 mycroft
348 1.42 fvdl /*
349 1.42 fvdl * Pick the first xs for a non-blocked target.
350 1.42 fvdl */
351 1.42 fvdl static __inline struct scsipi_xfer *
352 1.42 fvdl ahc_first_xs(struct ahc_softc *ahc)
353 1.14 gibbs {
354 1.42 fvdl int target;
355 1.42 fvdl struct scsipi_xfer *xs = TAILQ_FIRST(&ahc->sc_q);
356 1.42 fvdl
357 1.42 fvdl if (ahc->queue_blocked)
358 1.42 fvdl return NULL;
359 1.42 fvdl
360 1.42 fvdl while (xs != NULL) {
361 1.42 fvdl target = xs->sc_link->scsipi_scsi.target;
362 1.42 fvdl if (ahc->devqueue_blocked[target] == 0 &&
363 1.55 fvdl (ahc_istagged_device(ahc, xs, 0) ||
364 1.45 fvdl ahc_index_busy_tcl(ahc, XS_TCL(ahc, xs), FALSE) ==
365 1.45 fvdl SCB_LIST_NULL))
366 1.42 fvdl break;
367 1.42 fvdl xs = TAILQ_NEXT(xs, adapter_q);
368 1.42 fvdl }
369 1.42 fvdl
370 1.42 fvdl return xs;
371 1.42 fvdl }
372 1.14 gibbs
373 1.42 fvdl static __inline void
374 1.42 fvdl ahc_swap_hscb(struct hardware_scb *hscb)
375 1.42 fvdl {
376 1.42 fvdl hscb->SG_pointer = htole32(hscb->SG_pointer);
377 1.42 fvdl hscb->data = htole32(hscb->data);
378 1.42 fvdl hscb->datalen = htole32(hscb->datalen);
379 1.14 gibbs /*
380 1.48 thorpej * No need to swap cmdpointer; it's either 0 or set to
381 1.42 fvdl * cmdstore_busaddr, which is already swapped.
382 1.14 gibbs */
383 1.14 gibbs }
384 1.1 mycroft
385 1.42 fvdl static __inline void
386 1.42 fvdl ahc_swap_sg(struct ahc_dma_seg *sg)
387 1.42 fvdl {
388 1.42 fvdl sg->addr = htole32(sg->addr);
389 1.42 fvdl sg->len = htole32(sg->len);
390 1.14 gibbs }
391 1.1 mycroft
392 1.42 fvdl static void
393 1.42 fvdl ahcminphys(bp)
394 1.42 fvdl struct buf *bp;
395 1.42 fvdl {
396 1.1 mycroft /*
397 1.42 fvdl * Even though the card can transfer up to 16megs per command
398 1.42 fvdl * we are limited by the number of segments in the dma segment
399 1.42 fvdl * list that we can hold. The worst case is that all pages are
400 1.42 fvdl * discontinuous physically, hense the "page per segment" limit
401 1.42 fvdl * enforced here.
402 1.1 mycroft */
403 1.42 fvdl if (bp->b_bcount > AHC_MAXTRANSFER_SIZE) {
404 1.42 fvdl bp->b_bcount = AHC_MAXTRANSFER_SIZE;
405 1.42 fvdl }
406 1.42 fvdl minphys(bp);
407 1.14 gibbs }
408 1.1 mycroft
409 1.1 mycroft
410 1.42 fvdl static __inline u_int32_t
411 1.42 fvdl ahc_hscb_busaddr(struct ahc_softc *ahc, u_int index)
412 1.42 fvdl {
413 1.42 fvdl return (ahc->scb_data->hscb_busaddr
414 1.42 fvdl + (sizeof(struct hardware_scb) * index));
415 1.6 mycroft }
416 1.1 mycroft
417 1.42 fvdl #define AHC_BUSRESET_DELAY 25 /* Reset delay in us */
418 1.1 mycroft
419 1.42 fvdl static __inline int
420 1.42 fvdl sequencer_paused(struct ahc_softc *ahc)
421 1.42 fvdl {
422 1.42 fvdl return ((ahc_inb(ahc, HCNTRL) & PAUSE) != 0);
423 1.1 mycroft }
424 1.1 mycroft
425 1.42 fvdl static __inline void
426 1.42 fvdl pause_sequencer(struct ahc_softc *ahc)
427 1.42 fvdl {
428 1.42 fvdl ahc_outb(ahc, HCNTRL, ahc->pause);
429 1.1 mycroft
430 1.42 fvdl /*
431 1.42 fvdl * Since the sequencer can disable pausing in a critical section, we
432 1.42 fvdl * must loop until it actually stops.
433 1.42 fvdl */
434 1.42 fvdl while (sequencer_paused(ahc) == 0)
435 1.42 fvdl ;
436 1.42 fvdl }
437 1.1 mycroft
438 1.42 fvdl static __inline void
439 1.42 fvdl unpause_sequencer(struct ahc_softc *ahc)
440 1.42 fvdl {
441 1.42 fvdl if ((ahc_inb(ahc, INTSTAT) & (SCSIINT | SEQINT | BRKADRINT)) == 0)
442 1.42 fvdl ahc_outb(ahc, HCNTRL, ahc->unpause);
443 1.42 fvdl }
444 1.1 mycroft
445 1.1 mycroft /*
446 1.42 fvdl * Restart the sequencer program from address zero
447 1.1 mycroft */
448 1.42 fvdl static void
449 1.42 fvdl restart_sequencer(struct ahc_softc *ahc)
450 1.42 fvdl {
451 1.42 fvdl u_int i;
452 1.1 mycroft
453 1.42 fvdl pause_sequencer(ahc);
454 1.1 mycroft
455 1.6 mycroft /*
456 1.42 fvdl * Everytime we restart the sequencer, there
457 1.42 fvdl * is the possiblitity that we have restarted
458 1.42 fvdl * within a three instruction window where an
459 1.42 fvdl * SCB has been marked free but has not made it
460 1.42 fvdl * onto the free list. Since SCSI events(bus reset,
461 1.42 fvdl * unexpected bus free) will always freeze the
462 1.42 fvdl * sequencer, we cannot close this window. To
463 1.42 fvdl * avoid losing an SCB, we reconsitute the free
464 1.42 fvdl * list every time we restart the sequencer.
465 1.6 mycroft */
466 1.42 fvdl ahc_outb(ahc, FREE_SCBH, SCB_LIST_NULL);
467 1.42 fvdl for (i = 0; i < ahc->scb_data->maxhscbs; i++) {
468 1.42 fvdl
469 1.42 fvdl ahc_outb(ahc, SCBPTR, i);
470 1.42 fvdl if (ahc_inb(ahc, SCB_TAG) == SCB_LIST_NULL)
471 1.42 fvdl ahc_add_curscb_to_free_list(ahc);
472 1.42 fvdl }
473 1.42 fvdl ahc_outb(ahc, SEQCTL, FASTMODE|SEQRESET);
474 1.42 fvdl unpause_sequencer(ahc);
475 1.42 fvdl }
476 1.1 mycroft
477 1.42 fvdl static __inline u_int
478 1.42 fvdl ahc_index_busy_tcl(struct ahc_softc *ahc, u_int tcl, int unbusy)
479 1.42 fvdl {
480 1.42 fvdl u_int scbid;
481 1.1 mycroft
482 1.42 fvdl scbid = ahc->untagged_scbs[tcl];
483 1.42 fvdl if (unbusy) {
484 1.42 fvdl ahc->untagged_scbs[tcl] = SCB_LIST_NULL;
485 1.42 fvdl bus_dmamap_sync(ahc->parent_dmat, ahc->shared_data_dmamap,
486 1.42 fvdl UNTAGGEDSCB_OFFSET * 256, 256, BUS_DMASYNC_PREWRITE);
487 1.6 mycroft }
488 1.6 mycroft
489 1.42 fvdl return (scbid);
490 1.6 mycroft }
491 1.1 mycroft
492 1.42 fvdl static __inline void
493 1.42 fvdl ahc_busy_tcl(struct ahc_softc *ahc, struct scb *scb)
494 1.6 mycroft {
495 1.42 fvdl ahc->untagged_scbs[scb->hscb->tcl] = scb->hscb->tag;
496 1.42 fvdl bus_dmamap_sync(ahc->parent_dmat, ahc->shared_data_dmamap,
497 1.42 fvdl UNTAGGEDSCB_OFFSET * 256, 256, BUS_DMASYNC_PREWRITE);
498 1.1 mycroft }
499 1.1 mycroft
500 1.42 fvdl static __inline int
501 1.42 fvdl ahc_isbusy_tcl(struct ahc_softc *ahc, struct scb *scb)
502 1.42 fvdl {
503 1.42 fvdl return ahc->untagged_scbs[scb->hscb->tcl] != SCB_LIST_NULL;
504 1.6 mycroft }
505 1.1 mycroft
506 1.42 fvdl static __inline void
507 1.42 fvdl ahc_freeze_ccb(struct scb *scb)
508 1.1 mycroft {
509 1.42 fvdl struct scsipi_xfer *xs = scb->xs;
510 1.42 fvdl struct ahc_softc *ahc = (struct ahc_softc *)xs->sc_link->adapter_softc;
511 1.42 fvdl int target;
512 1.1 mycroft
513 1.42 fvdl target = xs->sc_link->scsipi_scsi.target;
514 1.42 fvdl if (!(scb->flags & SCB_FREEZE_QUEUE)) {
515 1.42 fvdl ahc->devqueue_blocked[target]++;
516 1.42 fvdl scb->flags |= SCB_FREEZE_QUEUE;
517 1.14 gibbs }
518 1.1 mycroft }
519 1.1 mycroft
520 1.42 fvdl static __inline void
521 1.42 fvdl ahcsetccbstatus(struct scsipi_xfer *xs, int status)
522 1.1 mycroft {
523 1.42 fvdl xs->error = status;
524 1.42 fvdl }
525 1.1 mycroft
526 1.42 fvdl static __inline struct ahc_initiator_tinfo *
527 1.42 fvdl ahc_fetch_transinfo(struct ahc_softc *ahc, char channel, u_int our_id,
528 1.42 fvdl u_int remote_id, struct tmode_tstate **tstate)
529 1.42 fvdl {
530 1.18 thorpej /*
531 1.42 fvdl * Transfer data structures are stored from the perspective
532 1.42 fvdl * of the target role. Since the parameters for a connection
533 1.42 fvdl * in the initiator role to a given target are the same as
534 1.42 fvdl * when the roles are reversed, we pretend we are the target.
535 1.18 thorpej */
536 1.42 fvdl if (channel == 'B')
537 1.42 fvdl our_id += 8;
538 1.42 fvdl *tstate = ahc->enabled_targets[our_id];
539 1.42 fvdl return (&(*tstate)->transinfo[remote_id]);
540 1.42 fvdl }
541 1.18 thorpej
542 1.42 fvdl static void
543 1.42 fvdl ahc_run_qoutfifo(struct ahc_softc *ahc)
544 1.42 fvdl {
545 1.42 fvdl struct scb *scb;
546 1.42 fvdl u_int scb_index;
547 1.32 thorpej
548 1.42 fvdl bus_dmamap_sync(ahc->parent_dmat, ahc->shared_data_dmamap, 0,
549 1.42 fvdl 256, BUS_DMASYNC_POSTREAD);
550 1.32 thorpej
551 1.42 fvdl while (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL) {
552 1.42 fvdl scb_index = ahc->qoutfifo[ahc->qoutfifonext];
553 1.42 fvdl ahc->qoutfifo[ahc->qoutfifonext++] = SCB_LIST_NULL;
554 1.42 fvdl
555 1.42 fvdl scb = &ahc->scb_data->scbarray[scb_index];
556 1.42 fvdl if (scb_index >= ahc->scb_data->numscbs
557 1.42 fvdl || (scb->flags & SCB_ACTIVE) == 0) {
558 1.42 fvdl printf("%s: WARNING no command for scb %d "
559 1.42 fvdl "(cmdcmplt)\nQOUTPOS = %d\n",
560 1.42 fvdl ahc_name(ahc), scb_index,
561 1.42 fvdl ahc->qoutfifonext - 1);
562 1.42 fvdl continue;
563 1.42 fvdl }
564 1.6 mycroft
565 1.6 mycroft /*
566 1.42 fvdl * Save off the residual
567 1.42 fvdl * if there is one.
568 1.6 mycroft */
569 1.42 fvdl if (scb->hscb->residual_SG_count != 0)
570 1.42 fvdl ahc_calc_residual(scb);
571 1.42 fvdl else
572 1.42 fvdl scb->xs->resid = 0;
573 1.42 fvdl #ifdef AHC_DEBUG
574 1.42 fvdl if (ahc_debug & AHC_SHOWSCBS) {
575 1.42 fvdl scsi_print_addr(scb->xs->sc_link);
576 1.42 fvdl printf("run_qoutfifo: SCB %x complete\n",
577 1.42 fvdl scb->hscb->tag);
578 1.42 fvdl }
579 1.42 fvdl #endif
580 1.42 fvdl ahc_done(ahc, scb);
581 1.1 mycroft }
582 1.1 mycroft }
583 1.1 mycroft
584 1.42 fvdl
585 1.6 mycroft /*
586 1.42 fvdl * An scb (and hence an scb entry on the board) is put onto the
587 1.42 fvdl * free list.
588 1.6 mycroft */
589 1.42 fvdl static void
590 1.42 fvdl ahcfreescb(struct ahc_softc *ahc, struct scb *scb)
591 1.42 fvdl {
592 1.42 fvdl struct hardware_scb *hscb;
593 1.42 fvdl int opri;
594 1.42 fvdl
595 1.42 fvdl hscb = scb->hscb;
596 1.42 fvdl
597 1.42 fvdl #ifdef AHC_DEBUG
598 1.42 fvdl if (ahc_debug & AHC_SHOWSCBALLOC)
599 1.42 fvdl printf("%s: free SCB tag %x\n", ahc_name(ahc), hscb->tag);
600 1.29 leo #endif
601 1.28 leo
602 1.42 fvdl opri = splbio();
603 1.6 mycroft
604 1.42 fvdl if ((ahc->flags & AHC_RESOURCE_SHORTAGE) != 0 ||
605 1.42 fvdl (scb->flags & SCB_RECOVERY_SCB) != 0) {
606 1.42 fvdl ahc->flags &= ~AHC_RESOURCE_SHORTAGE;
607 1.42 fvdl ahc->queue_blocked = 0;
608 1.42 fvdl }
609 1.6 mycroft
610 1.42 fvdl /* Clean up for the next user */
611 1.42 fvdl scb->flags = SCB_FREE;
612 1.42 fvdl hscb->control = 0;
613 1.42 fvdl hscb->status = 0;
614 1.6 mycroft
615 1.42 fvdl SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, scb, links);
616 1.29 leo
617 1.42 fvdl splx(opri);
618 1.6 mycroft }
619 1.6 mycroft
620 1.6 mycroft /*
621 1.42 fvdl * Get a free scb, either one already assigned to a hardware slot
622 1.42 fvdl * on the adapter or one that will require an SCB to be paged out before
623 1.42 fvdl * use. If there are none, see if we can allocate a new SCB. Otherwise
624 1.42 fvdl * either return an error or sleep.
625 1.6 mycroft */
626 1.42 fvdl static __inline struct scb *
627 1.42 fvdl ahcgetscb(struct ahc_softc *ahc)
628 1.42 fvdl {
629 1.42 fvdl struct scb *scbp;
630 1.42 fvdl int opri;;
631 1.42 fvdl
632 1.42 fvdl opri = splbio();
633 1.42 fvdl if ((scbp = SLIST_FIRST(&ahc->scb_data->free_scbs))) {
634 1.42 fvdl SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links);
635 1.42 fvdl } else {
636 1.42 fvdl ahcallocscbs(ahc);
637 1.42 fvdl scbp = SLIST_FIRST(&ahc->scb_data->free_scbs);
638 1.42 fvdl if (scbp != NULL)
639 1.42 fvdl SLIST_REMOVE_HEAD(&ahc->scb_data->free_scbs, links);
640 1.42 fvdl }
641 1.42 fvdl
642 1.42 fvdl splx(opri);
643 1.42 fvdl
644 1.42 fvdl #ifdef AHC_DEBUG
645 1.42 fvdl if (ahc_debug & AHC_SHOWSCBALLOC) {
646 1.42 fvdl if (scbp != NULL)
647 1.42 fvdl printf("%s: new SCB, tag %x\n", ahc_name(ahc),
648 1.42 fvdl scbp->hscb->tag);
649 1.42 fvdl else
650 1.42 fvdl printf("%s: failed to allocate new SCB\n",
651 1.42 fvdl ahc_name(ahc));
652 1.42 fvdl }
653 1.42 fvdl #endif
654 1.42 fvdl
655 1.42 fvdl return (scbp);
656 1.42 fvdl }
657 1.42 fvdl
658 1.42 fvdl static int
659 1.42 fvdl ahc_createdmamem(tag, size, flags, mapp, vaddr, baddr, seg, nseg, myname, what)
660 1.42 fvdl bus_dma_tag_t tag;
661 1.42 fvdl int size;
662 1.42 fvdl int flags;
663 1.42 fvdl bus_dmamap_t *mapp;
664 1.42 fvdl caddr_t *vaddr;
665 1.42 fvdl bus_addr_t *baddr;
666 1.42 fvdl bus_dma_segment_t *seg;
667 1.42 fvdl int *nseg;
668 1.42 fvdl const char *myname, *what;
669 1.42 fvdl {
670 1.42 fvdl int error, level = 0;
671 1.42 fvdl
672 1.42 fvdl if ((error = bus_dmamem_alloc(tag, size, NBPG, 0,
673 1.42 fvdl seg, 1, nseg, BUS_DMA_NOWAIT)) != 0) {
674 1.42 fvdl printf("%s: failed to allocate DMA mem for %s, error = %d\n",
675 1.42 fvdl myname, what, error);
676 1.42 fvdl goto out;
677 1.42 fvdl }
678 1.42 fvdl level++;
679 1.42 fvdl
680 1.42 fvdl if ((error = bus_dmamem_map(tag, seg, *nseg, size, vaddr,
681 1.42 fvdl BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
682 1.42 fvdl printf("%s: failed to map DMA mem for %s, error = %d\n",
683 1.42 fvdl myname, what, error);
684 1.42 fvdl goto out;
685 1.42 fvdl }
686 1.42 fvdl level++;
687 1.42 fvdl
688 1.42 fvdl if ((error = bus_dmamap_create(tag, size, 1, size, 0,
689 1.42 fvdl BUS_DMA_NOWAIT | flags, mapp)) != 0) {
690 1.42 fvdl printf("%s: failed to create DMA map for %s, error = %d\n",
691 1.42 fvdl myname, what, error);
692 1.42 fvdl goto out;
693 1.42 fvdl }
694 1.42 fvdl level++;
695 1.42 fvdl
696 1.42 fvdl if ((error = bus_dmamap_load(tag, *mapp, *vaddr, size, NULL,
697 1.42 fvdl BUS_DMA_NOWAIT)) != 0) {
698 1.42 fvdl printf("%s: failed to load DMA map for %s, error = %d\n",
699 1.42 fvdl myname, what, error);
700 1.42 fvdl goto out;
701 1.42 fvdl }
702 1.42 fvdl
703 1.42 fvdl *baddr = (*mapp)->dm_segs[0].ds_addr;
704 1.42 fvdl
705 1.42 fvdl #ifdef AHC_DEBUG
706 1.42 fvdl printf("%s: dmamem for %s at busaddr %lx virt %lx nseg %d size %d\n",
707 1.42 fvdl myname, what, (unsigned long)*baddr, (unsigned long)*vaddr,
708 1.42 fvdl *nseg, size);
709 1.42 fvdl #endif
710 1.42 fvdl
711 1.42 fvdl return 0;
712 1.42 fvdl out:
713 1.42 fvdl switch (level) {
714 1.42 fvdl case 3:
715 1.42 fvdl bus_dmamap_destroy(tag, *mapp);
716 1.42 fvdl /* FALLTHROUGH */
717 1.42 fvdl case 2:
718 1.42 fvdl bus_dmamem_unmap(tag, *vaddr, size);
719 1.42 fvdl /* FALLTHROUGH */
720 1.42 fvdl case 1:
721 1.42 fvdl bus_dmamem_free(tag, seg, *nseg);
722 1.42 fvdl break;
723 1.42 fvdl default:
724 1.42 fvdl break;
725 1.42 fvdl }
726 1.42 fvdl
727 1.42 fvdl return error;
728 1.42 fvdl }
729 1.42 fvdl
730 1.42 fvdl static void
731 1.42 fvdl ahc_freedmamem(tag, size, map, vaddr, seg, nseg)
732 1.42 fvdl bus_dma_tag_t tag;
733 1.42 fvdl int size;
734 1.42 fvdl bus_dmamap_t map;
735 1.42 fvdl caddr_t vaddr;
736 1.42 fvdl bus_dma_segment_t *seg;
737 1.42 fvdl int nseg;
738 1.42 fvdl {
739 1.42 fvdl
740 1.42 fvdl bus_dmamap_unload(tag, map);
741 1.42 fvdl bus_dmamap_destroy(tag, map);
742 1.42 fvdl bus_dmamem_unmap(tag, vaddr, size);
743 1.42 fvdl bus_dmamem_free(tag, seg, nseg);
744 1.42 fvdl }
745 1.42 fvdl
746 1.42 fvdl char *
747 1.42 fvdl ahc_name(struct ahc_softc *ahc)
748 1.42 fvdl {
749 1.42 fvdl return (ahc->sc_dev.dv_xname);
750 1.42 fvdl }
751 1.42 fvdl
752 1.42 fvdl #ifdef AHC_DEBUG
753 1.42 fvdl static void
754 1.42 fvdl ahc_print_scb(struct scb *scb)
755 1.42 fvdl {
756 1.42 fvdl struct hardware_scb *hscb = scb->hscb;
757 1.42 fvdl
758 1.42 fvdl printf("scb:%p tag %x control:0x%x tcl:0x%x cmdlen:%d cmdpointer:0x%lx\n",
759 1.42 fvdl scb,
760 1.42 fvdl hscb->tag,
761 1.42 fvdl hscb->control,
762 1.42 fvdl hscb->tcl,
763 1.42 fvdl hscb->cmdlen,
764 1.42 fvdl (unsigned long)le32toh(hscb->cmdpointer));
765 1.42 fvdl printf(" datlen:%u data:0x%lx segs:0x%x segp:0x%lx\n",
766 1.42 fvdl le32toh(hscb->datalen),
767 1.42 fvdl (unsigned long)(le32toh(hscb->data)),
768 1.42 fvdl hscb->SG_count,
769 1.42 fvdl (unsigned long)(le32toh(hscb->SG_pointer)));
770 1.42 fvdl printf(" sg_addr:%lx sg_len:%lu\n",
771 1.42 fvdl (unsigned long)(le32toh(scb->sg_list[0].addr)),
772 1.50 soren (unsigned long)(le32toh(scb->sg_list[0].len)));
773 1.42 fvdl printf(" cdb:%x %x %x %x %x %x %x %x %x %x %x %x\n",
774 1.42 fvdl hscb->cmdstore[0], hscb->cmdstore[1], hscb->cmdstore[2],
775 1.42 fvdl hscb->cmdstore[3], hscb->cmdstore[4], hscb->cmdstore[5],
776 1.42 fvdl hscb->cmdstore[6], hscb->cmdstore[7], hscb->cmdstore[8],
777 1.42 fvdl hscb->cmdstore[9], hscb->cmdstore[10], hscb->cmdstore[11]);
778 1.42 fvdl }
779 1.42 fvdl #endif
780 1.42 fvdl
781 1.42 fvdl static struct {
782 1.42 fvdl u_int8_t errno;
783 1.42 fvdl char *errmesg;
784 1.42 fvdl } hard_error[] = {
785 1.42 fvdl { ILLHADDR, "Illegal Host Access" },
786 1.42 fvdl { ILLSADDR, "Illegal Sequencer Address referrenced" },
787 1.42 fvdl { ILLOPCODE, "Illegal Opcode in sequencer program" },
788 1.42 fvdl { SQPARERR, "Sequencer Parity Error" },
789 1.42 fvdl { DPARERR, "Data-path Parity Error" },
790 1.42 fvdl { MPARERR, "Scratch or SCB Memory Parity Error" },
791 1.42 fvdl { PCIERRSTAT, "PCI Error detected" },
792 1.42 fvdl { CIOPARERR, "CIOBUS Parity Error" },
793 1.42 fvdl };
794 1.42 fvdl static const int num_errors = sizeof(hard_error)/sizeof(hard_error[0]);
795 1.42 fvdl
796 1.42 fvdl static struct {
797 1.42 fvdl u_int8_t phase;
798 1.42 fvdl u_int8_t mesg_out; /* Message response to parity errors */
799 1.42 fvdl char *phasemsg;
800 1.42 fvdl } phase_table[] = {
801 1.42 fvdl { P_DATAOUT, MSG_NOOP, "in Data-out phase" },
802 1.42 fvdl { P_DATAIN, MSG_INITIATOR_DET_ERR, "in Data-in phase" },
803 1.42 fvdl { P_COMMAND, MSG_NOOP, "in Command phase" },
804 1.42 fvdl { P_MESGOUT, MSG_NOOP, "in Message-out phase" },
805 1.42 fvdl { P_STATUS, MSG_INITIATOR_DET_ERR, "in Status phase" },
806 1.42 fvdl { P_MESGIN, MSG_PARITY_ERROR, "in Message-in phase" },
807 1.42 fvdl { P_BUSFREE, MSG_NOOP, "while idle" },
808 1.42 fvdl { 0, MSG_NOOP, "in unknown phase" }
809 1.42 fvdl };
810 1.42 fvdl static const int num_phases = (sizeof(phase_table)/sizeof(phase_table[0])) - 1;
811 1.42 fvdl
812 1.42 fvdl /*
813 1.42 fvdl * Valid SCSIRATE values. (p. 3-17)
814 1.42 fvdl * Provides a mapping of tranfer periods in ns to the proper value to
815 1.42 fvdl * stick in the scsiscfr reg to use that transfer rate.
816 1.42 fvdl */
817 1.42 fvdl #define AHC_SYNCRATE_DT 0
818 1.42 fvdl #define AHC_SYNCRATE_ULTRA2 1
819 1.45 fvdl #define AHC_SYNCRATE_ULTRA 3
820 1.45 fvdl #define AHC_SYNCRATE_FAST 6
821 1.42 fvdl static struct ahc_syncrate ahc_syncrates[] = {
822 1.42 fvdl /* ultra2 fast/ultra period rate */
823 1.42 fvdl { 0x42, 0x000, 9, "80.0" },
824 1.42 fvdl { 0x03, 0x000, 10, "40.0" },
825 1.42 fvdl { 0x04, 0x000, 11, "33.0" },
826 1.42 fvdl { 0x05, 0x100, 12, "20.0" },
827 1.42 fvdl { 0x06, 0x110, 15, "16.0" },
828 1.42 fvdl { 0x07, 0x120, 18, "13.4" },
829 1.42 fvdl { 0x08, 0x000, 25, "10.0" },
830 1.42 fvdl { 0x19, 0x010, 31, "8.0" },
831 1.42 fvdl { 0x1a, 0x020, 37, "6.67" },
832 1.42 fvdl { 0x1b, 0x030, 43, "5.7" },
833 1.42 fvdl { 0x1c, 0x040, 50, "5.0" },
834 1.42 fvdl { 0x00, 0x050, 56, "4.4" },
835 1.42 fvdl { 0x00, 0x060, 62, "4.0" },
836 1.42 fvdl { 0x00, 0x070, 68, "3.6" },
837 1.42 fvdl { 0x00, 0x000, 0, NULL }
838 1.42 fvdl };
839 1.42 fvdl
840 1.42 fvdl /*
841 1.42 fvdl * Allocate a controller structure for a new device and initialize it.
842 1.42 fvdl */
843 1.42 fvdl int
844 1.42 fvdl ahc_alloc(struct ahc_softc *ahc, bus_space_handle_t sh, bus_space_tag_t st,
845 1.42 fvdl bus_dma_tag_t parent_dmat, ahc_chip chip, ahc_feature features,
846 1.42 fvdl ahc_flag flags)
847 1.42 fvdl {
848 1.42 fvdl struct scb_data *scb_data;
849 1.42 fvdl
850 1.42 fvdl scb_data = malloc(sizeof (struct scb_data), M_DEVBUF, M_NOWAIT);
851 1.42 fvdl if (scb_data == NULL) {
852 1.42 fvdl printf("%s: cannot malloc softc!\n", ahc_name(ahc));
853 1.42 fvdl return -1;
854 1.42 fvdl }
855 1.42 fvdl bzero(scb_data, sizeof (struct scb_data));
856 1.42 fvdl LIST_INIT(&ahc->pending_ccbs);
857 1.42 fvdl ahc->tag = st;
858 1.42 fvdl ahc->bsh = sh;
859 1.42 fvdl ahc->parent_dmat = parent_dmat;
860 1.42 fvdl ahc->chip = chip;
861 1.42 fvdl ahc->features = features;
862 1.42 fvdl ahc->flags = flags;
863 1.42 fvdl ahc->scb_data = scb_data;
864 1.42 fvdl
865 1.42 fvdl ahc->unpause = (ahc_inb(ahc, HCNTRL) & IRQMS) | INTEN;
866 1.42 fvdl /* The IRQMS bit is only valid on VL and EISA chips */
867 1.42 fvdl if ((ahc->chip & AHC_PCI) != 0)
868 1.42 fvdl ahc->unpause &= ~IRQMS;
869 1.42 fvdl ahc->pause = ahc->unpause | PAUSE;
870 1.42 fvdl return (0);
871 1.42 fvdl }
872 1.42 fvdl
873 1.42 fvdl void
874 1.42 fvdl ahc_free(ahc)
875 1.42 fvdl struct ahc_softc *ahc;
876 1.42 fvdl {
877 1.42 fvdl ahcfiniscbdata(ahc);
878 1.42 fvdl if (ahc->init_level != 0)
879 1.42 fvdl ahc_freedmamem(ahc->parent_dmat, ahc->shared_data_size,
880 1.42 fvdl ahc->shared_data_dmamap, ahc->qoutfifo,
881 1.42 fvdl &ahc->shared_data_seg, ahc->shared_data_nseg);
882 1.42 fvdl
883 1.42 fvdl if (ahc->scb_data != NULL)
884 1.42 fvdl free(ahc->scb_data, M_DEVBUF);
885 1.42 fvdl if (ahc->bus_data != NULL)
886 1.42 fvdl free(ahc->bus_data, M_DEVBUF);
887 1.42 fvdl return;
888 1.42 fvdl }
889 1.42 fvdl
890 1.42 fvdl static int
891 1.42 fvdl ahcinitscbdata(struct ahc_softc *ahc)
892 1.42 fvdl {
893 1.42 fvdl struct scb_data *scb_data;
894 1.42 fvdl int i;
895 1.42 fvdl
896 1.42 fvdl scb_data = ahc->scb_data;
897 1.42 fvdl SLIST_INIT(&scb_data->free_scbs);
898 1.42 fvdl SLIST_INIT(&scb_data->sg_maps);
899 1.42 fvdl
900 1.42 fvdl /* Allocate SCB resources */
901 1.42 fvdl scb_data->scbarray =
902 1.42 fvdl (struct scb *)malloc(sizeof(struct scb) * AHC_SCB_MAX,
903 1.42 fvdl M_DEVBUF, M_NOWAIT);
904 1.42 fvdl if (scb_data->scbarray == NULL)
905 1.42 fvdl return (ENOMEM);
906 1.42 fvdl bzero(scb_data->scbarray, sizeof(struct scb) * AHC_SCB_MAX);
907 1.42 fvdl
908 1.42 fvdl /* Determine the number of hardware SCBs and initialize them */
909 1.42 fvdl
910 1.42 fvdl scb_data->maxhscbs = ahc_probe_scbs(ahc);
911 1.42 fvdl /* SCB 0 heads the free list */
912 1.42 fvdl ahc_outb(ahc, FREE_SCBH, 0);
913 1.42 fvdl for (i = 0; i < ahc->scb_data->maxhscbs; i++) {
914 1.42 fvdl ahc_outb(ahc, SCBPTR, i);
915 1.42 fvdl
916 1.42 fvdl /* Clear the control byte. */
917 1.42 fvdl ahc_outb(ahc, SCB_CONTROL, 0);
918 1.42 fvdl
919 1.42 fvdl /* Set the next pointer */
920 1.42 fvdl ahc_outb(ahc, SCB_NEXT, i+1);
921 1.42 fvdl
922 1.42 fvdl /* Make the tag number invalid */
923 1.42 fvdl ahc_outb(ahc, SCB_TAG, SCB_LIST_NULL);
924 1.42 fvdl }
925 1.42 fvdl
926 1.42 fvdl /* Make sure that the last SCB terminates the free list */
927 1.42 fvdl ahc_outb(ahc, SCBPTR, i-1);
928 1.42 fvdl ahc_outb(ahc, SCB_NEXT, SCB_LIST_NULL);
929 1.42 fvdl
930 1.42 fvdl /* Ensure we clear the 0 SCB's control byte. */
931 1.42 fvdl ahc_outb(ahc, SCBPTR, 0);
932 1.42 fvdl ahc_outb(ahc, SCB_CONTROL, 0);
933 1.42 fvdl
934 1.42 fvdl scb_data->maxhscbs = i;
935 1.42 fvdl
936 1.42 fvdl if (ahc->scb_data->maxhscbs == 0)
937 1.42 fvdl panic("%s: No SCB space found", ahc_name(ahc));
938 1.42 fvdl
939 1.42 fvdl /*
940 1.42 fvdl * Create our DMA tags. These tags define the kinds of device
941 1.42 fvdl * accessable memory allocations and memory mappings we will
942 1.42 fvdl * need to perform during normal operation.
943 1.42 fvdl *
944 1.42 fvdl * Unless we need to further restrict the allocation, we rely
945 1.42 fvdl * on the restrictions of the parent dmat, hence the common
946 1.42 fvdl * use of MAXADDR and MAXSIZE.
947 1.42 fvdl */
948 1.42 fvdl
949 1.42 fvdl if (ahc_createdmamem(ahc->parent_dmat,
950 1.42 fvdl AHC_SCB_MAX * sizeof(struct hardware_scb), ahc->sc_dmaflags,
951 1.42 fvdl &scb_data->hscb_dmamap,
952 1.42 fvdl (caddr_t *)&scb_data->hscbs, &scb_data->hscb_busaddr,
953 1.42 fvdl &scb_data->hscb_seg, &scb_data->hscb_nseg, ahc_name(ahc),
954 1.42 fvdl "hardware SCB structures") < 0)
955 1.42 fvdl goto error_exit;
956 1.42 fvdl
957 1.42 fvdl scb_data->init_level++;
958 1.42 fvdl
959 1.42 fvdl if (ahc_createdmamem(ahc->parent_dmat,
960 1.42 fvdl AHC_SCB_MAX * sizeof(struct scsipi_sense_data), ahc->sc_dmaflags,
961 1.42 fvdl &scb_data->sense_dmamap, (caddr_t *)&scb_data->sense,
962 1.42 fvdl &scb_data->sense_busaddr, &scb_data->sense_seg,
963 1.42 fvdl &scb_data->sense_nseg, ahc_name(ahc), "sense buffers") < 0)
964 1.42 fvdl goto error_exit;
965 1.42 fvdl
966 1.42 fvdl scb_data->init_level++;
967 1.42 fvdl
968 1.42 fvdl /* Perform initial CCB allocation */
969 1.42 fvdl bzero(scb_data->hscbs, AHC_SCB_MAX * sizeof(struct hardware_scb));
970 1.42 fvdl ahcallocscbs(ahc);
971 1.42 fvdl
972 1.42 fvdl if (scb_data->numscbs == 0) {
973 1.42 fvdl printf("%s: ahc_init_scb_data - "
974 1.42 fvdl "Unable to allocate initial scbs\n",
975 1.42 fvdl ahc_name(ahc));
976 1.42 fvdl goto error_exit;
977 1.42 fvdl }
978 1.42 fvdl
979 1.42 fvdl scb_data->init_level++;
980 1.42 fvdl
981 1.42 fvdl /*
982 1.42 fvdl * Note that we were successfull
983 1.42 fvdl */
984 1.42 fvdl return 0;
985 1.42 fvdl
986 1.42 fvdl error_exit:
987 1.42 fvdl
988 1.42 fvdl return ENOMEM;
989 1.42 fvdl }
990 1.42 fvdl
991 1.42 fvdl static void
992 1.42 fvdl ahcfiniscbdata(struct ahc_softc *ahc)
993 1.42 fvdl {
994 1.42 fvdl struct scb_data *scb_data;
995 1.42 fvdl
996 1.42 fvdl scb_data = ahc->scb_data;
997 1.42 fvdl
998 1.42 fvdl switch (scb_data->init_level) {
999 1.42 fvdl default:
1000 1.42 fvdl case 3:
1001 1.42 fvdl {
1002 1.42 fvdl struct sg_map_node *sg_map;
1003 1.42 fvdl
1004 1.42 fvdl while ((sg_map = SLIST_FIRST(&scb_data->sg_maps))!= NULL) {
1005 1.42 fvdl SLIST_REMOVE_HEAD(&scb_data->sg_maps, links);
1006 1.42 fvdl ahc_freedmamem(ahc->parent_dmat, PAGE_SIZE,
1007 1.42 fvdl sg_map->sg_dmamap, (caddr_t)sg_map->sg_vaddr,
1008 1.42 fvdl &sg_map->sg_dmasegs, sg_map->sg_nseg);
1009 1.42 fvdl free(sg_map, M_DEVBUF);
1010 1.42 fvdl }
1011 1.42 fvdl }
1012 1.42 fvdl /*FALLTHROUGH*/
1013 1.42 fvdl case 2:
1014 1.42 fvdl ahc_freedmamem(ahc->parent_dmat,
1015 1.42 fvdl AHC_SCB_MAX * sizeof(struct scsipi_sense_data),
1016 1.42 fvdl scb_data->sense_dmamap, (caddr_t)scb_data->sense,
1017 1.42 fvdl &scb_data->sense_seg, scb_data->sense_nseg);
1018 1.42 fvdl /*FALLTHROUGH*/
1019 1.42 fvdl case 1:
1020 1.42 fvdl ahc_freedmamem(ahc->parent_dmat,
1021 1.42 fvdl AHC_SCB_MAX * sizeof(struct hardware_scb),
1022 1.42 fvdl scb_data->hscb_dmamap, (caddr_t)scb_data->hscbs,
1023 1.42 fvdl &scb_data->hscb_seg, scb_data->hscb_nseg);
1024 1.42 fvdl /*FALLTHROUGH*/
1025 1.42 fvdl }
1026 1.42 fvdl if (scb_data->scbarray != NULL)
1027 1.42 fvdl free(scb_data->scbarray, M_DEVBUF);
1028 1.42 fvdl }
1029 1.42 fvdl
1030 1.42 fvdl int
1031 1.42 fvdl ahc_reset(struct ahc_softc *ahc)
1032 1.42 fvdl {
1033 1.42 fvdl u_int sblkctl;
1034 1.42 fvdl int wait;
1035 1.42 fvdl
1036 1.42 fvdl #ifdef AHC_DUMP_SEQ
1037 1.42 fvdl if (ahc->init_level == 0)
1038 1.42 fvdl ahc_dumpseq(ahc);
1039 1.42 fvdl #endif
1040 1.42 fvdl ahc_outb(ahc, HCNTRL, CHIPRST | ahc->pause);
1041 1.42 fvdl /*
1042 1.42 fvdl * Ensure that the reset has finished
1043 1.42 fvdl */
1044 1.42 fvdl wait = 1000;
1045 1.42 fvdl do {
1046 1.42 fvdl DELAY(1000);
1047 1.42 fvdl } while (--wait && !(ahc_inb(ahc, HCNTRL) & CHIPRSTACK));
1048 1.42 fvdl
1049 1.42 fvdl if (wait == 0) {
1050 1.42 fvdl printf("%s: WARNING - Failed chip reset! "
1051 1.42 fvdl "Trying to initialize anyway.\n", ahc_name(ahc));
1052 1.42 fvdl }
1053 1.42 fvdl ahc_outb(ahc, HCNTRL, ahc->pause);
1054 1.42 fvdl
1055 1.42 fvdl /* Determine channel configuration */
1056 1.42 fvdl sblkctl = ahc_inb(ahc, SBLKCTL) & (SELBUSB|SELWIDE);
1057 1.42 fvdl /* No Twin Channel PCI cards */
1058 1.42 fvdl if ((ahc->chip & AHC_PCI) != 0)
1059 1.42 fvdl sblkctl &= ~SELBUSB;
1060 1.42 fvdl switch (sblkctl) {
1061 1.42 fvdl case 0:
1062 1.42 fvdl /* Single Narrow Channel */
1063 1.42 fvdl break;
1064 1.42 fvdl case 2:
1065 1.42 fvdl /* Wide Channel */
1066 1.42 fvdl ahc->features |= AHC_WIDE;
1067 1.42 fvdl break;
1068 1.42 fvdl case 8:
1069 1.42 fvdl /* Twin Channel */
1070 1.42 fvdl ahc->features |= AHC_TWIN;
1071 1.42 fvdl break;
1072 1.42 fvdl default:
1073 1.42 fvdl printf(" Unsupported adapter type. Ignoring\n");
1074 1.42 fvdl return(-1);
1075 1.42 fvdl }
1076 1.42 fvdl
1077 1.42 fvdl return (0);
1078 1.42 fvdl }
1079 1.42 fvdl
1080 1.42 fvdl /*
1081 1.42 fvdl * Called when we have an active connection to a target on the bus,
1082 1.42 fvdl * this function finds the nearest syncrate to the input period limited
1083 1.42 fvdl * by the capabilities of the bus connectivity of the target.
1084 1.42 fvdl */
1085 1.42 fvdl static struct ahc_syncrate *
1086 1.42 fvdl ahc_devlimited_syncrate(struct ahc_softc *ahc, u_int *period) {
1087 1.42 fvdl u_int maxsync;
1088 1.42 fvdl
1089 1.42 fvdl if ((ahc->features & AHC_ULTRA2) != 0) {
1090 1.42 fvdl if ((ahc_inb(ahc, SBLKCTL) & ENAB40) != 0
1091 1.42 fvdl && (ahc_inb(ahc, SSTAT2) & EXP_ACTIVE) == 0) {
1092 1.42 fvdl maxsync = AHC_SYNCRATE_ULTRA2;
1093 1.42 fvdl } else {
1094 1.42 fvdl maxsync = AHC_SYNCRATE_ULTRA;
1095 1.42 fvdl }
1096 1.42 fvdl } else if ((ahc->features & AHC_ULTRA) != 0) {
1097 1.42 fvdl maxsync = AHC_SYNCRATE_ULTRA;
1098 1.42 fvdl } else {
1099 1.42 fvdl maxsync = AHC_SYNCRATE_FAST;
1100 1.42 fvdl }
1101 1.42 fvdl return (ahc_find_syncrate(ahc, period, maxsync));
1102 1.42 fvdl }
1103 1.42 fvdl
1104 1.42 fvdl /*
1105 1.42 fvdl * Look up the valid period to SCSIRATE conversion in our table.
1106 1.42 fvdl * Return the period and offset that should be sent to the target
1107 1.42 fvdl * if this was the beginning of an SDTR.
1108 1.42 fvdl */
1109 1.42 fvdl static struct ahc_syncrate *
1110 1.42 fvdl ahc_find_syncrate(struct ahc_softc *ahc, u_int *period, u_int maxsync)
1111 1.42 fvdl {
1112 1.42 fvdl struct ahc_syncrate *syncrate;
1113 1.42 fvdl
1114 1.42 fvdl syncrate = &ahc_syncrates[maxsync];
1115 1.42 fvdl while ((syncrate->rate != NULL)
1116 1.42 fvdl && ((ahc->features & AHC_ULTRA2) == 0
1117 1.42 fvdl || (syncrate->sxfr_u2 != 0))) {
1118 1.42 fvdl
1119 1.42 fvdl if (*period <= syncrate->period) {
1120 1.42 fvdl /*
1121 1.42 fvdl * When responding to a target that requests
1122 1.42 fvdl * sync, the requested rate may fall between
1123 1.42 fvdl * two rates that we can output, but still be
1124 1.42 fvdl * a rate that we can receive. Because of this,
1125 1.42 fvdl * we want to respond to the target with
1126 1.42 fvdl * the same rate that it sent to us even
1127 1.42 fvdl * if the period we use to send data to it
1128 1.42 fvdl * is lower. Only lower the response period
1129 1.42 fvdl * if we must.
1130 1.42 fvdl */
1131 1.42 fvdl if (syncrate == &ahc_syncrates[maxsync])
1132 1.42 fvdl *period = syncrate->period;
1133 1.42 fvdl break;
1134 1.42 fvdl }
1135 1.42 fvdl syncrate++;
1136 1.42 fvdl }
1137 1.42 fvdl
1138 1.42 fvdl if ((*period == 0)
1139 1.42 fvdl || (syncrate->rate == NULL)
1140 1.42 fvdl || ((ahc->features & AHC_ULTRA2) != 0
1141 1.42 fvdl && (syncrate->sxfr_u2 == 0))) {
1142 1.42 fvdl /* Use asynchronous transfers. */
1143 1.42 fvdl *period = 0;
1144 1.42 fvdl syncrate = NULL;
1145 1.42 fvdl }
1146 1.42 fvdl return (syncrate);
1147 1.42 fvdl }
1148 1.42 fvdl
1149 1.42 fvdl static u_int
1150 1.42 fvdl ahc_find_period(struct ahc_softc *ahc, u_int scsirate, u_int maxsync)
1151 1.42 fvdl {
1152 1.42 fvdl struct ahc_syncrate *syncrate;
1153 1.42 fvdl
1154 1.42 fvdl if ((ahc->features & AHC_ULTRA2) != 0)
1155 1.42 fvdl scsirate &= SXFR_ULTRA2;
1156 1.42 fvdl else
1157 1.42 fvdl scsirate &= SXFR;
1158 1.42 fvdl
1159 1.42 fvdl syncrate = &ahc_syncrates[maxsync];
1160 1.42 fvdl while (syncrate->rate != NULL) {
1161 1.42 fvdl
1162 1.42 fvdl if ((ahc->features & AHC_ULTRA2) != 0) {
1163 1.42 fvdl if (syncrate->sxfr_u2 == 0)
1164 1.42 fvdl break;
1165 1.42 fvdl else if (scsirate == (syncrate->sxfr_u2 & SXFR_ULTRA2))
1166 1.42 fvdl return (syncrate->period);
1167 1.42 fvdl } else if (scsirate == (syncrate->sxfr & SXFR)) {
1168 1.42 fvdl return (syncrate->period);
1169 1.42 fvdl }
1170 1.42 fvdl syncrate++;
1171 1.42 fvdl }
1172 1.42 fvdl return (0); /* async */
1173 1.42 fvdl }
1174 1.42 fvdl
1175 1.42 fvdl static void
1176 1.42 fvdl ahc_validate_offset(struct ahc_softc *ahc, struct ahc_syncrate *syncrate,
1177 1.42 fvdl u_int *offset, int wide)
1178 1.42 fvdl {
1179 1.42 fvdl u_int maxoffset;
1180 1.42 fvdl
1181 1.42 fvdl /* Limit offset to what we can do */
1182 1.42 fvdl if (syncrate == NULL) {
1183 1.42 fvdl maxoffset = 0;
1184 1.42 fvdl } else if ((ahc->features & AHC_ULTRA2) != 0) {
1185 1.42 fvdl maxoffset = MAX_OFFSET_ULTRA2;
1186 1.42 fvdl } else {
1187 1.42 fvdl if (wide)
1188 1.42 fvdl maxoffset = MAX_OFFSET_16BIT;
1189 1.42 fvdl else
1190 1.42 fvdl maxoffset = MAX_OFFSET_8BIT;
1191 1.42 fvdl }
1192 1.42 fvdl *offset = MIN(*offset, maxoffset);
1193 1.42 fvdl }
1194 1.42 fvdl
1195 1.42 fvdl static void
1196 1.42 fvdl ahc_update_target_msg_request(struct ahc_softc *ahc,
1197 1.42 fvdl struct ahc_devinfo *devinfo,
1198 1.42 fvdl struct ahc_initiator_tinfo *tinfo,
1199 1.42 fvdl int force, int paused)
1200 1.42 fvdl {
1201 1.42 fvdl u_int targ_msg_req_orig;
1202 1.42 fvdl
1203 1.42 fvdl targ_msg_req_orig = ahc->targ_msg_req;
1204 1.42 fvdl if (tinfo->current.period != tinfo->goal.period
1205 1.42 fvdl || tinfo->current.width != tinfo->goal.width
1206 1.42 fvdl || tinfo->current.offset != tinfo->goal.offset
1207 1.42 fvdl || (force
1208 1.42 fvdl && (tinfo->goal.period != 0
1209 1.42 fvdl || tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT))) {
1210 1.42 fvdl ahc->targ_msg_req |= devinfo->target_mask;
1211 1.42 fvdl } else {
1212 1.42 fvdl ahc->targ_msg_req &= ~devinfo->target_mask;
1213 1.42 fvdl }
1214 1.42 fvdl
1215 1.42 fvdl if (ahc->targ_msg_req != targ_msg_req_orig) {
1216 1.42 fvdl /* Update the message request bit for this target */
1217 1.42 fvdl if ((ahc->features & AHC_HS_MAILBOX) != 0) {
1218 1.42 fvdl if (paused) {
1219 1.42 fvdl ahc_outb(ahc, TARGET_MSG_REQUEST,
1220 1.42 fvdl ahc->targ_msg_req & 0xFF);
1221 1.42 fvdl ahc_outb(ahc, TARGET_MSG_REQUEST + 1,
1222 1.42 fvdl (ahc->targ_msg_req >> 8) & 0xFF);
1223 1.42 fvdl } else {
1224 1.42 fvdl ahc_outb(ahc, HS_MAILBOX,
1225 1.42 fvdl 0x01 << HOST_MAILBOX_SHIFT);
1226 1.42 fvdl }
1227 1.42 fvdl } else {
1228 1.42 fvdl if (!paused)
1229 1.42 fvdl pause_sequencer(ahc);
1230 1.42 fvdl
1231 1.42 fvdl ahc_outb(ahc, TARGET_MSG_REQUEST,
1232 1.42 fvdl ahc->targ_msg_req & 0xFF);
1233 1.42 fvdl ahc_outb(ahc, TARGET_MSG_REQUEST + 1,
1234 1.42 fvdl (ahc->targ_msg_req >> 8) & 0xFF);
1235 1.42 fvdl
1236 1.42 fvdl if (!paused)
1237 1.42 fvdl unpause_sequencer(ahc);
1238 1.42 fvdl }
1239 1.42 fvdl }
1240 1.42 fvdl }
1241 1.42 fvdl
1242 1.42 fvdl static void
1243 1.42 fvdl ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
1244 1.42 fvdl struct ahc_syncrate *syncrate,
1245 1.42 fvdl u_int period, u_int offset, u_int type, int paused, int done)
1246 1.42 fvdl {
1247 1.42 fvdl struct ahc_initiator_tinfo *tinfo;
1248 1.42 fvdl struct tmode_tstate *tstate;
1249 1.42 fvdl u_int old_period;
1250 1.42 fvdl u_int old_offset;
1251 1.42 fvdl int active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE;
1252 1.42 fvdl
1253 1.42 fvdl if (syncrate == NULL) {
1254 1.42 fvdl period = 0;
1255 1.42 fvdl offset = 0;
1256 1.42 fvdl }
1257 1.42 fvdl
1258 1.42 fvdl tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
1259 1.42 fvdl devinfo->target, &tstate);
1260 1.42 fvdl old_period = tinfo->current.period;
1261 1.42 fvdl old_offset = tinfo->current.offset;
1262 1.42 fvdl
1263 1.42 fvdl if ((type & AHC_TRANS_CUR) != 0
1264 1.42 fvdl && (old_period != period || old_offset != offset)) {
1265 1.42 fvdl u_int scsirate;
1266 1.42 fvdl
1267 1.42 fvdl scsirate = tinfo->scsirate;
1268 1.42 fvdl if ((ahc->features & AHC_ULTRA2) != 0) {
1269 1.42 fvdl
1270 1.42 fvdl /* XXX */
1271 1.42 fvdl /* Force single edge until DT is fully implemented */
1272 1.42 fvdl scsirate &= ~(SXFR_ULTRA2|SINGLE_EDGE|ENABLE_CRC);
1273 1.42 fvdl if (syncrate != NULL)
1274 1.42 fvdl scsirate |= syncrate->sxfr_u2|SINGLE_EDGE;
1275 1.42 fvdl
1276 1.42 fvdl if (active)
1277 1.42 fvdl ahc_outb(ahc, SCSIOFFSET, offset);
1278 1.42 fvdl } else {
1279 1.42 fvdl
1280 1.42 fvdl scsirate &= ~(SXFR|SOFS);
1281 1.42 fvdl /*
1282 1.42 fvdl * Ensure Ultra mode is set properly for
1283 1.42 fvdl * this target.
1284 1.42 fvdl */
1285 1.42 fvdl tstate->ultraenb &= ~devinfo->target_mask;
1286 1.42 fvdl if (syncrate != NULL) {
1287 1.42 fvdl if (syncrate->sxfr & ULTRA_SXFR) {
1288 1.42 fvdl tstate->ultraenb |=
1289 1.42 fvdl devinfo->target_mask;
1290 1.42 fvdl }
1291 1.42 fvdl scsirate |= syncrate->sxfr & SXFR;
1292 1.42 fvdl scsirate |= offset & SOFS;
1293 1.42 fvdl }
1294 1.42 fvdl if (active) {
1295 1.42 fvdl u_int sxfrctl0;
1296 1.42 fvdl
1297 1.42 fvdl sxfrctl0 = ahc_inb(ahc, SXFRCTL0);
1298 1.42 fvdl sxfrctl0 &= ~FAST20;
1299 1.42 fvdl if (tstate->ultraenb & devinfo->target_mask)
1300 1.42 fvdl sxfrctl0 |= FAST20;
1301 1.42 fvdl ahc_outb(ahc, SXFRCTL0, sxfrctl0);
1302 1.42 fvdl }
1303 1.42 fvdl }
1304 1.42 fvdl if (active)
1305 1.42 fvdl ahc_outb(ahc, SCSIRATE, scsirate);
1306 1.42 fvdl
1307 1.42 fvdl tinfo->scsirate = scsirate;
1308 1.42 fvdl tinfo->current.period = period;
1309 1.42 fvdl tinfo->current.offset = offset;
1310 1.42 fvdl
1311 1.42 fvdl /* Update the syncrates in any pending scbs */
1312 1.42 fvdl ahc_update_pending_syncrates(ahc);
1313 1.42 fvdl }
1314 1.42 fvdl
1315 1.42 fvdl /*
1316 1.42 fvdl * Print messages if we're verbose and at the end of a negotiation
1317 1.42 fvdl * cycle.
1318 1.42 fvdl */
1319 1.42 fvdl if (done) {
1320 1.42 fvdl if (offset != 0) {
1321 1.42 fvdl printf("%s: target %d synchronous at %sMHz, "
1322 1.42 fvdl "offset = 0x%x\n", ahc_name(ahc),
1323 1.42 fvdl devinfo->target, syncrate->rate, offset);
1324 1.42 fvdl } else {
1325 1.42 fvdl printf("%s: target %d using "
1326 1.42 fvdl "asynchronous transfers\n",
1327 1.42 fvdl ahc_name(ahc), devinfo->target);
1328 1.42 fvdl }
1329 1.42 fvdl }
1330 1.42 fvdl
1331 1.42 fvdl if ((type & AHC_TRANS_GOAL) != 0) {
1332 1.42 fvdl tinfo->goal.period = period;
1333 1.42 fvdl tinfo->goal.offset = offset;
1334 1.42 fvdl }
1335 1.42 fvdl
1336 1.42 fvdl if ((type & AHC_TRANS_USER) != 0) {
1337 1.42 fvdl tinfo->user.period = period;
1338 1.42 fvdl tinfo->user.offset = offset;
1339 1.42 fvdl }
1340 1.42 fvdl
1341 1.42 fvdl ahc_update_target_msg_request(ahc, devinfo, tinfo,
1342 1.42 fvdl /*force*/FALSE,
1343 1.42 fvdl paused);
1344 1.42 fvdl }
1345 1.42 fvdl
1346 1.42 fvdl static void
1347 1.42 fvdl ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
1348 1.42 fvdl u_int width, u_int type, int paused, int done)
1349 1.42 fvdl {
1350 1.42 fvdl struct ahc_initiator_tinfo *tinfo;
1351 1.42 fvdl struct tmode_tstate *tstate;
1352 1.42 fvdl u_int oldwidth;
1353 1.42 fvdl int active = (type & AHC_TRANS_ACTIVE) == AHC_TRANS_ACTIVE;
1354 1.42 fvdl
1355 1.42 fvdl tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
1356 1.42 fvdl devinfo->target, &tstate);
1357 1.42 fvdl oldwidth = tinfo->current.width;
1358 1.42 fvdl
1359 1.42 fvdl if ((type & AHC_TRANS_CUR) != 0 && oldwidth != width) {
1360 1.42 fvdl u_int scsirate;
1361 1.42 fvdl
1362 1.42 fvdl scsirate = tinfo->scsirate;
1363 1.42 fvdl scsirate &= ~WIDEXFER;
1364 1.42 fvdl if (width == MSG_EXT_WDTR_BUS_16_BIT)
1365 1.42 fvdl scsirate |= WIDEXFER;
1366 1.42 fvdl
1367 1.42 fvdl tinfo->scsirate = scsirate;
1368 1.42 fvdl
1369 1.42 fvdl if (active)
1370 1.42 fvdl ahc_outb(ahc, SCSIRATE, scsirate);
1371 1.42 fvdl
1372 1.42 fvdl tinfo->current.width = width;
1373 1.42 fvdl }
1374 1.42 fvdl
1375 1.42 fvdl if (done) {
1376 1.42 fvdl printf("%s: target %d using %dbit transfers\n",
1377 1.42 fvdl ahc_name(ahc), devinfo->target,
1378 1.42 fvdl 8 * (0x01 << width));
1379 1.42 fvdl }
1380 1.42 fvdl
1381 1.42 fvdl if ((type & AHC_TRANS_GOAL) != 0)
1382 1.42 fvdl tinfo->goal.width = width;
1383 1.42 fvdl if ((type & AHC_TRANS_USER) != 0)
1384 1.42 fvdl tinfo->user.width = width;
1385 1.42 fvdl
1386 1.42 fvdl ahc_update_target_msg_request(ahc, devinfo, tinfo,
1387 1.42 fvdl /*force*/FALSE, paused);
1388 1.42 fvdl }
1389 1.42 fvdl
1390 1.42 fvdl static void
1391 1.42 fvdl ahc_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, int enable)
1392 1.42 fvdl {
1393 1.42 fvdl struct ahc_initiator_tinfo *tinfo;
1394 1.42 fvdl struct tmode_tstate *tstate;
1395 1.42 fvdl
1396 1.42 fvdl tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
1397 1.42 fvdl devinfo->target, &tstate);
1398 1.42 fvdl
1399 1.42 fvdl if (enable)
1400 1.42 fvdl tstate->tagenable |= devinfo->target_mask;
1401 1.49 fvdl else {
1402 1.42 fvdl tstate->tagenable &= ~devinfo->target_mask;
1403 1.49 fvdl tstate->tagdisable |= devinfo->target_mask;
1404 1.49 fvdl }
1405 1.42 fvdl }
1406 1.42 fvdl
1407 1.42 fvdl /*
1408 1.42 fvdl * Attach all the sub-devices we can find
1409 1.42 fvdl */
1410 1.42 fvdl int
1411 1.42 fvdl ahc_attach(struct ahc_softc *ahc)
1412 1.42 fvdl {
1413 1.42 fvdl TAILQ_INIT(&ahc->sc_q);
1414 1.42 fvdl
1415 1.42 fvdl ahc->sc_adapter.scsipi_cmd = ahc_action;
1416 1.42 fvdl ahc->sc_adapter.scsipi_minphys = ahcminphys;
1417 1.52 fvdl ahc->sc_adapter.scsipi_ioctl = ahc_ioctl;
1418 1.42 fvdl ahc->sc_link.type = BUS_SCSI;
1419 1.42 fvdl ahc->sc_link.scsipi_scsi.adapter_target = ahc->our_id;
1420 1.42 fvdl ahc->sc_link.scsipi_scsi.channel = 0;
1421 1.42 fvdl ahc->sc_link.scsipi_scsi.max_target =
1422 1.42 fvdl (ahc->features & AHC_WIDE) ? 15 : 7;
1423 1.42 fvdl ahc->sc_link.scsipi_scsi.max_lun = 7;
1424 1.42 fvdl ahc->sc_link.adapter_softc = ahc;
1425 1.42 fvdl ahc->sc_link.adapter = &ahc->sc_adapter;
1426 1.42 fvdl ahc->sc_link.openings = 2;
1427 1.42 fvdl ahc->sc_link.device = &ahc_dev;
1428 1.42 fvdl
1429 1.42 fvdl if (ahc->features & AHC_TWIN) {
1430 1.42 fvdl ahc->sc_link_b = ahc->sc_link;
1431 1.42 fvdl ahc->sc_link_b.scsipi_scsi.adapter_target = ahc->our_id_b;
1432 1.42 fvdl ahc->sc_link_b.scsipi_scsi.channel = 1;
1433 1.42 fvdl }
1434 1.42 fvdl
1435 1.42 fvdl if ((ahc->flags & AHC_CHANNEL_B_PRIMARY) == 0) {
1436 1.42 fvdl ahc->sc_link_b.scsipi_scsi.scsibus = 0xff;
1437 1.42 fvdl config_found((void *)ahc, &ahc->sc_link, scsiprint);
1438 1.42 fvdl if (ahc->features & AHC_TWIN)
1439 1.42 fvdl config_found((void *)ahc, &ahc->sc_link_b, scsiprint);
1440 1.42 fvdl } else {
1441 1.42 fvdl config_found((void *)ahc, &ahc->sc_link_b, scsiprint);
1442 1.42 fvdl config_found((void *)ahc, &ahc->sc_link, scsiprint);
1443 1.42 fvdl }
1444 1.42 fvdl return 1;
1445 1.42 fvdl }
1446 1.42 fvdl
1447 1.42 fvdl static void
1448 1.42 fvdl ahc_fetch_devinfo(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
1449 1.42 fvdl {
1450 1.42 fvdl u_int saved_tcl;
1451 1.42 fvdl role_t role;
1452 1.42 fvdl int our_id;
1453 1.42 fvdl
1454 1.42 fvdl if (ahc_inb(ahc, SSTAT0) & TARGET)
1455 1.42 fvdl role = ROLE_TARGET;
1456 1.42 fvdl else
1457 1.42 fvdl role = ROLE_INITIATOR;
1458 1.42 fvdl
1459 1.42 fvdl if (role == ROLE_TARGET
1460 1.42 fvdl && (ahc->features & AHC_MULTI_TID) != 0
1461 1.42 fvdl && (ahc_inb(ahc, SEQ_FLAGS) & CMDPHASE_PENDING) != 0) {
1462 1.42 fvdl /* We were selected, so pull our id from TARGIDIN */
1463 1.42 fvdl our_id = ahc_inb(ahc, TARGIDIN) & OID;
1464 1.42 fvdl } else if ((ahc->features & AHC_ULTRA2) != 0)
1465 1.42 fvdl our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID;
1466 1.42 fvdl else
1467 1.42 fvdl our_id = ahc_inb(ahc, SCSIID) & OID;
1468 1.42 fvdl
1469 1.42 fvdl saved_tcl = ahc_inb(ahc, SAVED_TCL);
1470 1.42 fvdl ahc_compile_devinfo(devinfo, our_id, TCL_TARGET(saved_tcl),
1471 1.42 fvdl TCL_LUN(saved_tcl), TCL_CHANNEL(ahc, saved_tcl),
1472 1.42 fvdl role);
1473 1.42 fvdl }
1474 1.42 fvdl
1475 1.42 fvdl static void
1476 1.42 fvdl ahc_compile_devinfo(struct ahc_devinfo *devinfo, u_int our_id, u_int target,
1477 1.42 fvdl u_int lun, char channel, role_t role)
1478 1.42 fvdl {
1479 1.42 fvdl devinfo->our_scsiid = our_id;
1480 1.42 fvdl devinfo->target = target;
1481 1.42 fvdl devinfo->lun = lun;
1482 1.42 fvdl devinfo->target_offset = target;
1483 1.42 fvdl devinfo->channel = channel;
1484 1.42 fvdl devinfo->role = role;
1485 1.42 fvdl if (channel == 'B')
1486 1.42 fvdl devinfo->target_offset += 8;
1487 1.42 fvdl devinfo->target_mask = (0x01 << devinfo->target_offset);
1488 1.42 fvdl }
1489 1.42 fvdl
1490 1.42 fvdl /*
1491 1.42 fvdl * Catch an interrupt from the adapter
1492 1.42 fvdl */
1493 1.42 fvdl int
1494 1.42 fvdl ahc_intr(void *arg)
1495 1.42 fvdl {
1496 1.42 fvdl struct ahc_softc *ahc;
1497 1.42 fvdl u_int intstat;
1498 1.42 fvdl
1499 1.42 fvdl ahc = (struct ahc_softc *)arg;
1500 1.42 fvdl
1501 1.42 fvdl intstat = ahc_inb(ahc, INTSTAT);
1502 1.42 fvdl
1503 1.42 fvdl /*
1504 1.42 fvdl * Any interrupts to process?
1505 1.42 fvdl */
1506 1.42 fvdl if ((intstat & INT_PEND) == 0) {
1507 1.43 fvdl if (ahc->bus_intr && ahc->bus_intr(ahc)) {
1508 1.43 fvdl #ifdef AHC_DEBUG
1509 1.43 fvdl printf("%s: bus intr: CCHADDR %x HADDR %x SEQADDR %x\n",
1510 1.42 fvdl ahc_name(ahc),
1511 1.42 fvdl ahc_inb(ahc, CCHADDR) |
1512 1.42 fvdl (ahc_inb(ahc, CCHADDR+1) << 8)
1513 1.42 fvdl | (ahc_inb(ahc, CCHADDR+2) << 16)
1514 1.42 fvdl | (ahc_inb(ahc, CCHADDR+3) << 24),
1515 1.42 fvdl ahc_inb(ahc, HADDR) | (ahc_inb(ahc, HADDR+1) << 8)
1516 1.42 fvdl | (ahc_inb(ahc, HADDR+2) << 16)
1517 1.42 fvdl | (ahc_inb(ahc, HADDR+3) << 24),
1518 1.42 fvdl ahc_inb(ahc, SEQADDR0) |
1519 1.42 fvdl (ahc_inb(ahc, SEQADDR1) << 8));
1520 1.42 fvdl #endif
1521 1.42 fvdl return 1;
1522 1.42 fvdl }
1523 1.42 fvdl return 0;
1524 1.42 fvdl }
1525 1.42 fvdl
1526 1.42 fvdl #ifdef AHC_DEBUG
1527 1.42 fvdl if (ahc_debug & AHC_SHOWINTR) {
1528 1.42 fvdl printf("%s: intstat %x\n", ahc_name(ahc), intstat);
1529 1.42 fvdl }
1530 1.42 fvdl #endif
1531 1.42 fvdl
1532 1.42 fvdl if (intstat & CMDCMPLT) {
1533 1.42 fvdl ahc_outb(ahc, CLRINT, CLRCMDINT);
1534 1.42 fvdl ahc_run_qoutfifo(ahc);
1535 1.42 fvdl }
1536 1.42 fvdl if (intstat & BRKADRINT) {
1537 1.42 fvdl /*
1538 1.42 fvdl * We upset the sequencer :-(
1539 1.42 fvdl * Lookup the error message
1540 1.42 fvdl */
1541 1.42 fvdl int i, error, num_errors;
1542 1.42 fvdl
1543 1.42 fvdl error = ahc_inb(ahc, ERROR);
1544 1.42 fvdl num_errors = sizeof(hard_error)/sizeof(hard_error[0]);
1545 1.42 fvdl for (i = 0; error != 1 && i < num_errors; i++)
1546 1.42 fvdl error >>= 1;
1547 1.42 fvdl panic("%s: brkadrint, %s at seqaddr = 0x%x\n",
1548 1.42 fvdl ahc_name(ahc), hard_error[i].errmesg,
1549 1.42 fvdl ahc_inb(ahc, SEQADDR0) |
1550 1.42 fvdl (ahc_inb(ahc, SEQADDR1) << 8));
1551 1.42 fvdl
1552 1.42 fvdl /* Tell everyone that this HBA is no longer availible */
1553 1.42 fvdl ahc_abort_scbs(ahc, AHC_TARGET_WILDCARD, ALL_CHANNELS,
1554 1.42 fvdl AHC_LUN_WILDCARD, SCB_LIST_NULL, ROLE_UNKNOWN,
1555 1.42 fvdl XS_DRIVER_STUFFUP);
1556 1.42 fvdl }
1557 1.42 fvdl if (intstat & SEQINT)
1558 1.42 fvdl ahc_handle_seqint(ahc, intstat);
1559 1.42 fvdl
1560 1.42 fvdl if (intstat & SCSIINT)
1561 1.42 fvdl ahc_handle_scsiint(ahc, intstat);
1562 1.42 fvdl
1563 1.42 fvdl return 1;
1564 1.42 fvdl }
1565 1.42 fvdl
1566 1.42 fvdl static struct tmode_tstate *
1567 1.42 fvdl ahc_alloc_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel)
1568 1.42 fvdl {
1569 1.42 fvdl struct tmode_tstate *master_tstate;
1570 1.42 fvdl struct tmode_tstate *tstate;
1571 1.42 fvdl int i, s;
1572 1.42 fvdl
1573 1.42 fvdl master_tstate = ahc->enabled_targets[ahc->our_id];
1574 1.42 fvdl if (channel == 'B') {
1575 1.42 fvdl scsi_id += 8;
1576 1.42 fvdl master_tstate = ahc->enabled_targets[ahc->our_id_b + 8];
1577 1.42 fvdl }
1578 1.42 fvdl if (ahc->enabled_targets[scsi_id] != NULL
1579 1.42 fvdl && ahc->enabled_targets[scsi_id] != master_tstate)
1580 1.42 fvdl panic("%s: ahc_alloc_tstate - Target already allocated",
1581 1.42 fvdl ahc_name(ahc));
1582 1.42 fvdl tstate = malloc(sizeof(*tstate), M_DEVBUF, M_NOWAIT);
1583 1.42 fvdl if (tstate == NULL)
1584 1.42 fvdl return (NULL);
1585 1.42 fvdl
1586 1.42 fvdl /*
1587 1.42 fvdl * If we have allocated a master tstate, copy user settings from
1588 1.42 fvdl * the master tstate (taken from SRAM or the EEPROM) for this
1589 1.42 fvdl * channel, but reset our current and goal settings to async/narrow
1590 1.42 fvdl * until an initiator talks to us.
1591 1.42 fvdl */
1592 1.42 fvdl if (master_tstate != NULL) {
1593 1.42 fvdl bcopy(master_tstate, tstate, sizeof(*tstate));
1594 1.42 fvdl tstate->ultraenb = 0;
1595 1.42 fvdl for (i = 0; i < 16; i++) {
1596 1.42 fvdl bzero(&tstate->transinfo[i].current,
1597 1.42 fvdl sizeof(tstate->transinfo[i].current));
1598 1.42 fvdl bzero(&tstate->transinfo[i].goal,
1599 1.42 fvdl sizeof(tstate->transinfo[i].goal));
1600 1.42 fvdl }
1601 1.42 fvdl } else
1602 1.42 fvdl bzero(tstate, sizeof(*tstate));
1603 1.42 fvdl s = splbio();
1604 1.42 fvdl ahc->enabled_targets[scsi_id] = tstate;
1605 1.42 fvdl splx(s);
1606 1.42 fvdl return (tstate);
1607 1.42 fvdl }
1608 1.42 fvdl
1609 1.42 fvdl #if UNUSED
1610 1.42 fvdl static void
1611 1.42 fvdl ahc_free_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel, int force)
1612 1.42 fvdl {
1613 1.42 fvdl struct tmode_tstate *tstate;
1614 1.42 fvdl
1615 1.42 fvdl /* Don't clean up the entry for our initiator role */
1616 1.42 fvdl if ((ahc->flags & AHC_INITIATORMODE) != 0
1617 1.42 fvdl && ((channel == 'B' && scsi_id == ahc->our_id_b)
1618 1.42 fvdl || (channel == 'A' && scsi_id == ahc->our_id))
1619 1.42 fvdl && force == FALSE)
1620 1.42 fvdl return;
1621 1.42 fvdl
1622 1.42 fvdl if (channel == 'B')
1623 1.42 fvdl scsi_id += 8;
1624 1.42 fvdl tstate = ahc->enabled_targets[scsi_id];
1625 1.42 fvdl if (tstate != NULL)
1626 1.42 fvdl free(tstate, M_DEVBUF);
1627 1.42 fvdl ahc->enabled_targets[scsi_id] = NULL;
1628 1.42 fvdl }
1629 1.42 fvdl #endif
1630 1.42 fvdl
1631 1.42 fvdl static void
1632 1.42 fvdl ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
1633 1.42 fvdl {
1634 1.42 fvdl struct scb *scb;
1635 1.42 fvdl struct ahc_devinfo devinfo;
1636 1.42 fvdl
1637 1.42 fvdl ahc_fetch_devinfo(ahc, &devinfo);
1638 1.42 fvdl
1639 1.42 fvdl /*
1640 1.42 fvdl * Clear the upper byte that holds SEQINT status
1641 1.42 fvdl * codes and clear the SEQINT bit. We will unpause
1642 1.42 fvdl * the sequencer, if appropriate, after servicing
1643 1.42 fvdl * the request.
1644 1.42 fvdl */
1645 1.42 fvdl ahc_outb(ahc, CLRINT, CLRSEQINT);
1646 1.42 fvdl switch (intstat & SEQINT_MASK) {
1647 1.42 fvdl case NO_MATCH:
1648 1.42 fvdl {
1649 1.42 fvdl /* Ensure we don't leave the selection hardware on */
1650 1.42 fvdl ahc_outb(ahc, SCSISEQ,
1651 1.42 fvdl ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP));
1652 1.42 fvdl
1653 1.42 fvdl printf("%s:%c:%d: no active SCB for reconnecting "
1654 1.42 fvdl "target - issuing BUS DEVICE RESET\n",
1655 1.42 fvdl ahc_name(ahc), devinfo.channel, devinfo.target);
1656 1.42 fvdl printf("SAVED_TCL == 0x%x, ARG_1 == 0x%x, SEQ_FLAGS == 0x%x\n",
1657 1.42 fvdl ahc_inb(ahc, SAVED_TCL), ahc_inb(ahc, ARG_1),
1658 1.42 fvdl ahc_inb(ahc, SEQ_FLAGS));
1659 1.42 fvdl ahc->msgout_buf[0] = MSG_BUS_DEV_RESET;
1660 1.42 fvdl ahc->msgout_len = 1;
1661 1.42 fvdl ahc->msgout_index = 0;
1662 1.42 fvdl ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
1663 1.42 fvdl ahc_outb(ahc, MSG_OUT, HOST_MSG);
1664 1.42 fvdl ahc_outb(ahc, SCSISIGO, ahc_inb(ahc, LASTPHASE) | ATNO);
1665 1.42 fvdl break;
1666 1.42 fvdl }
1667 1.42 fvdl case UPDATE_TMSG_REQ:
1668 1.42 fvdl ahc_outb(ahc, TARGET_MSG_REQUEST, ahc->targ_msg_req & 0xFF);
1669 1.42 fvdl ahc_outb(ahc, TARGET_MSG_REQUEST + 1,
1670 1.42 fvdl (ahc->targ_msg_req >> 8) & 0xFF);
1671 1.42 fvdl ahc_outb(ahc, HS_MAILBOX, 0);
1672 1.42 fvdl break;
1673 1.42 fvdl case SEND_REJECT:
1674 1.42 fvdl {
1675 1.42 fvdl u_int rejbyte = ahc_inb(ahc, ACCUM);
1676 1.42 fvdl printf("%s:%c:%d: Warning - unknown message received from "
1677 1.42 fvdl "target (0x%x). Rejecting\n",
1678 1.42 fvdl ahc_name(ahc), devinfo.channel, devinfo.target, rejbyte);
1679 1.42 fvdl break;
1680 1.42 fvdl }
1681 1.42 fvdl case NO_IDENT:
1682 1.42 fvdl {
1683 1.42 fvdl /*
1684 1.42 fvdl * The reconnecting target either did not send an identify
1685 1.42 fvdl * message, or did, but we didn't find and SCB to match and
1686 1.42 fvdl * before it could respond to our ATN/abort, it hit a dataphase.
1687 1.42 fvdl * The only safe thing to do is to blow it away with a bus
1688 1.42 fvdl * reset.
1689 1.42 fvdl */
1690 1.42 fvdl int found;
1691 1.42 fvdl
1692 1.42 fvdl printf("%s:%c:%d: Target did not send an IDENTIFY message. "
1693 1.42 fvdl "LASTPHASE = 0x%x, SAVED_TCL == 0x%x\n",
1694 1.42 fvdl ahc_name(ahc), devinfo.channel, devinfo.target,
1695 1.42 fvdl ahc_inb(ahc, LASTPHASE), ahc_inb(ahc, SAVED_TCL));
1696 1.42 fvdl found = ahc_reset_channel(ahc, devinfo.channel,
1697 1.42 fvdl /*initiate reset*/TRUE);
1698 1.42 fvdl printf("%s: Issued Channel %c Bus Reset. "
1699 1.42 fvdl "%d SCBs aborted\n", ahc_name(ahc), devinfo.channel,
1700 1.42 fvdl found);
1701 1.42 fvdl return;
1702 1.42 fvdl }
1703 1.42 fvdl case BAD_PHASE:
1704 1.42 fvdl {
1705 1.42 fvdl u_int lastphase;
1706 1.42 fvdl
1707 1.42 fvdl lastphase = ahc_inb(ahc, LASTPHASE);
1708 1.42 fvdl if (lastphase == P_BUSFREE) {
1709 1.42 fvdl printf("%s:%c:%d: Missed busfree. Curphase = 0x%x\n",
1710 1.42 fvdl ahc_name(ahc), devinfo.channel, devinfo.target,
1711 1.42 fvdl ahc_inb(ahc, SCSISIGI));
1712 1.42 fvdl restart_sequencer(ahc);
1713 1.42 fvdl return;
1714 1.42 fvdl } else {
1715 1.42 fvdl printf("%s:%c:%d: unknown scsi bus phase %x. "
1716 1.42 fvdl "Attempting to continue\n",
1717 1.42 fvdl ahc_name(ahc), devinfo.channel, devinfo.target,
1718 1.42 fvdl ahc_inb(ahc, SCSISIGI));
1719 1.42 fvdl }
1720 1.42 fvdl break;
1721 1.42 fvdl }
1722 1.42 fvdl case BAD_STATUS:
1723 1.42 fvdl {
1724 1.42 fvdl u_int scb_index;
1725 1.42 fvdl struct hardware_scb *hscb;
1726 1.42 fvdl struct scsipi_xfer *xs;
1727 1.55 fvdl struct scb *scbp;
1728 1.55 fvdl int todo, inqueue;
1729 1.42 fvdl /*
1730 1.42 fvdl * The sequencer will notify us when a command
1731 1.42 fvdl * has an error that would be of interest to
1732 1.42 fvdl * the kernel. This allows us to leave the sequencer
1733 1.42 fvdl * running in the common case of command completes
1734 1.42 fvdl * without error. The sequencer will already have
1735 1.42 fvdl * dma'd the SCB back up to us, so we can reference
1736 1.42 fvdl * the in kernel copy directly.
1737 1.42 fvdl */
1738 1.42 fvdl scb_index = ahc_inb(ahc, SCB_TAG);
1739 1.42 fvdl scb = &ahc->scb_data->scbarray[scb_index];
1740 1.42 fvdl
1741 1.42 fvdl /* ahc_print_scb(scb); */
1742 1.42 fvdl
1743 1.42 fvdl /*
1744 1.42 fvdl * Set the default return value to 0 (don't
1745 1.42 fvdl * send sense). The sense code will change
1746 1.42 fvdl * this if needed.
1747 1.42 fvdl */
1748 1.42 fvdl ahc_outb(ahc, RETURN_1, 0);
1749 1.42 fvdl if (!(scb_index < ahc->scb_data->numscbs
1750 1.42 fvdl && (scb->flags & SCB_ACTIVE) != 0)) {
1751 1.42 fvdl printf("%s:%c:%d: ahc_intr - referenced scb "
1752 1.42 fvdl "not valid during seqint 0x%x scb(%d)\n",
1753 1.42 fvdl ahc_name(ahc), devinfo.channel,
1754 1.42 fvdl devinfo.target, intstat, scb_index);
1755 1.42 fvdl goto unpause;
1756 1.42 fvdl }
1757 1.42 fvdl
1758 1.42 fvdl hscb = scb->hscb;
1759 1.42 fvdl xs = scb->xs;
1760 1.42 fvdl
1761 1.42 fvdl /* Don't want to clobber the original sense code */
1762 1.42 fvdl if ((scb->flags & SCB_SENSE) != 0) {
1763 1.42 fvdl /*
1764 1.42 fvdl * Clear the SCB_SENSE Flag and have
1765 1.42 fvdl * the sequencer do a normal command
1766 1.42 fvdl * complete.
1767 1.42 fvdl */
1768 1.42 fvdl scb->flags &= ~SCB_SENSE;
1769 1.42 fvdl ahcsetccbstatus(xs, XS_DRIVER_STUFFUP);
1770 1.42 fvdl break;
1771 1.42 fvdl }
1772 1.42 fvdl /* Freeze the queue unit the client sees the error. */
1773 1.42 fvdl ahc_freeze_devq(ahc, xs->sc_link);
1774 1.42 fvdl ahc_freeze_ccb(scb);
1775 1.42 fvdl xs->status = hscb->status;
1776 1.42 fvdl switch (hscb->status) {
1777 1.42 fvdl case SCSI_STATUS_OK:
1778 1.42 fvdl printf("%s: Interrupted for status of 0???\n",
1779 1.42 fvdl ahc_name(ahc));
1780 1.42 fvdl break;
1781 1.42 fvdl case SCSI_STATUS_CMD_TERMINATED:
1782 1.42 fvdl case SCSI_STATUS_CHECK_COND:
1783 1.42 fvdl #if defined(AHC_DEBUG)
1784 1.42 fvdl if (ahc_debug & AHC_SHOWSENSE) {
1785 1.42 fvdl scsi_print_addr(xs->sc_link);
1786 1.42 fvdl printf("Check Status, resid %d datalen %d\n",
1787 1.42 fvdl xs->resid, xs->datalen);
1788 1.42 fvdl }
1789 1.42 fvdl #endif
1790 1.42 fvdl
1791 1.42 fvdl if (xs->error == XS_NOERROR &&
1792 1.42 fvdl !(scb->flags & SCB_SENSE)) {
1793 1.42 fvdl struct ahc_dma_seg *sg;
1794 1.42 fvdl struct scsipi_sense *sc;
1795 1.42 fvdl struct ahc_initiator_tinfo *tinfo;
1796 1.42 fvdl struct tmode_tstate *tstate;
1797 1.42 fvdl
1798 1.42 fvdl sg = scb->sg_list;
1799 1.42 fvdl sc = (struct scsipi_sense *)(&hscb->cmdstore);
1800 1.42 fvdl /*
1801 1.42 fvdl * Save off the residual if there is one.
1802 1.42 fvdl */
1803 1.42 fvdl if (hscb->residual_SG_count != 0)
1804 1.42 fvdl ahc_calc_residual(scb);
1805 1.42 fvdl else
1806 1.42 fvdl xs->resid = 0;
1807 1.42 fvdl
1808 1.42 fvdl #ifdef AHC_DEBUG
1809 1.42 fvdl if (ahc_debug & AHC_SHOWSENSE) {
1810 1.42 fvdl scsi_print_addr(xs->sc_link);
1811 1.42 fvdl printf("Sending Sense\n");
1812 1.42 fvdl }
1813 1.42 fvdl #endif
1814 1.42 fvdl sg->addr = ahc->scb_data->sense_busaddr +
1815 1.42 fvdl (hscb->tag*sizeof(struct scsipi_sense_data));
1816 1.42 fvdl sg->len = sizeof (struct scsipi_sense_data);
1817 1.42 fvdl
1818 1.42 fvdl sc->opcode = REQUEST_SENSE;
1819 1.42 fvdl sc->byte2 = SCB_LUN(scb) << 5;
1820 1.42 fvdl sc->unused[0] = 0;
1821 1.42 fvdl sc->unused[1] = 0;
1822 1.42 fvdl sc->length = sg->len;
1823 1.42 fvdl sc->control = 0;
1824 1.42 fvdl
1825 1.42 fvdl /*
1826 1.42 fvdl * Would be nice to preserve DISCENB here,
1827 1.42 fvdl * but due to the way we page SCBs, we can't.
1828 1.42 fvdl */
1829 1.42 fvdl hscb->control = 0;
1830 1.42 fvdl
1831 1.42 fvdl /*
1832 1.42 fvdl * This request sense could be because the
1833 1.42 fvdl * the device lost power or in some other
1834 1.42 fvdl * way has lost our transfer negotiations.
1835 1.42 fvdl * Renegotiate if appropriate. Unit attention
1836 1.42 fvdl * errors will be reported before any data
1837 1.42 fvdl * phases occur.
1838 1.42 fvdl */
1839 1.42 fvdl ahc_calc_residual(scb);
1840 1.42 fvdl #if defined(AHC_DEBUG)
1841 1.42 fvdl if (ahc_debug & AHC_SHOWSENSE) {
1842 1.42 fvdl scsi_print_addr(xs->sc_link);
1843 1.42 fvdl printf("Sense: datalen %d resid %d"
1844 1.42 fvdl "chan %d id %d targ %d\n",
1845 1.42 fvdl xs->datalen, xs->resid,
1846 1.42 fvdl devinfo.channel, devinfo.our_scsiid,
1847 1.42 fvdl devinfo.target);
1848 1.42 fvdl }
1849 1.42 fvdl #endif
1850 1.42 fvdl if (xs->datalen > 0 &&
1851 1.42 fvdl xs->resid == xs->datalen) {
1852 1.42 fvdl tinfo = ahc_fetch_transinfo(ahc,
1853 1.42 fvdl devinfo.channel,
1854 1.42 fvdl devinfo.our_scsiid,
1855 1.42 fvdl devinfo.target,
1856 1.42 fvdl &tstate);
1857 1.42 fvdl ahc_update_target_msg_request(ahc,
1858 1.42 fvdl &devinfo,
1859 1.42 fvdl tinfo,
1860 1.42 fvdl /*force*/TRUE,
1861 1.42 fvdl /*paused*/TRUE);
1862 1.42 fvdl }
1863 1.42 fvdl hscb->status = 0;
1864 1.42 fvdl hscb->SG_count = 1;
1865 1.42 fvdl hscb->SG_pointer = scb->sg_list_phys;
1866 1.42 fvdl hscb->data = sg->addr;
1867 1.42 fvdl hscb->datalen = sg->len;
1868 1.42 fvdl hscb->cmdpointer = hscb->cmdstore_busaddr;
1869 1.42 fvdl hscb->cmdlen = sizeof(*sc);
1870 1.42 fvdl scb->sg_count = hscb->SG_count;
1871 1.42 fvdl ahc_swap_hscb(hscb);
1872 1.42 fvdl ahc_swap_sg(scb->sg_list);
1873 1.42 fvdl scb->flags |= SCB_SENSE;
1874 1.42 fvdl /*
1875 1.42 fvdl * Ensure the target is busy since this
1876 1.42 fvdl * will be an untagged request.
1877 1.42 fvdl */
1878 1.42 fvdl ahc_busy_tcl(ahc, scb);
1879 1.42 fvdl ahc_outb(ahc, RETURN_1, SEND_SENSE);
1880 1.42 fvdl
1881 1.42 fvdl /*
1882 1.42 fvdl * Ensure we have enough time to actually
1883 1.42 fvdl * retrieve the sense.
1884 1.42 fvdl */
1885 1.42 fvdl if (!(scb->xs->xs_control & XS_CTL_POLL)) {
1886 1.44 thorpej callout_reset(&scb->xs->xs_callout,
1887 1.44 thorpej 5 * hz, ahc_timeout, scb);
1888 1.42 fvdl }
1889 1.42 fvdl }
1890 1.42 fvdl break;
1891 1.49 fvdl case SCSI_STATUS_QUEUE_FULL:
1892 1.49 fvdl scsi_print_addr(xs->sc_link);
1893 1.49 fvdl printf("queue full\n");
1894 1.42 fvdl case SCSI_STATUS_BUSY:
1895 1.42 fvdl /*
1896 1.53 fvdl * XXX middle layer doesn't handle XS_BUSY well.
1897 1.55 fvdl * So, requeue this ourselves internally. It will
1898 1.55 fvdl * get its turn once all outstanding (tagged)
1899 1.55 fvdl * commands have finished.
1900 1.42 fvdl */
1901 1.53 fvdl xs->error = XS_BUSY;
1902 1.55 fvdl xs->xs_status |= XS_STS_DEBUG;
1903 1.53 fvdl scb->flags |= SCB_REQUEUE;
1904 1.55 fvdl
1905 1.55 fvdl /*
1906 1.55 fvdl * Walk through all pending SCBs for this target,
1907 1.55 fvdl * incrementing the freeze count for the queue.
1908 1.55 fvdl * When all of these have been completed, the
1909 1.55 fvdl * queue will be available again.
1910 1.55 fvdl */
1911 1.55 fvdl inqueue = todo = 0;
1912 1.55 fvdl scbp = ahc->pending_ccbs.lh_first;
1913 1.55 fvdl while (scbp != NULL) {
1914 1.55 fvdl inqueue++;
1915 1.55 fvdl if (ahc_match_scb(scbp, SCB_TARGET(scb),
1916 1.55 fvdl SCB_CHANNEL(scb), SCB_LUN(scb),
1917 1.55 fvdl SCB_LIST_NULL, ROLE_INITIATOR)) {
1918 1.55 fvdl ahc_freeze_ccb(scbp);
1919 1.55 fvdl todo++;
1920 1.55 fvdl }
1921 1.55 fvdl scbp = scbp->plinks.le_next;
1922 1.55 fvdl }
1923 1.55 fvdl scsi_print_addr(xs->sc_link);
1924 1.55 fvdl printf("%d SCBs pending, %d to drain\n", inqueue, todo);
1925 1.42 fvdl break;
1926 1.42 fvdl }
1927 1.42 fvdl break;
1928 1.42 fvdl }
1929 1.42 fvdl case TRACE_POINT:
1930 1.42 fvdl {
1931 1.42 fvdl printf("SSTAT2 = 0x%x DFCNTRL = 0x%x\n", ahc_inb(ahc, SSTAT2),
1932 1.42 fvdl ahc_inb(ahc, DFCNTRL));
1933 1.42 fvdl printf("SSTAT3 = 0x%x DSTATUS = 0x%x\n", ahc_inb(ahc, SSTAT3),
1934 1.42 fvdl ahc_inb(ahc, DFSTATUS));
1935 1.42 fvdl printf("SSTAT0 = 0x%x, SCB_DATACNT = 0x%x\n",
1936 1.42 fvdl ahc_inb(ahc, SSTAT0),
1937 1.42 fvdl ahc_inb(ahc, SCB_DATACNT));
1938 1.42 fvdl break;
1939 1.42 fvdl }
1940 1.42 fvdl case HOST_MSG_LOOP:
1941 1.42 fvdl {
1942 1.42 fvdl /*
1943 1.42 fvdl * The sequencer has encountered a message phase
1944 1.42 fvdl * that requires host assistance for completion.
1945 1.42 fvdl * While handling the message phase(s), we will be
1946 1.42 fvdl * notified by the sequencer after each byte is
1947 1.42 fvdl * transfered so we can track bus phases.
1948 1.42 fvdl *
1949 1.42 fvdl * If this is the first time we've seen a HOST_MSG_LOOP,
1950 1.42 fvdl * initialize the state of the host message loop.
1951 1.42 fvdl */
1952 1.42 fvdl if (ahc->msg_type == MSG_TYPE_NONE) {
1953 1.42 fvdl u_int bus_phase;
1954 1.42 fvdl
1955 1.42 fvdl bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;
1956 1.42 fvdl if (bus_phase != P_MESGIN
1957 1.42 fvdl && bus_phase != P_MESGOUT) {
1958 1.42 fvdl printf("ahc_intr: HOST_MSG_LOOP bad "
1959 1.42 fvdl "phase 0x%x\n",
1960 1.42 fvdl bus_phase);
1961 1.42 fvdl /*
1962 1.42 fvdl * Probably transitioned to bus free before
1963 1.42 fvdl * we got here. Just punt the message.
1964 1.42 fvdl */
1965 1.42 fvdl ahc_clear_intstat(ahc);
1966 1.42 fvdl restart_sequencer(ahc);
1967 1.42 fvdl }
1968 1.42 fvdl
1969 1.42 fvdl if (devinfo.role == ROLE_INITIATOR) {
1970 1.42 fvdl struct scb *scb;
1971 1.42 fvdl u_int scb_index;
1972 1.42 fvdl
1973 1.42 fvdl scb_index = ahc_inb(ahc, SCB_TAG);
1974 1.42 fvdl scb = &ahc->scb_data->scbarray[scb_index];
1975 1.42 fvdl
1976 1.42 fvdl if (bus_phase == P_MESGOUT)
1977 1.42 fvdl ahc_setup_initiator_msgout(ahc,
1978 1.42 fvdl &devinfo,
1979 1.42 fvdl scb);
1980 1.42 fvdl else {
1981 1.42 fvdl ahc->msg_type =
1982 1.42 fvdl MSG_TYPE_INITIATOR_MSGIN;
1983 1.42 fvdl ahc->msgin_index = 0;
1984 1.42 fvdl }
1985 1.42 fvdl } else {
1986 1.42 fvdl if (bus_phase == P_MESGOUT) {
1987 1.42 fvdl ahc->msg_type =
1988 1.42 fvdl MSG_TYPE_TARGET_MSGOUT;
1989 1.42 fvdl ahc->msgin_index = 0;
1990 1.42 fvdl } else
1991 1.42 fvdl /* XXX Ever executed??? */
1992 1.42 fvdl ahc_setup_target_msgin(ahc, &devinfo);
1993 1.42 fvdl }
1994 1.42 fvdl }
1995 1.42 fvdl
1996 1.42 fvdl /* Pass a NULL path so that handlers generate their own */
1997 1.42 fvdl ahc_handle_message_phase(ahc, /*path*/NULL);
1998 1.42 fvdl break;
1999 1.42 fvdl }
2000 1.42 fvdl case PERR_DETECTED:
2001 1.42 fvdl {
2002 1.42 fvdl /*
2003 1.42 fvdl * If we've cleared the parity error interrupt
2004 1.42 fvdl * but the sequencer still believes that SCSIPERR
2005 1.42 fvdl * is true, it must be that the parity error is
2006 1.42 fvdl * for the currently presented byte on the bus,
2007 1.42 fvdl * and we are not in a phase (data-in) where we will
2008 1.42 fvdl * eventually ack this byte. Ack the byte and
2009 1.42 fvdl * throw it away in the hope that the target will
2010 1.42 fvdl * take us to message out to deliver the appropriate
2011 1.42 fvdl * error message.
2012 1.42 fvdl */
2013 1.42 fvdl if ((intstat & SCSIINT) == 0
2014 1.42 fvdl && (ahc_inb(ahc, SSTAT1) & SCSIPERR) != 0) {
2015 1.42 fvdl u_int curphase;
2016 1.42 fvdl
2017 1.42 fvdl /*
2018 1.42 fvdl * The hardware will only let you ack bytes
2019 1.42 fvdl * if the expected phase in SCSISIGO matches
2020 1.42 fvdl * the current phase. Make sure this is
2021 1.42 fvdl * currently the case.
2022 1.42 fvdl */
2023 1.42 fvdl curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;
2024 1.42 fvdl ahc_outb(ahc, LASTPHASE, curphase);
2025 1.42 fvdl ahc_outb(ahc, SCSISIGO, curphase);
2026 1.42 fvdl ahc_inb(ahc, SCSIDATL);
2027 1.42 fvdl }
2028 1.42 fvdl break;
2029 1.42 fvdl }
2030 1.42 fvdl case DATA_OVERRUN:
2031 1.42 fvdl {
2032 1.42 fvdl /*
2033 1.42 fvdl * When the sequencer detects an overrun, it
2034 1.42 fvdl * places the controller in "BITBUCKET" mode
2035 1.42 fvdl * and allows the target to complete its transfer.
2036 1.42 fvdl * Unfortunately, none of the counters get updated
2037 1.42 fvdl * when the controller is in this mode, so we have
2038 1.42 fvdl * no way of knowing how large the overrun was.
2039 1.42 fvdl */
2040 1.42 fvdl u_int scbindex = ahc_inb(ahc, SCB_TAG);
2041 1.42 fvdl u_int lastphase = ahc_inb(ahc, LASTPHASE);
2042 1.42 fvdl int i;
2043 1.42 fvdl
2044 1.42 fvdl scb = &ahc->scb_data->scbarray[scbindex];
2045 1.42 fvdl for (i = 0; i < num_phases; i++) {
2046 1.42 fvdl if (lastphase == phase_table[i].phase)
2047 1.42 fvdl break;
2048 1.42 fvdl }
2049 1.42 fvdl scsi_print_addr(scb->xs->sc_link);
2050 1.42 fvdl printf("data overrun detected %s."
2051 1.42 fvdl " Tag == 0x%x.\n",
2052 1.42 fvdl phase_table[i].phasemsg,
2053 1.42 fvdl scb->hscb->tag);
2054 1.42 fvdl scsi_print_addr(scb->xs->sc_link);
2055 1.42 fvdl printf("%s seen Data Phase. Length = %d. NumSGs = %d.\n",
2056 1.42 fvdl ahc_inb(ahc, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't",
2057 1.42 fvdl scb->xs->datalen, scb->sg_count);
2058 1.42 fvdl if (scb->sg_count > 0) {
2059 1.42 fvdl for (i = 0; i < scb->sg_count; i++) {
2060 1.42 fvdl printf("sg[%d] - Addr 0x%x : Length %d\n",
2061 1.42 fvdl i,
2062 1.42 fvdl le32toh(scb->sg_list[i].addr),
2063 1.42 fvdl le32toh(scb->sg_list[i].len));
2064 1.42 fvdl }
2065 1.42 fvdl }
2066 1.42 fvdl /*
2067 1.42 fvdl * Set this and it will take affect when the
2068 1.42 fvdl * target does a command complete.
2069 1.42 fvdl */
2070 1.42 fvdl ahc_freeze_devq(ahc, scb->xs->sc_link);
2071 1.42 fvdl ahcsetccbstatus(scb->xs, XS_DRIVER_STUFFUP);
2072 1.42 fvdl ahc_freeze_ccb(scb);
2073 1.42 fvdl break;
2074 1.42 fvdl }
2075 1.42 fvdl case TRACEPOINT:
2076 1.6 mycroft {
2077 1.42 fvdl printf("TRACEPOINT: RETURN_1 = %d\n", ahc_inb(ahc, RETURN_1));
2078 1.42 fvdl printf("TRACEPOINT: RETURN_2 = %d\n", ahc_inb(ahc, RETURN_2));
2079 1.42 fvdl printf("TRACEPOINT: ARG_1 = %d\n", ahc_inb(ahc, ARG_1));
2080 1.42 fvdl printf("TRACEPOINT: ARG_2 = %d\n", ahc_inb(ahc, ARG_2));
2081 1.42 fvdl printf("TRACEPOINT: CCHADDR = %x\n",
2082 1.42 fvdl ahc_inb(ahc, CCHADDR) | (ahc_inb(ahc, CCHADDR+1) << 8)
2083 1.42 fvdl | (ahc_inb(ahc, CCHADDR+2) << 16)
2084 1.42 fvdl | (ahc_inb(ahc, CCHADDR+3) << 24));
2085 1.42 fvdl #if 0
2086 1.42 fvdl printf("SSTAT1 == 0x%x\n", ahc_inb(ahc, SSTAT1));
2087 1.42 fvdl printf("SSTAT0 == 0x%x\n", ahc_inb(ahc, SSTAT0));
2088 1.42 fvdl printf(", SCSISIGI == 0x%x\n", ahc_inb(ahc, SCSISIGI));
2089 1.42 fvdl printf("TRACEPOINT: CCHCNT = %d, SG_COUNT = %d\n",
2090 1.42 fvdl ahc_inb(ahc, CCHCNT), ahc_inb(ahc, SG_COUNT));
2091 1.42 fvdl printf("TRACEPOINT: SCB_TAG = %d\n", ahc_inb(ahc, SCB_TAG));
2092 1.42 fvdl printf("TRACEPOINT1: CCHADDR = %d, CCHCNT = %d, SCBPTR = %d\n",
2093 1.42 fvdl ahc_inb(ahc, CCHADDR)
2094 1.42 fvdl | (ahc_inb(ahc, CCHADDR+1) << 8)
2095 1.42 fvdl | (ahc_inb(ahc, CCHADDR+2) << 16)
2096 1.42 fvdl | (ahc_inb(ahc, CCHADDR+3) << 24),
2097 1.42 fvdl ahc_inb(ahc, CCHCNT)
2098 1.42 fvdl | (ahc_inb(ahc, CCHCNT+1) << 8)
2099 1.42 fvdl | (ahc_inb(ahc, CCHCNT+2) << 16),
2100 1.42 fvdl ahc_inb(ahc, SCBPTR));
2101 1.42 fvdl printf("TRACEPOINT: WAITING_SCBH = %d\n", ahc_inb(ahc, WAITING_SCBH));
2102 1.42 fvdl printf("TRACEPOINT: SCB_TAG = %d\n", ahc_inb(ahc, SCB_TAG));
2103 1.42 fvdl #if DDB > 0
2104 1.42 fvdl cpu_Debugger();
2105 1.42 fvdl #endif
2106 1.42 fvdl #endif
2107 1.42 fvdl break;
2108 1.42 fvdl }
2109 1.42 fvdl #if NOT_YET
2110 1.42 fvdl /* XXX Fill these in later */
2111 1.42 fvdl case MESG_BUFFER_BUSY:
2112 1.42 fvdl break;
2113 1.42 fvdl case MSGIN_PHASEMIS:
2114 1.42 fvdl break;
2115 1.42 fvdl #endif
2116 1.42 fvdl default:
2117 1.42 fvdl printf("ahc_intr: seqint, "
2118 1.42 fvdl "intstat == 0x%x, scsisigi = 0x%x\n",
2119 1.42 fvdl intstat, ahc_inb(ahc, SCSISIGI));
2120 1.42 fvdl break;
2121 1.6 mycroft }
2122 1.42 fvdl
2123 1.42 fvdl unpause:
2124 1.42 fvdl /*
2125 1.42 fvdl * The sequencer is paused immediately on
2126 1.42 fvdl * a SEQINT, so we should restart it when
2127 1.42 fvdl * we're done.
2128 1.42 fvdl */
2129 1.42 fvdl unpause_sequencer(ahc);
2130 1.6 mycroft }
2131 1.6 mycroft
2132 1.42 fvdl static void
2133 1.42 fvdl ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
2134 1.6 mycroft {
2135 1.42 fvdl u_int scb_index;
2136 1.42 fvdl u_int status;
2137 1.42 fvdl struct scb *scb;
2138 1.42 fvdl char cur_channel;
2139 1.42 fvdl char intr_channel;
2140 1.6 mycroft
2141 1.42 fvdl if ((ahc->features & AHC_TWIN) != 0
2142 1.42 fvdl && ((ahc_inb(ahc, SBLKCTL) & SELBUSB) != 0))
2143 1.42 fvdl cur_channel = 'B';
2144 1.42 fvdl else
2145 1.42 fvdl cur_channel = 'A';
2146 1.42 fvdl intr_channel = cur_channel;
2147 1.1 mycroft
2148 1.42 fvdl status = ahc_inb(ahc, SSTAT1);
2149 1.42 fvdl if (status == 0) {
2150 1.42 fvdl if ((ahc->features & AHC_TWIN) != 0) {
2151 1.42 fvdl /* Try the other channel */
2152 1.42 fvdl ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) ^ SELBUSB);
2153 1.42 fvdl status = ahc_inb(ahc, SSTAT1);
2154 1.42 fvdl ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) ^ SELBUSB);
2155 1.42 fvdl intr_channel = (cur_channel == 'A') ? 'B' : 'A';
2156 1.42 fvdl }
2157 1.42 fvdl if (status == 0) {
2158 1.42 fvdl printf("%s: Spurious SCSI interrupt\n", ahc_name(ahc));
2159 1.42 fvdl return;
2160 1.42 fvdl }
2161 1.42 fvdl }
2162 1.6 mycroft
2163 1.42 fvdl scb_index = ahc_inb(ahc, SCB_TAG);
2164 1.42 fvdl if (scb_index < ahc->scb_data->numscbs) {
2165 1.42 fvdl scb = &ahc->scb_data->scbarray[scb_index];
2166 1.42 fvdl if ((scb->flags & SCB_ACTIVE) == 0
2167 1.42 fvdl || (ahc_inb(ahc, SEQ_FLAGS) & IDENTIFY_SEEN) == 0)
2168 1.42 fvdl scb = NULL;
2169 1.42 fvdl } else
2170 1.42 fvdl scb = NULL;
2171 1.6 mycroft
2172 1.42 fvdl if ((status & SCSIRSTI) != 0) {
2173 1.42 fvdl printf("%s: Someone reset channel %c\n",
2174 1.42 fvdl ahc_name(ahc), intr_channel);
2175 1.42 fvdl ahc_reset_channel(ahc, intr_channel, /* Initiate Reset */FALSE);
2176 1.42 fvdl } else if ((status & SCSIPERR) != 0) {
2177 1.42 fvdl /*
2178 1.42 fvdl * Determine the bus phase and queue an appropriate message.
2179 1.42 fvdl * SCSIPERR is latched true as soon as a parity error
2180 1.42 fvdl * occurs. If the sequencer acked the transfer that
2181 1.42 fvdl * caused the parity error and the currently presented
2182 1.42 fvdl * transfer on the bus has correct parity, SCSIPERR will
2183 1.42 fvdl * be cleared by CLRSCSIPERR. Use this to determine if
2184 1.42 fvdl * we should look at the last phase the sequencer recorded,
2185 1.42 fvdl * or the current phase presented on the bus.
2186 1.42 fvdl */
2187 1.42 fvdl u_int mesg_out;
2188 1.42 fvdl u_int curphase;
2189 1.42 fvdl u_int errorphase;
2190 1.42 fvdl u_int lastphase;
2191 1.42 fvdl int i;
2192 1.42 fvdl
2193 1.42 fvdl lastphase = ahc_inb(ahc, LASTPHASE);
2194 1.42 fvdl curphase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;
2195 1.42 fvdl ahc_outb(ahc, CLRSINT1, CLRSCSIPERR);
2196 1.42 fvdl /*
2197 1.42 fvdl * For all phases save DATA, the sequencer won't
2198 1.42 fvdl * automatically ack a byte that has a parity error
2199 1.42 fvdl * in it. So the only way that the current phase
2200 1.42 fvdl * could be 'data-in' is if the parity error is for
2201 1.42 fvdl * an already acked byte in the data phase. During
2202 1.42 fvdl * synchronous data-in transfers, we may actually
2203 1.42 fvdl * ack bytes before latching the current phase in
2204 1.42 fvdl * LASTPHASE, leading to the discrepancy between
2205 1.42 fvdl * curphase and lastphase.
2206 1.42 fvdl */
2207 1.42 fvdl if ((ahc_inb(ahc, SSTAT1) & SCSIPERR) != 0
2208 1.42 fvdl || curphase == P_DATAIN)
2209 1.42 fvdl errorphase = curphase;
2210 1.42 fvdl else
2211 1.42 fvdl errorphase = lastphase;
2212 1.6 mycroft
2213 1.42 fvdl for (i = 0; i < num_phases; i++) {
2214 1.42 fvdl if (errorphase == phase_table[i].phase)
2215 1.42 fvdl break;
2216 1.6 mycroft }
2217 1.42 fvdl mesg_out = phase_table[i].mesg_out;
2218 1.42 fvdl if (scb != NULL)
2219 1.42 fvdl scsi_print_addr(scb->xs->sc_link);
2220 1.42 fvdl else
2221 1.42 fvdl printf("%s:%c:%d: ", ahc_name(ahc),
2222 1.42 fvdl intr_channel,
2223 1.42 fvdl TCL_TARGET(ahc_inb(ahc, SAVED_TCL)));
2224 1.42 fvdl
2225 1.42 fvdl printf("parity error detected %s. "
2226 1.42 fvdl "SEQADDR(0x%x) SCSIRATE(0x%x)\n",
2227 1.42 fvdl phase_table[i].phasemsg,
2228 1.42 fvdl ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8),
2229 1.42 fvdl ahc_inb(ahc, SCSIRATE));
2230 1.6 mycroft
2231 1.42 fvdl /*
2232 1.42 fvdl * We've set the hardware to assert ATN if we
2233 1.42 fvdl * get a parity error on "in" phases, so all we
2234 1.42 fvdl * need to do is stuff the message buffer with
2235 1.42 fvdl * the appropriate message. "In" phases have set
2236 1.42 fvdl * mesg_out to something other than MSG_NOP.
2237 1.42 fvdl */
2238 1.42 fvdl if (mesg_out != MSG_NOOP) {
2239 1.42 fvdl if (ahc->msg_type != MSG_TYPE_NONE)
2240 1.42 fvdl ahc->send_msg_perror = TRUE;
2241 1.42 fvdl else
2242 1.42 fvdl ahc_outb(ahc, MSG_OUT, mesg_out);
2243 1.42 fvdl }
2244 1.42 fvdl ahc_outb(ahc, CLRINT, CLRSCSIINT);
2245 1.42 fvdl unpause_sequencer(ahc);
2246 1.42 fvdl } else if ((status & BUSFREE) != 0
2247 1.42 fvdl && (ahc_inb(ahc, SIMODE1) & ENBUSFREE) != 0) {
2248 1.42 fvdl /*
2249 1.42 fvdl * First look at what phase we were last in.
2250 1.42 fvdl * If its message out, chances are pretty good
2251 1.42 fvdl * that the busfree was in response to one of
2252 1.42 fvdl * our abort requests.
2253 1.42 fvdl */
2254 1.42 fvdl u_int lastphase = ahc_inb(ahc, LASTPHASE);
2255 1.42 fvdl u_int saved_tcl = ahc_inb(ahc, SAVED_TCL);
2256 1.42 fvdl u_int target = TCL_TARGET(saved_tcl);
2257 1.42 fvdl u_int initiator_role_id = TCL_SCSI_ID(ahc, saved_tcl);
2258 1.42 fvdl char channel = TCL_CHANNEL(ahc, saved_tcl);
2259 1.42 fvdl int printerror = 1;
2260 1.42 fvdl
2261 1.42 fvdl ahc_outb(ahc, SCSISEQ,
2262 1.42 fvdl ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP));
2263 1.42 fvdl if (lastphase == P_MESGOUT) {
2264 1.42 fvdl u_int message;
2265 1.42 fvdl u_int tag;
2266 1.42 fvdl
2267 1.42 fvdl message = ahc->msgout_buf[ahc->msgout_index - 1];
2268 1.42 fvdl tag = SCB_LIST_NULL;
2269 1.42 fvdl switch (message) {
2270 1.42 fvdl case MSG_ABORT_TAG:
2271 1.42 fvdl tag = scb->hscb->tag;
2272 1.42 fvdl /* FALLTRHOUGH */
2273 1.42 fvdl case MSG_ABORT:
2274 1.42 fvdl scsi_print_addr(scb->xs->sc_link);
2275 1.42 fvdl printf("SCB %x - Abort %s Completed.\n",
2276 1.42 fvdl scb->hscb->tag, tag == SCB_LIST_NULL ?
2277 1.42 fvdl "" : "Tag");
2278 1.42 fvdl ahc_abort_scbs(ahc, target, channel,
2279 1.42 fvdl TCL_LUN(saved_tcl), tag,
2280 1.42 fvdl ROLE_INITIATOR,
2281 1.42 fvdl XS_DRIVER_STUFFUP);
2282 1.42 fvdl printerror = 0;
2283 1.42 fvdl break;
2284 1.42 fvdl case MSG_BUS_DEV_RESET:
2285 1.42 fvdl {
2286 1.42 fvdl struct ahc_devinfo devinfo;
2287 1.6 mycroft
2288 1.42 fvdl if (scb != NULL &&
2289 1.42 fvdl (scb->xs->xs_control & XS_CTL_RESET)
2290 1.42 fvdl && ahc_match_scb(scb, target, channel,
2291 1.42 fvdl TCL_LUN(saved_tcl),
2292 1.42 fvdl SCB_LIST_NULL,
2293 1.42 fvdl ROLE_INITIATOR)) {
2294 1.42 fvdl ahcsetccbstatus(scb->xs, XS_NOERROR);
2295 1.42 fvdl }
2296 1.42 fvdl ahc_compile_devinfo(&devinfo,
2297 1.42 fvdl initiator_role_id,
2298 1.42 fvdl target,
2299 1.42 fvdl TCL_LUN(saved_tcl),
2300 1.42 fvdl channel,
2301 1.42 fvdl ROLE_INITIATOR);
2302 1.42 fvdl ahc_handle_devreset(ahc, &devinfo,
2303 1.42 fvdl XS_RESET,
2304 1.42 fvdl "Bus Device Reset",
2305 1.42 fvdl /*verbose_level*/0);
2306 1.42 fvdl printerror = 0;
2307 1.42 fvdl break;
2308 1.42 fvdl }
2309 1.42 fvdl default:
2310 1.6 mycroft break;
2311 1.42 fvdl }
2312 1.42 fvdl }
2313 1.42 fvdl if (printerror != 0) {
2314 1.42 fvdl int i;
2315 1.6 mycroft
2316 1.42 fvdl if (scb != NULL) {
2317 1.42 fvdl u_int tag;
2318 1.6 mycroft
2319 1.42 fvdl if ((scb->hscb->control & TAG_ENB) != 0)
2320 1.42 fvdl tag = scb->hscb->tag;
2321 1.42 fvdl else
2322 1.42 fvdl tag = SCB_LIST_NULL;
2323 1.42 fvdl ahc_abort_scbs(ahc, target, channel,
2324 1.42 fvdl SCB_LUN(scb), tag,
2325 1.42 fvdl ROLE_INITIATOR,
2326 1.42 fvdl XS_DRIVER_STUFFUP);
2327 1.42 fvdl scsi_print_addr(scb->xs->sc_link);
2328 1.42 fvdl } else {
2329 1.42 fvdl /*
2330 1.42 fvdl * We had not fully identified this connection,
2331 1.42 fvdl * so we cannot abort anything.
2332 1.42 fvdl */
2333 1.42 fvdl printf("%s: ", ahc_name(ahc));
2334 1.42 fvdl }
2335 1.42 fvdl for (i = 0; i < num_phases; i++) {
2336 1.42 fvdl if (lastphase == phase_table[i].phase)
2337 1.42 fvdl break;
2338 1.42 fvdl }
2339 1.42 fvdl printf("Unexpected busfree %s\n"
2340 1.42 fvdl "SEQADDR == 0x%x\n",
2341 1.42 fvdl phase_table[i].phasemsg, ahc_inb(ahc, SEQADDR0)
2342 1.42 fvdl | (ahc_inb(ahc, SEQADDR1) << 8));
2343 1.42 fvdl }
2344 1.42 fvdl ahc_clear_msg_state(ahc);
2345 1.42 fvdl ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
2346 1.42 fvdl ahc_outb(ahc, CLRSINT1, CLRBUSFREE|CLRSCSIPERR);
2347 1.42 fvdl ahc_outb(ahc, CLRINT, CLRSCSIINT);
2348 1.42 fvdl restart_sequencer(ahc);
2349 1.42 fvdl } else if ((status & SELTO) != 0) {
2350 1.42 fvdl u_int scbptr;
2351 1.6 mycroft
2352 1.42 fvdl scbptr = ahc_inb(ahc, WAITING_SCBH);
2353 1.42 fvdl ahc_outb(ahc, SCBPTR, scbptr);
2354 1.42 fvdl scb_index = ahc_inb(ahc, SCB_TAG);
2355 1.42 fvdl
2356 1.42 fvdl if (scb_index < ahc->scb_data->numscbs) {
2357 1.42 fvdl scb = &ahc->scb_data->scbarray[scb_index];
2358 1.42 fvdl if ((scb->flags & SCB_ACTIVE) == 0)
2359 1.42 fvdl scb = NULL;
2360 1.42 fvdl } else
2361 1.42 fvdl scb = NULL;
2362 1.6 mycroft
2363 1.42 fvdl if (scb == NULL) {
2364 1.42 fvdl printf("%s: ahc_intr - referenced scb not "
2365 1.42 fvdl "valid during SELTO scb(%d, %d)\n",
2366 1.42 fvdl ahc_name(ahc), scbptr, scb_index);
2367 1.42 fvdl } else {
2368 1.42 fvdl u_int tag;
2369 1.6 mycroft
2370 1.42 fvdl tag = SCB_LIST_NULL;
2371 1.42 fvdl if ((scb->hscb->control & MSG_SIMPLE_Q_TAG) != 0)
2372 1.42 fvdl tag = scb->hscb->tag;
2373 1.6 mycroft
2374 1.42 fvdl ahc_abort_scbs(ahc, SCB_TARGET(scb), SCB_CHANNEL(scb),
2375 1.42 fvdl SCB_LUN(scb), tag,
2376 1.42 fvdl ROLE_INITIATOR, XS_SELTIMEOUT);
2377 1.42 fvdl }
2378 1.42 fvdl /* Stop the selection */
2379 1.42 fvdl ahc_outb(ahc, SCSISEQ, 0);
2380 1.6 mycroft
2381 1.42 fvdl /* No more pending messages */
2382 1.42 fvdl ahc_clear_msg_state(ahc);
2383 1.6 mycroft
2384 1.42 fvdl /*
2385 1.42 fvdl * Although the driver does not care about the
2386 1.42 fvdl * 'Selection in Progress' status bit, the busy
2387 1.42 fvdl * LED does. SELINGO is only cleared by a sucessful
2388 1.42 fvdl * selection, so we must manually clear it to ensure
2389 1.42 fvdl * the LED turns off just incase no future successful
2390 1.42 fvdl * selections occur (e.g. no devices on the bus).
2391 1.42 fvdl */
2392 1.42 fvdl ahc_outb(ahc, CLRSINT0, CLRSELINGO);
2393 1.6 mycroft
2394 1.42 fvdl /* Clear interrupt state */
2395 1.42 fvdl ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR);
2396 1.42 fvdl ahc_outb(ahc, CLRINT, CLRSCSIINT);
2397 1.42 fvdl restart_sequencer(ahc);
2398 1.42 fvdl } else {
2399 1.42 fvdl scsi_print_addr(scb->xs->sc_link);
2400 1.42 fvdl printf("Unknown SCSIINT. Status = 0x%x\n", status);
2401 1.42 fvdl ahc_outb(ahc, CLRSINT1, status);
2402 1.42 fvdl ahc_outb(ahc, CLRINT, CLRSCSIINT);
2403 1.42 fvdl unpause_sequencer(ahc);
2404 1.6 mycroft }
2405 1.1 mycroft }
2406 1.1 mycroft
2407 1.42 fvdl static void
2408 1.42 fvdl ahc_build_transfer_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
2409 1.1 mycroft {
2410 1.42 fvdl /*
2411 1.42 fvdl * We need to initiate transfer negotiations.
2412 1.42 fvdl * If our current and goal settings are identical,
2413 1.42 fvdl * we want to renegotiate due to a check condition.
2414 1.42 fvdl */
2415 1.42 fvdl struct ahc_initiator_tinfo *tinfo;
2416 1.42 fvdl struct tmode_tstate *tstate;
2417 1.42 fvdl int dowide;
2418 1.42 fvdl int dosync;
2419 1.42 fvdl
2420 1.42 fvdl tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
2421 1.42 fvdl devinfo->target, &tstate);
2422 1.42 fvdl dowide = tinfo->current.width != tinfo->goal.width;
2423 1.42 fvdl dosync = tinfo->current.period != tinfo->goal.period;
2424 1.42 fvdl
2425 1.42 fvdl if (!dowide && !dosync) {
2426 1.42 fvdl dowide = tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT;
2427 1.42 fvdl dosync = tinfo->goal.period != 0;
2428 1.42 fvdl }
2429 1.42 fvdl
2430 1.42 fvdl if (dowide) {
2431 1.42 fvdl ahc_construct_wdtr(ahc, tinfo->goal.width);
2432 1.42 fvdl } else if (dosync) {
2433 1.42 fvdl struct ahc_syncrate *rate;
2434 1.42 fvdl u_int period;
2435 1.42 fvdl u_int offset;
2436 1.42 fvdl
2437 1.42 fvdl period = tinfo->goal.period;
2438 1.42 fvdl rate = ahc_devlimited_syncrate(ahc, &period);
2439 1.42 fvdl offset = tinfo->goal.offset;
2440 1.42 fvdl ahc_validate_offset(ahc, rate, &offset,
2441 1.42 fvdl tinfo->current.width);
2442 1.42 fvdl ahc_construct_sdtr(ahc, period, offset);
2443 1.42 fvdl } else {
2444 1.42 fvdl panic("ahc_intr: AWAITING_MSG for negotiation, "
2445 1.42 fvdl "but no negotiation needed\n");
2446 1.42 fvdl }
2447 1.42 fvdl }
2448 1.1 mycroft
2449 1.42 fvdl static void
2450 1.42 fvdl ahc_setup_initiator_msgout(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
2451 1.42 fvdl struct scb *scb)
2452 1.42 fvdl {
2453 1.42 fvdl /*
2454 1.42 fvdl * To facilitate adding multiple messages together,
2455 1.42 fvdl * each routine should increment the index and len
2456 1.42 fvdl * variables instead of setting them explicitly.
2457 1.42 fvdl */
2458 1.42 fvdl ahc->msgout_index = 0;
2459 1.42 fvdl ahc->msgout_len = 0;
2460 1.42 fvdl
2461 1.42 fvdl if ((scb->flags & SCB_DEVICE_RESET) == 0
2462 1.42 fvdl && ahc_inb(ahc, MSG_OUT) == MSG_IDENTIFYFLAG) {
2463 1.42 fvdl u_int identify_msg;
2464 1.42 fvdl
2465 1.42 fvdl identify_msg = MSG_IDENTIFYFLAG | SCB_LUN(scb);
2466 1.42 fvdl if ((scb->hscb->control & DISCENB) != 0)
2467 1.42 fvdl identify_msg |= MSG_IDENTIFY_DISCFLAG;
2468 1.42 fvdl ahc->msgout_buf[ahc->msgout_index++] = identify_msg;
2469 1.42 fvdl ahc->msgout_len++;
2470 1.42 fvdl
2471 1.42 fvdl if ((scb->hscb->control & TAG_ENB) != 0) {
2472 1.42 fvdl /* XXX fvdl FreeBSD has tag action passed down */
2473 1.42 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_SIMPLE_Q_TAG;
2474 1.42 fvdl ahc->msgout_buf[ahc->msgout_index++] = scb->hscb->tag;
2475 1.42 fvdl ahc->msgout_len += 2;
2476 1.42 fvdl }
2477 1.42 fvdl }
2478 1.6 mycroft
2479 1.42 fvdl if (scb->flags & SCB_DEVICE_RESET) {
2480 1.42 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_BUS_DEV_RESET;
2481 1.42 fvdl ahc->msgout_len++;
2482 1.42 fvdl scsi_print_addr(scb->xs->sc_link);
2483 1.42 fvdl printf("Bus Device Reset Message Sent\n");
2484 1.42 fvdl } else if (scb->flags & SCB_ABORT) {
2485 1.42 fvdl if ((scb->hscb->control & TAG_ENB) != 0)
2486 1.42 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_ABORT_TAG;
2487 1.42 fvdl else
2488 1.42 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_ABORT;
2489 1.42 fvdl ahc->msgout_len++;
2490 1.42 fvdl scsi_print_addr(scb->xs->sc_link);
2491 1.42 fvdl printf("Abort Message Sent\n");
2492 1.42 fvdl } else if ((ahc->targ_msg_req & devinfo->target_mask) != 0) {
2493 1.42 fvdl ahc_build_transfer_msg(ahc, devinfo);
2494 1.42 fvdl } else {
2495 1.42 fvdl printf("ahc_intr: AWAITING_MSG for an SCB that "
2496 1.42 fvdl "does not have a waiting message");
2497 1.42 fvdl panic("SCB = %d, SCB Control = %x, MSG_OUT = %x "
2498 1.42 fvdl "SCB flags = %x", scb->hscb->tag, scb->hscb->control,
2499 1.42 fvdl ahc_inb(ahc, MSG_OUT), scb->flags);
2500 1.42 fvdl }
2501 1.6 mycroft
2502 1.42 fvdl /*
2503 1.42 fvdl * Clear the MK_MESSAGE flag from the SCB so we aren't
2504 1.42 fvdl * asked to send this message again.
2505 1.42 fvdl */
2506 1.42 fvdl ahc_outb(ahc, SCB_CONTROL, ahc_inb(ahc, SCB_CONTROL) & ~MK_MESSAGE);
2507 1.42 fvdl ahc->msgout_index = 0;
2508 1.42 fvdl ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
2509 1.1 mycroft }
2510 1.1 mycroft
2511 1.42 fvdl static void
2512 1.42 fvdl ahc_setup_target_msgin(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
2513 1.1 mycroft {
2514 1.42 fvdl /*
2515 1.42 fvdl * To facilitate adding multiple messages together,
2516 1.42 fvdl * each routine should increment the index and len
2517 1.42 fvdl * variables instead of setting them explicitly.
2518 1.42 fvdl */
2519 1.42 fvdl ahc->msgout_index = 0;
2520 1.42 fvdl ahc->msgout_len = 0;
2521 1.42 fvdl
2522 1.42 fvdl if ((ahc->targ_msg_req & devinfo->target_mask) != 0)
2523 1.42 fvdl ahc_build_transfer_msg(ahc, devinfo);
2524 1.42 fvdl else
2525 1.42 fvdl panic("ahc_intr: AWAITING target message with no message");
2526 1.40 thorpej
2527 1.42 fvdl ahc->msgout_index = 0;
2528 1.42 fvdl ahc->msg_type = MSG_TYPE_TARGET_MSGIN;
2529 1.42 fvdl }
2530 1.6 mycroft
2531 1.42 fvdl static int
2532 1.42 fvdl ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
2533 1.42 fvdl {
2534 1.1 mycroft /*
2535 1.42 fvdl * What we care about here is if we had an
2536 1.42 fvdl * outstanding SDTR or WDTR message for this
2537 1.42 fvdl * target. If we did, this is a signal that
2538 1.42 fvdl * the target is refusing negotiation.
2539 1.1 mycroft */
2540 1.42 fvdl struct scb *scb;
2541 1.42 fvdl u_int scb_index;
2542 1.42 fvdl u_int last_msg;
2543 1.42 fvdl int response = 0;
2544 1.42 fvdl
2545 1.42 fvdl scb_index = ahc_inb(ahc, SCB_TAG);
2546 1.42 fvdl scb = &ahc->scb_data->scbarray[scb_index];
2547 1.42 fvdl
2548 1.42 fvdl /* Might be necessary */
2549 1.42 fvdl last_msg = ahc_inb(ahc, LAST_MSG);
2550 1.42 fvdl
2551 1.42 fvdl if (ahc_sent_msg(ahc, MSG_EXT_WDTR, /*full*/FALSE)) {
2552 1.42 fvdl struct ahc_initiator_tinfo *tinfo;
2553 1.42 fvdl struct tmode_tstate *tstate;
2554 1.42 fvdl
2555 1.42 fvdl #ifdef AHC_DEBUG_NEG
2556 1.42 fvdl /* note 8bit xfers */
2557 1.42 fvdl printf("%s:%c:%d: refuses WIDE negotiation. Using "
2558 1.42 fvdl "8bit transfers\n", ahc_name(ahc),
2559 1.42 fvdl devinfo->channel, devinfo->target);
2560 1.42 fvdl #endif
2561 1.42 fvdl ahc_set_width(ahc, devinfo,
2562 1.42 fvdl MSG_EXT_WDTR_BUS_8_BIT,
2563 1.42 fvdl AHC_TRANS_ACTIVE|AHC_TRANS_GOAL,
2564 1.42 fvdl /*paused*/TRUE, /*done*/TRUE);
2565 1.42 fvdl /*
2566 1.42 fvdl * No need to clear the sync rate. If the target
2567 1.42 fvdl * did not accept the command, our syncrate is
2568 1.42 fvdl * unaffected. If the target started the negotiation,
2569 1.42 fvdl * but rejected our response, we already cleared the
2570 1.42 fvdl * sync rate before sending our WDTR.
2571 1.42 fvdl */
2572 1.42 fvdl tinfo = ahc_fetch_transinfo(ahc, devinfo->channel,
2573 1.42 fvdl devinfo->our_scsiid,
2574 1.42 fvdl devinfo->target, &tstate);
2575 1.42 fvdl if (tinfo->goal.period) {
2576 1.42 fvdl u_int period;
2577 1.42 fvdl
2578 1.42 fvdl /* Start the sync negotiation */
2579 1.42 fvdl period = tinfo->goal.period;
2580 1.42 fvdl ahc_devlimited_syncrate(ahc, &period);
2581 1.42 fvdl ahc->msgout_index = 0;
2582 1.42 fvdl ahc->msgout_len = 0;
2583 1.42 fvdl ahc_construct_sdtr(ahc, period, tinfo->goal.offset);
2584 1.42 fvdl ahc->msgout_index = 0;
2585 1.42 fvdl response = 1;
2586 1.42 fvdl }
2587 1.42 fvdl } else if (ahc_sent_msg(ahc, MSG_EXT_SDTR, /*full*/FALSE)) {
2588 1.42 fvdl /* note asynch xfers and clear flag */
2589 1.42 fvdl ahc_set_syncrate(ahc, devinfo, /*syncrate*/NULL, /*period*/0,
2590 1.42 fvdl /*offset*/0, AHC_TRANS_ACTIVE|AHC_TRANS_GOAL,
2591 1.42 fvdl /*paused*/TRUE, /*done*/TRUE);
2592 1.42 fvdl #ifdef AHC_DEBUG_NEG
2593 1.42 fvdl printf("%s:%c:%d: refuses synchronous negotiation. "
2594 1.42 fvdl "Using asynchronous transfers\n",
2595 1.42 fvdl ahc_name(ahc),
2596 1.42 fvdl devinfo->channel, devinfo->target);
2597 1.42 fvdl #endif
2598 1.42 fvdl } else if ((scb->hscb->control & MSG_SIMPLE_Q_TAG) != 0) {
2599 1.42 fvdl printf("%s:%c:%d: refuses tagged commands. Performing "
2600 1.42 fvdl "non-tagged I/O\n", ahc_name(ahc),
2601 1.42 fvdl devinfo->channel, devinfo->target);
2602 1.42 fvdl
2603 1.42 fvdl ahc_set_tags(ahc, devinfo, FALSE);
2604 1.6 mycroft
2605 1.42 fvdl /*
2606 1.42 fvdl * Resend the identify for this CCB as the target
2607 1.42 fvdl * may believe that the selection is invalid otherwise.
2608 1.42 fvdl */
2609 1.42 fvdl ahc_outb(ahc, SCB_CONTROL, ahc_inb(ahc, SCB_CONTROL)
2610 1.42 fvdl & ~MSG_SIMPLE_Q_TAG);
2611 1.42 fvdl scb->hscb->control &= ~MSG_SIMPLE_Q_TAG;
2612 1.42 fvdl ahc_outb(ahc, MSG_OUT, MSG_IDENTIFYFLAG);
2613 1.42 fvdl ahc_outb(ahc, SCSISIGO, ahc_inb(ahc, SCSISIGO) | ATNO);
2614 1.1 mycroft
2615 1.42 fvdl /*
2616 1.42 fvdl * Requeue all tagged commands for this target
2617 1.42 fvdl * currently in our posession so they can be
2618 1.42 fvdl * converted to untagged commands.
2619 1.42 fvdl */
2620 1.42 fvdl ahc_search_qinfifo(ahc, SCB_TARGET(scb), SCB_CHANNEL(scb),
2621 1.42 fvdl SCB_LUN(scb), /*tag*/SCB_LIST_NULL,
2622 1.42 fvdl ROLE_INITIATOR, SCB_REQUEUE,
2623 1.42 fvdl SEARCH_COMPLETE);
2624 1.42 fvdl } else {
2625 1.42 fvdl /*
2626 1.42 fvdl * Otherwise, we ignore it.
2627 1.42 fvdl */
2628 1.42 fvdl printf("%s:%c:%d: Message reject for %x -- ignored\n",
2629 1.42 fvdl ahc_name(ahc), devinfo->channel, devinfo->target,
2630 1.42 fvdl last_msg);
2631 1.42 fvdl }
2632 1.42 fvdl return (response);
2633 1.42 fvdl }
2634 1.14 gibbs
2635 1.42 fvdl static void
2636 1.42 fvdl ahc_clear_msg_state(struct ahc_softc *ahc)
2637 1.42 fvdl {
2638 1.42 fvdl ahc->msgout_len = 0;
2639 1.42 fvdl ahc->msgin_index = 0;
2640 1.42 fvdl ahc->msg_type = MSG_TYPE_NONE;
2641 1.42 fvdl ahc_outb(ahc, MSG_OUT, MSG_NOOP);
2642 1.42 fvdl }
2643 1.14 gibbs
2644 1.42 fvdl static void
2645 1.42 fvdl ahc_handle_message_phase(struct ahc_softc *ahc, struct scsipi_link *sc_link)
2646 1.42 fvdl {
2647 1.42 fvdl struct ahc_devinfo devinfo;
2648 1.42 fvdl u_int bus_phase;
2649 1.42 fvdl int end_session;
2650 1.42 fvdl
2651 1.42 fvdl ahc_fetch_devinfo(ahc, &devinfo);
2652 1.42 fvdl end_session = FALSE;
2653 1.42 fvdl bus_phase = ahc_inb(ahc, SCSISIGI) & PHASE_MASK;
2654 1.42 fvdl
2655 1.42 fvdl reswitch:
2656 1.42 fvdl switch (ahc->msg_type) {
2657 1.42 fvdl case MSG_TYPE_INITIATOR_MSGOUT:
2658 1.42 fvdl {
2659 1.42 fvdl int lastbyte;
2660 1.42 fvdl int phasemis;
2661 1.42 fvdl int msgdone;
2662 1.42 fvdl
2663 1.42 fvdl if (ahc->msgout_len == 0)
2664 1.42 fvdl panic("REQINIT interrupt with no active message");
2665 1.42 fvdl
2666 1.42 fvdl phasemis = bus_phase != P_MESGOUT;
2667 1.42 fvdl if (phasemis) {
2668 1.42 fvdl if (bus_phase == P_MESGIN) {
2669 1.42 fvdl /*
2670 1.42 fvdl * Change gears and see if
2671 1.42 fvdl * this messages is of interest to
2672 1.42 fvdl * us or should be passed back to
2673 1.42 fvdl * the sequencer.
2674 1.42 fvdl */
2675 1.42 fvdl ahc_outb(ahc, CLRSINT1, CLRATNO);
2676 1.42 fvdl ahc->send_msg_perror = FALSE;
2677 1.42 fvdl ahc->msg_type = MSG_TYPE_INITIATOR_MSGIN;
2678 1.42 fvdl ahc->msgin_index = 0;
2679 1.42 fvdl goto reswitch;
2680 1.42 fvdl }
2681 1.42 fvdl end_session = TRUE;
2682 1.42 fvdl break;
2683 1.14 gibbs }
2684 1.42 fvdl
2685 1.42 fvdl if (ahc->send_msg_perror) {
2686 1.42 fvdl ahc_outb(ahc, CLRSINT1, CLRATNO);
2687 1.42 fvdl ahc_outb(ahc, CLRSINT1, CLRREQINIT);
2688 1.42 fvdl ahc_outb(ahc, SCSIDATL, MSG_PARITY_ERROR);
2689 1.42 fvdl break;
2690 1.14 gibbs }
2691 1.42 fvdl
2692 1.42 fvdl msgdone = ahc->msgout_index == ahc->msgout_len;
2693 1.42 fvdl if (msgdone) {
2694 1.14 gibbs /*
2695 1.42 fvdl * The target has requested a retry.
2696 1.42 fvdl * Re-assert ATN, reset our message index to
2697 1.42 fvdl * 0, and try again.
2698 1.14 gibbs */
2699 1.42 fvdl ahc->msgout_index = 0;
2700 1.42 fvdl ahc_outb(ahc, SCSISIGO, ahc_inb(ahc, SCSISIGO) | ATNO);
2701 1.42 fvdl }
2702 1.42 fvdl
2703 1.42 fvdl lastbyte = ahc->msgout_index == (ahc->msgout_len - 1);
2704 1.42 fvdl if (lastbyte) {
2705 1.42 fvdl /* Last byte is signified by dropping ATN */
2706 1.42 fvdl ahc_outb(ahc, CLRSINT1, CLRATNO);
2707 1.42 fvdl }
2708 1.42 fvdl
2709 1.42 fvdl /*
2710 1.42 fvdl * Clear our interrupt status and present
2711 1.42 fvdl * the next byte on the bus.
2712 1.42 fvdl */
2713 1.42 fvdl ahc_outb(ahc, CLRSINT1, CLRREQINIT);
2714 1.42 fvdl ahc_outb(ahc, SCSIDATL, ahc->msgout_buf[ahc->msgout_index++]);
2715 1.42 fvdl break;
2716 1.42 fvdl }
2717 1.42 fvdl case MSG_TYPE_INITIATOR_MSGIN:
2718 1.42 fvdl {
2719 1.42 fvdl int phasemis;
2720 1.42 fvdl int message_done;
2721 1.42 fvdl
2722 1.42 fvdl phasemis = bus_phase != P_MESGIN;
2723 1.42 fvdl
2724 1.42 fvdl if (phasemis) {
2725 1.42 fvdl ahc->msgin_index = 0;
2726 1.42 fvdl if (bus_phase == P_MESGOUT
2727 1.42 fvdl && (ahc->send_msg_perror == TRUE
2728 1.42 fvdl || (ahc->msgout_len != 0
2729 1.42 fvdl && ahc->msgout_index == 0))) {
2730 1.42 fvdl ahc->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
2731 1.42 fvdl goto reswitch;
2732 1.14 gibbs }
2733 1.42 fvdl end_session = TRUE;
2734 1.42 fvdl break;
2735 1.42 fvdl }
2736 1.42 fvdl
2737 1.42 fvdl /* Pull the byte in without acking it */
2738 1.42 fvdl ahc->msgin_buf[ahc->msgin_index] = ahc_inb(ahc, SCSIBUSL);
2739 1.42 fvdl
2740 1.42 fvdl message_done = ahc_parse_msg(ahc, sc_link, &devinfo);
2741 1.42 fvdl
2742 1.42 fvdl if (message_done) {
2743 1.42 fvdl /*
2744 1.42 fvdl * Clear our incoming message buffer in case there
2745 1.42 fvdl * is another message following this one.
2746 1.42 fvdl */
2747 1.42 fvdl ahc->msgin_index = 0;
2748 1.42 fvdl
2749 1.42 fvdl /*
2750 1.42 fvdl * If this message illicited a response,
2751 1.42 fvdl * assert ATN so the target takes us to the
2752 1.42 fvdl * message out phase.
2753 1.42 fvdl */
2754 1.42 fvdl if (ahc->msgout_len != 0)
2755 1.42 fvdl ahc_outb(ahc, SCSISIGO,
2756 1.42 fvdl ahc_inb(ahc, SCSISIGO) | ATNO);
2757 1.42 fvdl } else
2758 1.42 fvdl ahc->msgin_index++;
2759 1.42 fvdl
2760 1.42 fvdl /* Ack the byte */
2761 1.42 fvdl ahc_outb(ahc, CLRSINT1, CLRREQINIT);
2762 1.42 fvdl ahc_inb(ahc, SCSIDATL);
2763 1.42 fvdl break;
2764 1.42 fvdl }
2765 1.42 fvdl case MSG_TYPE_TARGET_MSGIN:
2766 1.42 fvdl {
2767 1.42 fvdl int msgdone;
2768 1.42 fvdl int msgout_request;
2769 1.42 fvdl
2770 1.42 fvdl if (ahc->msgout_len == 0)
2771 1.42 fvdl panic("Target MSGIN with no active message");
2772 1.42 fvdl
2773 1.42 fvdl /*
2774 1.42 fvdl * If we interrupted a mesgout session, the initiator
2775 1.42 fvdl * will not know this until our first REQ. So, we
2776 1.42 fvdl * only honor mesgout requests after we've sent our
2777 1.42 fvdl * first byte.
2778 1.42 fvdl */
2779 1.42 fvdl if ((ahc_inb(ahc, SCSISIGI) & ATNI) != 0
2780 1.42 fvdl && ahc->msgout_index > 0)
2781 1.42 fvdl msgout_request = TRUE;
2782 1.42 fvdl else
2783 1.42 fvdl msgout_request = FALSE;
2784 1.42 fvdl
2785 1.42 fvdl if (msgout_request) {
2786 1.42 fvdl
2787 1.42 fvdl /*
2788 1.42 fvdl * Change gears and see if
2789 1.42 fvdl * this messages is of interest to
2790 1.42 fvdl * us or should be passed back to
2791 1.42 fvdl * the sequencer.
2792 1.42 fvdl */
2793 1.42 fvdl ahc->msg_type = MSG_TYPE_TARGET_MSGOUT;
2794 1.42 fvdl ahc_outb(ahc, SCSISIGO, P_MESGOUT | BSYO);
2795 1.42 fvdl ahc->msgin_index = 0;
2796 1.42 fvdl /* Dummy read to REQ for first byte */
2797 1.42 fvdl ahc_inb(ahc, SCSIDATL);
2798 1.42 fvdl ahc_outb(ahc, SXFRCTL0,
2799 1.42 fvdl ahc_inb(ahc, SXFRCTL0) | SPIOEN);
2800 1.42 fvdl break;
2801 1.42 fvdl }
2802 1.42 fvdl
2803 1.42 fvdl msgdone = ahc->msgout_index == ahc->msgout_len;
2804 1.42 fvdl if (msgdone) {
2805 1.42 fvdl ahc_outb(ahc, SXFRCTL0,
2806 1.42 fvdl ahc_inb(ahc, SXFRCTL0) & ~SPIOEN);
2807 1.42 fvdl end_session = TRUE;
2808 1.42 fvdl break;
2809 1.42 fvdl }
2810 1.42 fvdl
2811 1.42 fvdl /*
2812 1.42 fvdl * Present the next byte on the bus.
2813 1.42 fvdl */
2814 1.42 fvdl ahc_outb(ahc, SXFRCTL0, ahc_inb(ahc, SXFRCTL0) | SPIOEN);
2815 1.42 fvdl ahc_outb(ahc, SCSIDATL, ahc->msgout_buf[ahc->msgout_index++]);
2816 1.42 fvdl break;
2817 1.42 fvdl }
2818 1.42 fvdl case MSG_TYPE_TARGET_MSGOUT:
2819 1.42 fvdl {
2820 1.42 fvdl int lastbyte;
2821 1.42 fvdl int msgdone;
2822 1.42 fvdl
2823 1.42 fvdl /*
2824 1.42 fvdl * The initiator signals that this is
2825 1.42 fvdl * the last byte by dropping ATN.
2826 1.42 fvdl */
2827 1.42 fvdl lastbyte = (ahc_inb(ahc, SCSISIGI) & ATNI) == 0;
2828 1.42 fvdl
2829 1.42 fvdl /*
2830 1.42 fvdl * Read the latched byte, but turn off SPIOEN first
2831 1.42 fvdl * so that we don't inadvertantly cause a REQ for the
2832 1.42 fvdl * next byte.
2833 1.42 fvdl */
2834 1.42 fvdl ahc_outb(ahc, SXFRCTL0, ahc_inb(ahc, SXFRCTL0) & ~SPIOEN);
2835 1.42 fvdl ahc->msgin_buf[ahc->msgin_index] = ahc_inb(ahc, SCSIDATL);
2836 1.42 fvdl msgdone = ahc_parse_msg(ahc, sc_link, &devinfo);
2837 1.42 fvdl if (msgdone == MSGLOOP_TERMINATED) {
2838 1.42 fvdl /*
2839 1.42 fvdl * The message is *really* done in that it caused
2840 1.42 fvdl * us to go to bus free. The sequencer has already
2841 1.42 fvdl * been reset at this point, so pull the ejection
2842 1.42 fvdl * handle.
2843 1.42 fvdl */
2844 1.42 fvdl return;
2845 1.42 fvdl }
2846 1.42 fvdl
2847 1.42 fvdl ahc->msgin_index++;
2848 1.42 fvdl
2849 1.42 fvdl /*
2850 1.42 fvdl * XXX Read spec about initiator dropping ATN too soon
2851 1.42 fvdl * and use msgdone to detect it.
2852 1.42 fvdl */
2853 1.42 fvdl if (msgdone == MSGLOOP_MSGCOMPLETE) {
2854 1.42 fvdl ahc->msgin_index = 0;
2855 1.9 explorer
2856 1.14 gibbs /*
2857 1.42 fvdl * If this message illicited a response, transition
2858 1.42 fvdl * to the Message in phase and send it.
2859 1.14 gibbs */
2860 1.42 fvdl if (ahc->msgout_len != 0) {
2861 1.42 fvdl ahc_outb(ahc, SCSISIGO, P_MESGIN | BSYO);
2862 1.42 fvdl ahc_outb(ahc, SXFRCTL0,
2863 1.42 fvdl ahc_inb(ahc, SXFRCTL0) | SPIOEN);
2864 1.42 fvdl ahc->msg_type = MSG_TYPE_TARGET_MSGIN;
2865 1.42 fvdl ahc->msgin_index = 0;
2866 1.42 fvdl break;
2867 1.14 gibbs }
2868 1.14 gibbs }
2869 1.14 gibbs
2870 1.42 fvdl if (lastbyte)
2871 1.42 fvdl end_session = TRUE;
2872 1.42 fvdl else {
2873 1.42 fvdl /* Ask for the next byte. */
2874 1.42 fvdl ahc_outb(ahc, SXFRCTL0,
2875 1.42 fvdl ahc_inb(ahc, SXFRCTL0) | SPIOEN);
2876 1.42 fvdl }
2877 1.9 explorer
2878 1.42 fvdl break;
2879 1.42 fvdl }
2880 1.42 fvdl default:
2881 1.42 fvdl panic("Unknown REQINIT message type");
2882 1.14 gibbs }
2883 1.14 gibbs
2884 1.42 fvdl if (end_session) {
2885 1.42 fvdl ahc_clear_msg_state(ahc);
2886 1.42 fvdl ahc_outb(ahc, RETURN_1, EXIT_MSG_LOOP);
2887 1.42 fvdl } else
2888 1.42 fvdl ahc_outb(ahc, RETURN_1, CONT_MSG_LOOP);
2889 1.14 gibbs }
2890 1.14 gibbs
2891 1.42 fvdl /*
2892 1.42 fvdl * See if we sent a particular extended message to the target.
2893 1.42 fvdl * If "full" is true, the target saw the full message.
2894 1.42 fvdl * If "full" is false, the target saw at least the first
2895 1.42 fvdl * byte of the message.
2896 1.42 fvdl */
2897 1.42 fvdl static int
2898 1.42 fvdl ahc_sent_msg(struct ahc_softc *ahc, u_int msgtype, int full)
2899 1.14 gibbs {
2900 1.42 fvdl int found;
2901 1.42 fvdl int index;
2902 1.14 gibbs
2903 1.42 fvdl found = FALSE;
2904 1.42 fvdl index = 0;
2905 1.14 gibbs
2906 1.42 fvdl while (index < ahc->msgout_len) {
2907 1.42 fvdl if (ahc->msgout_buf[index] == MSG_EXTENDED) {
2908 1.14 gibbs
2909 1.42 fvdl /* Found a candidate */
2910 1.42 fvdl if (ahc->msgout_buf[index+2] == msgtype) {
2911 1.42 fvdl u_int end_index;
2912 1.42 fvdl
2913 1.42 fvdl end_index = index + 1
2914 1.42 fvdl + ahc->msgout_buf[index + 1];
2915 1.42 fvdl if (full) {
2916 1.42 fvdl if (ahc->msgout_index > end_index)
2917 1.42 fvdl found = TRUE;
2918 1.42 fvdl } else if (ahc->msgout_index > index)
2919 1.42 fvdl found = TRUE;
2920 1.14 gibbs }
2921 1.42 fvdl break;
2922 1.42 fvdl } else if (ahc->msgout_buf[index] >= MSG_SIMPLE_Q_TAG
2923 1.42 fvdl && ahc->msgout_buf[index] <= MSG_IGN_WIDE_RESIDUE) {
2924 1.14 gibbs
2925 1.42 fvdl /* Skip tag type and tag id or residue param*/
2926 1.42 fvdl index += 2;
2927 1.14 gibbs } else {
2928 1.42 fvdl /* Single byte message */
2929 1.42 fvdl index++;
2930 1.14 gibbs }
2931 1.42 fvdl }
2932 1.42 fvdl return (found);
2933 1.42 fvdl }
2934 1.42 fvdl
2935 1.42 fvdl static int
2936 1.42 fvdl ahc_parse_msg(struct ahc_softc *ahc, struct scsipi_link *sc_link,
2937 1.42 fvdl struct ahc_devinfo *devinfo)
2938 1.42 fvdl {
2939 1.42 fvdl struct ahc_initiator_tinfo *tinfo;
2940 1.42 fvdl struct tmode_tstate *tstate;
2941 1.42 fvdl int reject;
2942 1.42 fvdl int done;
2943 1.42 fvdl int response;
2944 1.42 fvdl u_int targ_scsirate;
2945 1.42 fvdl
2946 1.42 fvdl done = MSGLOOP_IN_PROG;
2947 1.42 fvdl response = FALSE;
2948 1.42 fvdl reject = FALSE;
2949 1.42 fvdl tinfo = ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
2950 1.42 fvdl devinfo->target, &tstate);
2951 1.42 fvdl targ_scsirate = tinfo->scsirate;
2952 1.42 fvdl
2953 1.42 fvdl /*
2954 1.42 fvdl * Parse as much of the message as is availible,
2955 1.42 fvdl * rejecting it if we don't support it. When
2956 1.42 fvdl * the entire message is availible and has been
2957 1.42 fvdl * handled, return MSGLOOP_MSGCOMPLETE, indicating
2958 1.42 fvdl * that we have parsed an entire message.
2959 1.42 fvdl *
2960 1.42 fvdl * In the case of extended messages, we accept the length
2961 1.42 fvdl * byte outright and perform more checking once we know the
2962 1.42 fvdl * extended message type.
2963 1.42 fvdl */
2964 1.42 fvdl switch (ahc->msgin_buf[0]) {
2965 1.42 fvdl case MSG_MESSAGE_REJECT:
2966 1.42 fvdl response = ahc_handle_msg_reject(ahc, devinfo);
2967 1.42 fvdl /* FALLTHROUGH */
2968 1.42 fvdl case MSG_NOOP:
2969 1.42 fvdl done = MSGLOOP_MSGCOMPLETE;
2970 1.14 gibbs break;
2971 1.42 fvdl case MSG_IGN_WIDE_RESIDUE:
2972 1.14 gibbs {
2973 1.42 fvdl /* Wait for the whole message */
2974 1.42 fvdl if (ahc->msgin_index >= 1) {
2975 1.42 fvdl if (ahc->msgin_buf[1] != 1
2976 1.42 fvdl || tinfo->current.width == MSG_EXT_WDTR_BUS_8_BIT) {
2977 1.42 fvdl reject = TRUE;
2978 1.42 fvdl done = MSGLOOP_MSGCOMPLETE;
2979 1.42 fvdl } else
2980 1.42 fvdl ahc_handle_ign_wide_residue(ahc, devinfo);
2981 1.42 fvdl }
2982 1.42 fvdl break;
2983 1.14 gibbs }
2984 1.42 fvdl case MSG_EXTENDED:
2985 1.14 gibbs {
2986 1.42 fvdl /* Wait for enough of the message to begin validation */
2987 1.42 fvdl if (ahc->msgin_index < 2)
2988 1.42 fvdl break;
2989 1.42 fvdl switch (ahc->msgin_buf[2]) {
2990 1.14 gibbs case MSG_EXT_SDTR:
2991 1.14 gibbs {
2992 1.42 fvdl struct ahc_syncrate *syncrate;
2993 1.42 fvdl u_int period;
2994 1.42 fvdl u_int offset;
2995 1.42 fvdl u_int saved_offset;
2996 1.42 fvdl
2997 1.42 fvdl if (ahc->msgin_buf[1] != MSG_EXT_SDTR_LEN) {
2998 1.42 fvdl reject = TRUE;
2999 1.14 gibbs break;
3000 1.14 gibbs }
3001 1.14 gibbs
3002 1.14 gibbs /*
3003 1.42 fvdl * Wait until we have both args before validating
3004 1.42 fvdl * and acting on this message.
3005 1.42 fvdl *
3006 1.42 fvdl * Add one to MSG_EXT_SDTR_LEN to account for
3007 1.42 fvdl * the extended message preamble.
3008 1.14 gibbs */
3009 1.42 fvdl if (ahc->msgin_index < (MSG_EXT_SDTR_LEN + 1))
3010 1.42 fvdl break;
3011 1.42 fvdl
3012 1.42 fvdl period = ahc->msgin_buf[3];
3013 1.42 fvdl saved_offset = offset = ahc->msgin_buf[4];
3014 1.42 fvdl syncrate = ahc_devlimited_syncrate(ahc, &period);
3015 1.42 fvdl ahc_validate_offset(ahc, syncrate, &offset,
3016 1.42 fvdl targ_scsirate & WIDEXFER);
3017 1.42 fvdl ahc_set_syncrate(ahc, devinfo,
3018 1.42 fvdl syncrate, period, offset,
3019 1.42 fvdl AHC_TRANS_ACTIVE|AHC_TRANS_GOAL,
3020 1.42 fvdl /*paused*/TRUE, /*done*/TRUE);
3021 1.14 gibbs
3022 1.14 gibbs /*
3023 1.14 gibbs * See if we initiated Sync Negotiation
3024 1.14 gibbs * and didn't have to fall down to async
3025 1.14 gibbs * transfers.
3026 1.14 gibbs */
3027 1.42 fvdl if (ahc_sent_msg(ahc, MSG_EXT_SDTR, /*full*/TRUE)) {
3028 1.42 fvdl /* We started it */
3029 1.42 fvdl if (saved_offset != offset) {
3030 1.42 fvdl /* Went too low - force async */
3031 1.42 fvdl reject = TRUE;
3032 1.42 fvdl }
3033 1.14 gibbs } else {
3034 1.14 gibbs /*
3035 1.14 gibbs * Send our own SDTR in reply
3036 1.1 mycroft */
3037 1.42 fvdl ahc->msgout_index = 0;
3038 1.42 fvdl ahc->msgout_len = 0;
3039 1.42 fvdl ahc_construct_sdtr(ahc, period, offset);
3040 1.42 fvdl ahc->msgout_index = 0;
3041 1.42 fvdl response = TRUE;
3042 1.1 mycroft }
3043 1.42 fvdl done = MSGLOOP_MSGCOMPLETE;
3044 1.14 gibbs break;
3045 1.14 gibbs }
3046 1.14 gibbs case MSG_EXT_WDTR:
3047 1.14 gibbs {
3048 1.42 fvdl u_int bus_width;
3049 1.42 fvdl u_int sending_reply;
3050 1.1 mycroft
3051 1.42 fvdl sending_reply = FALSE;
3052 1.42 fvdl if (ahc->msgin_buf[1] != MSG_EXT_WDTR_LEN) {
3053 1.42 fvdl reject = TRUE;
3054 1.14 gibbs break;
3055 1.14 gibbs }
3056 1.1 mycroft
3057 1.42 fvdl /*
3058 1.42 fvdl * Wait until we have our arg before validating
3059 1.42 fvdl * and acting on this message.
3060 1.42 fvdl *
3061 1.42 fvdl * Add one to MSG_EXT_WDTR_LEN to account for
3062 1.42 fvdl * the extended message preamble.
3063 1.42 fvdl */
3064 1.42 fvdl if (ahc->msgin_index < (MSG_EXT_WDTR_LEN + 1))
3065 1.42 fvdl break;
3066 1.1 mycroft
3067 1.42 fvdl bus_width = ahc->msgin_buf[3];
3068 1.42 fvdl if (ahc_sent_msg(ahc, MSG_EXT_WDTR, /*full*/TRUE)) {
3069 1.14 gibbs /*
3070 1.14 gibbs * Don't send a WDTR back to the
3071 1.14 gibbs * target, since we asked first.
3072 1.14 gibbs */
3073 1.42 fvdl switch (bus_width){
3074 1.42 fvdl default:
3075 1.6 mycroft /*
3076 1.42 fvdl * How can we do anything greater
3077 1.42 fvdl * than 16bit transfers on a 16bit
3078 1.42 fvdl * bus?
3079 1.6 mycroft */
3080 1.42 fvdl reject = TRUE;
3081 1.42 fvdl printf("%s: target %d requested %dBit "
3082 1.14 gibbs "transfers. Rejecting...\n",
3083 1.42 fvdl ahc_name(ahc), devinfo->target,
3084 1.42 fvdl 8 * (0x01 << bus_width));
3085 1.42 fvdl /* FALLTHROUGH */
3086 1.42 fvdl case MSG_EXT_WDTR_BUS_8_BIT:
3087 1.42 fvdl bus_width = MSG_EXT_WDTR_BUS_8_BIT;
3088 1.14 gibbs break;
3089 1.42 fvdl case MSG_EXT_WDTR_BUS_16_BIT:
3090 1.14 gibbs break;
3091 1.14 gibbs }
3092 1.14 gibbs } else {
3093 1.14 gibbs /*
3094 1.14 gibbs * Send our own WDTR in reply
3095 1.14 gibbs */
3096 1.42 fvdl switch (bus_width) {
3097 1.14 gibbs default:
3098 1.42 fvdl if (ahc->features & AHC_WIDE) {
3099 1.42 fvdl /* Respond Wide */
3100 1.42 fvdl bus_width =
3101 1.42 fvdl MSG_EXT_WDTR_BUS_16_BIT;
3102 1.42 fvdl break;
3103 1.42 fvdl }
3104 1.42 fvdl /* FALLTHROUGH */
3105 1.42 fvdl case MSG_EXT_WDTR_BUS_8_BIT:
3106 1.42 fvdl bus_width = MSG_EXT_WDTR_BUS_8_BIT;
3107 1.14 gibbs break;
3108 1.1 mycroft }
3109 1.42 fvdl ahc->msgout_index = 0;
3110 1.42 fvdl ahc->msgout_len = 0;
3111 1.42 fvdl ahc_construct_wdtr(ahc, bus_width);
3112 1.42 fvdl ahc->msgout_index = 0;
3113 1.42 fvdl response = TRUE;
3114 1.42 fvdl sending_reply = TRUE;
3115 1.42 fvdl }
3116 1.42 fvdl ahc_set_width(ahc, devinfo, bus_width,
3117 1.42 fvdl AHC_TRANS_ACTIVE|AHC_TRANS_GOAL,
3118 1.42 fvdl /*paused*/TRUE, /*done*/TRUE);
3119 1.42 fvdl
3120 1.42 fvdl /* After a wide message, we are async */
3121 1.42 fvdl ahc_set_syncrate(ahc, devinfo,
3122 1.42 fvdl /*syncrate*/NULL, /*period*/0,
3123 1.42 fvdl /*offset*/0, AHC_TRANS_ACTIVE,
3124 1.42 fvdl /*paused*/TRUE, /*done*/FALSE);
3125 1.42 fvdl if (sending_reply == FALSE && reject == FALSE) {
3126 1.42 fvdl
3127 1.42 fvdl if (tinfo->goal.period) {
3128 1.42 fvdl struct ahc_syncrate *rate;
3129 1.42 fvdl u_int period;
3130 1.42 fvdl u_int offset;
3131 1.42 fvdl
3132 1.42 fvdl /* Start the sync negotiation */
3133 1.42 fvdl period = tinfo->goal.period;
3134 1.42 fvdl rate = ahc_devlimited_syncrate(ahc,
3135 1.42 fvdl &period);
3136 1.42 fvdl offset = tinfo->goal.offset;
3137 1.42 fvdl ahc_validate_offset(ahc, rate, &offset,
3138 1.42 fvdl tinfo->current.width);
3139 1.42 fvdl ahc->msgout_index = 0;
3140 1.42 fvdl ahc->msgout_len = 0;
3141 1.42 fvdl ahc_construct_sdtr(ahc, period, offset);
3142 1.42 fvdl ahc->msgout_index = 0;
3143 1.42 fvdl response = TRUE;
3144 1.42 fvdl }
3145 1.42 fvdl }
3146 1.42 fvdl done = MSGLOOP_MSGCOMPLETE;
3147 1.14 gibbs break;
3148 1.14 gibbs }
3149 1.14 gibbs default:
3150 1.14 gibbs /* Unknown extended message. Reject it. */
3151 1.42 fvdl reject = TRUE;
3152 1.42 fvdl break;
3153 1.14 gibbs }
3154 1.42 fvdl break;
3155 1.14 gibbs }
3156 1.42 fvdl case MSG_BUS_DEV_RESET:
3157 1.42 fvdl ahc_handle_devreset(ahc, devinfo,
3158 1.42 fvdl XS_RESET, "Bus Device Reset Received",
3159 1.42 fvdl /*verbose_level*/0);
3160 1.42 fvdl restart_sequencer(ahc);
3161 1.42 fvdl done = MSGLOOP_TERMINATED;
3162 1.42 fvdl break;
3163 1.42 fvdl case MSG_ABORT_TAG:
3164 1.42 fvdl case MSG_ABORT:
3165 1.42 fvdl case MSG_CLEAR_QUEUE:
3166 1.42 fvdl /* Target mode messages */
3167 1.42 fvdl if (devinfo->role != ROLE_TARGET) {
3168 1.42 fvdl reject = TRUE;
3169 1.14 gibbs break;
3170 1.14 gibbs }
3171 1.42 fvdl #if AHC_TARGET_MODE
3172 1.42 fvdl ahc_abort_scbs(ahc, devinfo->target, devinfo->channel,
3173 1.42 fvdl devinfo->lun,
3174 1.42 fvdl ahc->msgin_buf[0] == MSG_ABORT_TAG
3175 1.42 fvdl ? SCB_LIST_NULL
3176 1.42 fvdl : ahc_inb(ahc, INITIATOR_TAG),
3177 1.42 fvdl ROLE_TARGET, XS_DRIVER_STUFFUP);
3178 1.42 fvdl
3179 1.42 fvdl tstate = ahc->enabled_targets[devinfo->our_scsiid];
3180 1.42 fvdl if (tstate != NULL) {
3181 1.42 fvdl struct tmode_lstate* lstate;
3182 1.42 fvdl
3183 1.42 fvdl lstate = tstate->enabled_luns[devinfo->lun];
3184 1.42 fvdl if (lstate != NULL) {
3185 1.42 fvdl ahc_queue_lstate_event(ahc, lstate,
3186 1.42 fvdl devinfo->our_scsiid,
3187 1.42 fvdl ahc->msgin_buf[0],
3188 1.42 fvdl /*arg*/0);
3189 1.42 fvdl ahc_send_lstate_events(ahc, lstate);
3190 1.42 fvdl }
3191 1.42 fvdl }
3192 1.42 fvdl done = MSGLOOP_MSGCOMPLETE;
3193 1.42 fvdl #else
3194 1.42 fvdl panic("ahc: got target mode message");
3195 1.42 fvdl #endif
3196 1.42 fvdl break;
3197 1.42 fvdl case MSG_TERM_IO_PROC:
3198 1.42 fvdl default:
3199 1.42 fvdl reject = TRUE;
3200 1.14 gibbs break;
3201 1.14 gibbs }
3202 1.6 mycroft
3203 1.42 fvdl if (reject) {
3204 1.14 gibbs /*
3205 1.42 fvdl * Setup to reject the message.
3206 1.14 gibbs */
3207 1.42 fvdl ahc->msgout_index = 0;
3208 1.42 fvdl ahc->msgout_len = 1;
3209 1.42 fvdl ahc->msgout_buf[0] = MSG_MESSAGE_REJECT;
3210 1.42 fvdl done = MSGLOOP_MSGCOMPLETE;
3211 1.42 fvdl response = TRUE;
3212 1.42 fvdl }
3213 1.1 mycroft
3214 1.42 fvdl if (done != MSGLOOP_IN_PROG && !response)
3215 1.42 fvdl /* Clear the outgoing message buffer */
3216 1.42 fvdl ahc->msgout_len = 0;
3217 1.1 mycroft
3218 1.42 fvdl return (done);
3219 1.42 fvdl }
3220 1.1 mycroft
3221 1.42 fvdl static void
3222 1.42 fvdl ahc_handle_ign_wide_residue(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
3223 1.42 fvdl {
3224 1.42 fvdl u_int scb_index;
3225 1.42 fvdl struct scb *scb;
3226 1.22 cgd
3227 1.42 fvdl scb_index = ahc_inb(ahc, SCB_TAG);
3228 1.42 fvdl scb = &ahc->scb_data->scbarray[scb_index];
3229 1.42 fvdl if ((ahc_inb(ahc, SEQ_FLAGS) & DPHASE) == 0
3230 1.42 fvdl || !(scb->xs->xs_control & XS_CTL_DATA_IN)) {
3231 1.42 fvdl /*
3232 1.42 fvdl * Ignore the message if we haven't
3233 1.42 fvdl * seen an appropriate data phase yet.
3234 1.42 fvdl */
3235 1.42 fvdl } else {
3236 1.1 mycroft /*
3237 1.42 fvdl * If the residual occurred on the last
3238 1.42 fvdl * transfer and the transfer request was
3239 1.42 fvdl * expected to end on an odd count, do
3240 1.42 fvdl * nothing. Otherwise, subtract a byte
3241 1.42 fvdl * and update the residual count accordingly.
3242 1.1 mycroft */
3243 1.42 fvdl u_int resid_sgcnt;
3244 1.6 mycroft
3245 1.42 fvdl resid_sgcnt = ahc_inb(ahc, SCB_RESID_SGCNT);
3246 1.42 fvdl if (resid_sgcnt == 0
3247 1.42 fvdl && ahc_inb(ahc, DATA_COUNT_ODD) == 1) {
3248 1.6 mycroft /*
3249 1.42 fvdl * If the residual occurred on the last
3250 1.42 fvdl * transfer and the transfer request was
3251 1.42 fvdl * expected to end on an odd count, do
3252 1.42 fvdl * nothing.
3253 1.6 mycroft */
3254 1.42 fvdl } else {
3255 1.42 fvdl u_int data_cnt;
3256 1.42 fvdl u_int32_t data_addr;
3257 1.42 fvdl u_int sg_index;
3258 1.42 fvdl
3259 1.42 fvdl data_cnt = (ahc_inb(ahc, SCB_RESID_DCNT + 2) << 16)
3260 1.42 fvdl | (ahc_inb(ahc, SCB_RESID_DCNT + 1) << 8)
3261 1.42 fvdl | (ahc_inb(ahc, SCB_RESID_DCNT));
3262 1.42 fvdl
3263 1.42 fvdl data_addr = (ahc_inb(ahc, SHADDR + 3) << 24)
3264 1.42 fvdl | (ahc_inb(ahc, SHADDR + 2) << 16)
3265 1.42 fvdl | (ahc_inb(ahc, SHADDR + 1) << 8)
3266 1.42 fvdl | (ahc_inb(ahc, SHADDR));
3267 1.42 fvdl
3268 1.42 fvdl data_cnt += 1;
3269 1.42 fvdl data_addr -= 1;
3270 1.42 fvdl
3271 1.42 fvdl sg_index = scb->sg_count - resid_sgcnt;
3272 1.42 fvdl
3273 1.42 fvdl if (sg_index != 0
3274 1.42 fvdl && (le32toh(scb->sg_list[sg_index].len) < data_cnt)) {
3275 1.42 fvdl u_int32_t sg_addr;
3276 1.42 fvdl
3277 1.42 fvdl sg_index--;
3278 1.42 fvdl data_cnt = 1;
3279 1.42 fvdl data_addr = le32toh(scb->sg_list[sg_index].addr)
3280 1.42 fvdl + le32toh(scb->sg_list[sg_index].len)
3281 1.42 fvdl - 1;
3282 1.42 fvdl
3283 1.42 fvdl /*
3284 1.42 fvdl * The physical address base points to the
3285 1.42 fvdl * second entry as it is always used for
3286 1.42 fvdl * calculating the "next S/G pointer".
3287 1.42 fvdl */
3288 1.42 fvdl sg_addr = scb->sg_list_phys
3289 1.42 fvdl + (sg_index* sizeof(*scb->sg_list));
3290 1.42 fvdl ahc_outb(ahc, SG_NEXT + 3, sg_addr >> 24);
3291 1.42 fvdl ahc_outb(ahc, SG_NEXT + 2, sg_addr >> 16);
3292 1.42 fvdl ahc_outb(ahc, SG_NEXT + 1, sg_addr >> 8);
3293 1.42 fvdl ahc_outb(ahc, SG_NEXT, sg_addr);
3294 1.6 mycroft }
3295 1.9 explorer
3296 1.42 fvdl ahc_outb(ahc, SCB_RESID_DCNT + 2, data_cnt >> 16);
3297 1.42 fvdl ahc_outb(ahc, SCB_RESID_DCNT + 1, data_cnt >> 8);
3298 1.42 fvdl ahc_outb(ahc, SCB_RESID_DCNT, data_cnt);
3299 1.42 fvdl
3300 1.42 fvdl ahc_outb(ahc, SHADDR + 3, data_addr >> 24);
3301 1.42 fvdl ahc_outb(ahc, SHADDR + 2, data_addr >> 16);
3302 1.42 fvdl ahc_outb(ahc, SHADDR + 1, data_addr >> 8);
3303 1.42 fvdl ahc_outb(ahc, SHADDR, data_addr);
3304 1.1 mycroft }
3305 1.6 mycroft }
3306 1.42 fvdl }
3307 1.1 mycroft
3308 1.42 fvdl static void
3309 1.42 fvdl ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
3310 1.42 fvdl int status, char *message,
3311 1.42 fvdl int verbose_level)
3312 1.42 fvdl {
3313 1.42 fvdl int found;
3314 1.14 gibbs
3315 1.42 fvdl found = ahc_abort_scbs(ahc, devinfo->target, devinfo->channel,
3316 1.42 fvdl AHC_LUN_WILDCARD, SCB_LIST_NULL, devinfo->role,
3317 1.42 fvdl status);
3318 1.14 gibbs
3319 1.14 gibbs /*
3320 1.42 fvdl * Go back to async/narrow transfers and renegotiate.
3321 1.42 fvdl * ahc_set_width and ahc_set_syncrate can cope with NULL
3322 1.42 fvdl * paths.
3323 1.42 fvdl */
3324 1.42 fvdl ahc_set_width(ahc, devinfo, MSG_EXT_WDTR_BUS_8_BIT,
3325 1.42 fvdl AHC_TRANS_CUR, /*paused*/TRUE, /*done*/FALSE);
3326 1.42 fvdl ahc_set_syncrate(ahc, devinfo, /*syncrate*/NULL,
3327 1.42 fvdl /*period*/0, /*offset*/0, AHC_TRANS_CUR,
3328 1.42 fvdl /*paused*/TRUE, /*done*/FALSE);
3329 1.42 fvdl
3330 1.42 fvdl if (message != NULL && (verbose_level <= 0))
3331 1.42 fvdl printf("%s: %s on %c:%d. %d SCBs aborted\n", ahc_name(ahc),
3332 1.42 fvdl message, devinfo->channel, devinfo->target, found);
3333 1.1 mycroft }
3334 1.1 mycroft
3335 1.1 mycroft /*
3336 1.42 fvdl * We have an scb which has been processed by the
3337 1.1 mycroft * adaptor, now we look to see how the operation
3338 1.1 mycroft * went.
3339 1.1 mycroft */
3340 1.6 mycroft static void
3341 1.42 fvdl ahc_done(struct ahc_softc *ahc, struct scb *scb)
3342 1.1 mycroft {
3343 1.42 fvdl struct scsipi_xfer *xs;
3344 1.42 fvdl struct scsipi_link *sc_link;
3345 1.42 fvdl int requeue = 0;
3346 1.42 fvdl int target;
3347 1.42 fvdl
3348 1.42 fvdl
3349 1.42 fvdl xs = scb->xs;
3350 1.42 fvdl sc_link = xs->sc_link;
3351 1.42 fvdl LIST_REMOVE(scb, plinks);
3352 1.42 fvdl
3353 1.44 thorpej callout_stop(&scb->xs->xs_callout);
3354 1.42 fvdl
3355 1.42 fvdl #ifdef AHC_DEBUG
3356 1.42 fvdl if (ahc_debug & AHC_SHOWCMDS) {
3357 1.42 fvdl scsi_print_addr(sc_link);
3358 1.42 fvdl printf("ahc_done opcode %d tag %x\n", xs->cmdstore.opcode,
3359 1.42 fvdl scb->hscb->tag);
3360 1.42 fvdl }
3361 1.42 fvdl #endif
3362 1.6 mycroft
3363 1.42 fvdl target = sc_link->scsipi_scsi.target;
3364 1.28 leo
3365 1.28 leo if (xs->datalen) {
3366 1.42 fvdl int op;
3367 1.42 fvdl
3368 1.42 fvdl if (xs->xs_control & XS_CTL_DATA_IN)
3369 1.42 fvdl op = BUS_DMASYNC_POSTREAD;
3370 1.42 fvdl else
3371 1.42 fvdl op = BUS_DMASYNC_POSTWRITE;
3372 1.42 fvdl bus_dmamap_sync(ahc->parent_dmat, scb->dmamap, 0,
3373 1.42 fvdl scb->dmamap->dm_mapsize, op);
3374 1.42 fvdl bus_dmamap_unload(ahc->parent_dmat, scb->dmamap);
3375 1.28 leo }
3376 1.42 fvdl
3377 1.28 leo /*
3378 1.42 fvdl * Unbusy this target/channel/lun.
3379 1.42 fvdl * XXX if we are holding two commands per lun,
3380 1.42 fvdl * send the next command.
3381 1.42 fvdl */
3382 1.45 fvdl if (!(scb->hscb->control & TAG_ENB))
3383 1.45 fvdl ahc_index_busy_tcl(ahc, scb->hscb->tcl, /*unbusy*/TRUE);
3384 1.42 fvdl
3385 1.1 mycroft /*
3386 1.42 fvdl * If the recovery SCB completes, we have to be
3387 1.42 fvdl * out of our timeout.
3388 1.1 mycroft */
3389 1.42 fvdl if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
3390 1.42 fvdl
3391 1.42 fvdl struct scb *scbp;
3392 1.42 fvdl
3393 1.42 fvdl /*
3394 1.42 fvdl * We were able to complete the command successfully,
3395 1.42 fvdl * so reinstate the timeouts for all other pending
3396 1.42 fvdl * commands.
3397 1.42 fvdl */
3398 1.42 fvdl scbp = ahc->pending_ccbs.lh_first;
3399 1.42 fvdl while (scbp != NULL) {
3400 1.42 fvdl struct scsipi_xfer *txs = scbp->xs;
3401 1.42 fvdl
3402 1.42 fvdl if (!(txs->xs_control & XS_CTL_POLL)) {
3403 1.44 thorpej callout_reset(&scbp->xs->xs_callout,
3404 1.44 thorpej (scbp->xs->timeout * hz) / 1000,
3405 1.44 thorpej ahc_timeout, scbp);
3406 1.42 fvdl }
3407 1.42 fvdl scbp = LIST_NEXT(scbp, plinks);
3408 1.42 fvdl }
3409 1.42 fvdl
3410 1.42 fvdl /*
3411 1.42 fvdl * Ensure that we didn't put a second instance of this
3412 1.42 fvdl * SCB into the QINFIFO.
3413 1.42 fvdl */
3414 1.42 fvdl ahc_search_qinfifo(ahc, SCB_TARGET(scb), SCB_CHANNEL(scb),
3415 1.42 fvdl SCB_LUN(scb), scb->hscb->tag,
3416 1.42 fvdl ROLE_INITIATOR, /*status*/0,
3417 1.42 fvdl SEARCH_REMOVE);
3418 1.42 fvdl if (xs->error != XS_NOERROR)
3419 1.42 fvdl ahcsetccbstatus(xs, XS_TIMEOUT);
3420 1.42 fvdl scsi_print_addr(xs->sc_link);
3421 1.42 fvdl printf("no longer in timeout, status = %x\n", xs->status);
3422 1.42 fvdl }
3423 1.42 fvdl
3424 1.6 mycroft if (xs->error != XS_NOERROR) {
3425 1.42 fvdl /* Don't clobber any existing error state */
3426 1.42 fvdl } else if ((scb->flags & SCB_SENSE) != 0) {
3427 1.42 fvdl /*
3428 1.42 fvdl * We performed autosense retrieval.
3429 1.42 fvdl *
3430 1.42 fvdl * bzero the sense data before having
3431 1.42 fvdl * the drive fill it. The SCSI spec mandates
3432 1.42 fvdl * that any untransfered data should be
3433 1.42 fvdl * assumed to be zero. Complete the 'bounce'
3434 1.42 fvdl * of sense information through buffers accessible
3435 1.42 fvdl * via bus-space by copying it into the clients
3436 1.42 fvdl * csio.
3437 1.42 fvdl */
3438 1.42 fvdl bzero(&xs->sense.scsi_sense, sizeof(xs->sense.scsi_sense));
3439 1.42 fvdl bcopy(&ahc->scb_data->sense[scb->hscb->tag],
3440 1.42 fvdl &xs->sense.scsi_sense, le32toh(scb->sg_list->len));
3441 1.6 mycroft xs->error = XS_SENSE;
3442 1.28 leo }
3443 1.42 fvdl if (scb->flags & SCB_FREEZE_QUEUE) {
3444 1.42 fvdl ahc->devqueue_blocked[target]--;
3445 1.42 fvdl scb->flags &= ~SCB_FREEZE_QUEUE;
3446 1.1 mycroft }
3447 1.42 fvdl
3448 1.42 fvdl requeue = scb->flags & SCB_REQUEUE;
3449 1.42 fvdl ahcfreescb(ahc, scb);
3450 1.42 fvdl
3451 1.42 fvdl if (requeue) {
3452 1.42 fvdl /*
3453 1.42 fvdl * Re-insert at the front of the private queue to
3454 1.42 fvdl * preserve order.
3455 1.1 mycroft */
3456 1.42 fvdl int s;
3457 1.42 fvdl
3458 1.55 fvdl if (xs->xs_status & XS_STS_DEBUG) {
3459 1.55 fvdl scsi_print_addr(xs->sc_link);
3460 1.55 fvdl printf("putting SCB that caused queue full back"
3461 1.55 fvdl " in queue\n");
3462 1.55 fvdl }
3463 1.55 fvdl
3464 1.42 fvdl s = splbio();
3465 1.42 fvdl TAILQ_INSERT_HEAD(&ahc->sc_q, xs, adapter_q);
3466 1.42 fvdl splx(s);
3467 1.42 fvdl } else {
3468 1.55 fvdl if (xs->xs_status & XS_STS_DEBUG) {
3469 1.55 fvdl xs->xs_status &= ~XS_STS_DEBUG;
3470 1.55 fvdl scsi_print_addr(xs->sc_link);
3471 1.55 fvdl printf("completed SCB that caused queue full\n");
3472 1.55 fvdl }
3473 1.42 fvdl xs->xs_status |= XS_STS_DONE;
3474 1.45 fvdl ahc_check_tags(ahc, xs);
3475 1.42 fvdl scsipi_done(xs);
3476 1.1 mycroft }
3477 1.18 thorpej
3478 1.34 thorpej if ((xs = TAILQ_FIRST(&ahc->sc_q)) != NULL)
3479 1.42 fvdl ahc_action(xs);
3480 1.42 fvdl }
3481 1.42 fvdl
3482 1.42 fvdl /*
3483 1.42 fvdl * Determine the number of SCBs available on the controller
3484 1.42 fvdl */
3485 1.42 fvdl int
3486 1.42 fvdl ahc_probe_scbs(struct ahc_softc *ahc) {
3487 1.42 fvdl int i;
3488 1.42 fvdl
3489 1.42 fvdl for (i = 0; i < AHC_SCB_MAX; i++) {
3490 1.42 fvdl ahc_outb(ahc, SCBPTR, i);
3491 1.42 fvdl ahc_outb(ahc, SCB_CONTROL, i);
3492 1.42 fvdl if (ahc_inb(ahc, SCB_CONTROL) != i)
3493 1.42 fvdl break;
3494 1.42 fvdl ahc_outb(ahc, SCBPTR, 0);
3495 1.42 fvdl if (ahc_inb(ahc, SCB_CONTROL) != 0)
3496 1.42 fvdl break;
3497 1.42 fvdl }
3498 1.42 fvdl return (i);
3499 1.1 mycroft }
3500 1.1 mycroft
3501 1.1 mycroft /*
3502 1.1 mycroft * Start the board, ready for normal operation
3503 1.1 mycroft */
3504 1.1 mycroft int
3505 1.42 fvdl ahc_init(struct ahc_softc *ahc)
3506 1.1 mycroft {
3507 1.14 gibbs int max_targ = 15;
3508 1.42 fvdl int i;
3509 1.42 fvdl int term;
3510 1.42 fvdl u_int scsi_conf;
3511 1.42 fvdl u_int scsiseq_template;
3512 1.42 fvdl u_int ultraenb;
3513 1.42 fvdl u_int discenable;
3514 1.42 fvdl u_int tagenable;
3515 1.42 fvdl size_t driver_data_size;
3516 1.42 fvdl u_int32_t physaddr;
3517 1.42 fvdl
3518 1.42 fvdl #ifdef AHC_PRINT_SRAM
3519 1.42 fvdl printf("Scratch Ram:");
3520 1.42 fvdl for (i = 0x20; i < 0x5f; i++) {
3521 1.42 fvdl if (((i % 8) == 0) && (i != 0)) {
3522 1.42 fvdl printf ("\n ");
3523 1.42 fvdl }
3524 1.42 fvdl printf (" 0x%x", ahc_inb(ahc, i));
3525 1.42 fvdl }
3526 1.42 fvdl if ((ahc->features & AHC_MORE_SRAM) != 0) {
3527 1.42 fvdl for (i = 0x70; i < 0x7f; i++) {
3528 1.42 fvdl if (((i % 8) == 0) && (i != 0)) {
3529 1.42 fvdl printf ("\n ");
3530 1.42 fvdl }
3531 1.42 fvdl printf (" 0x%x", ahc_inb(ahc, i));
3532 1.42 fvdl }
3533 1.42 fvdl }
3534 1.42 fvdl printf ("\n");
3535 1.28 leo #endif
3536 1.28 leo
3537 1.1 mycroft /*
3538 1.6 mycroft * Assume we have a board at this stage and it has been reset.
3539 1.1 mycroft */
3540 1.42 fvdl if ((ahc->flags & AHC_USEDEFAULTS) != 0)
3541 1.42 fvdl ahc->our_id = ahc->our_id_b = 7;
3542 1.42 fvdl
3543 1.42 fvdl /*
3544 1.42 fvdl * Default to allowing initiator operations.
3545 1.42 fvdl */
3546 1.42 fvdl ahc->flags |= AHC_INITIATORMODE;
3547 1.1 mycroft
3548 1.42 fvdl /*
3549 1.42 fvdl * DMA tag for our command fifos and other data in system memory
3550 1.42 fvdl * the card's sequencer must be able to access. For initiator
3551 1.42 fvdl * roles, we need to allocate space for the qinfifo, qoutfifo,
3552 1.42 fvdl * and untagged_scb arrays each of which are composed of 256
3553 1.42 fvdl * 1 byte elements. When providing for the target mode role,
3554 1.42 fvdl * we additionally must provide space for the incoming target
3555 1.42 fvdl * command fifo.
3556 1.42 fvdl */
3557 1.42 fvdl driver_data_size = 3 * 256 * sizeof(u_int8_t);
3558 1.6 mycroft
3559 1.42 fvdl if (ahc_createdmamem(ahc->parent_dmat, driver_data_size,
3560 1.42 fvdl ahc->sc_dmaflags,
3561 1.42 fvdl &ahc->shared_data_dmamap, (caddr_t *)&ahc->qoutfifo,
3562 1.42 fvdl &ahc->shared_data_busaddr, &ahc->shared_data_seg,
3563 1.42 fvdl &ahc->shared_data_nseg, ahc_name(ahc), "shared data") < 0)
3564 1.42 fvdl return (ENOMEM);
3565 1.1 mycroft
3566 1.42 fvdl ahc->init_level++;
3567 1.1 mycroft
3568 1.42 fvdl /* Allocate SCB data now that parent_dmat is initialized */
3569 1.42 fvdl if (ahc->scb_data->maxhscbs == 0)
3570 1.42 fvdl if (ahcinitscbdata(ahc) != 0)
3571 1.42 fvdl return (ENOMEM);
3572 1.1 mycroft
3573 1.42 fvdl ahc->qinfifo = &ahc->qoutfifo[256];
3574 1.42 fvdl ahc->untagged_scbs = &ahc->qinfifo[256];
3575 1.42 fvdl /* There are no untagged SCBs active yet. */
3576 1.42 fvdl for (i = 0; i < 256; i++)
3577 1.42 fvdl ahc->untagged_scbs[i] = SCB_LIST_NULL;
3578 1.6 mycroft
3579 1.42 fvdl /* All of our queues are empty */
3580 1.42 fvdl for (i = 0; i < 256; i++)
3581 1.42 fvdl ahc->qoutfifo[i] = SCB_LIST_NULL;
3582 1.6 mycroft
3583 1.42 fvdl bus_dmamap_sync(ahc->parent_dmat, ahc->shared_data_dmamap, 0,
3584 1.42 fvdl driver_data_size, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
3585 1.6 mycroft
3586 1.28 leo /*
3587 1.42 fvdl * Allocate a tstate to house information for our
3588 1.42 fvdl * initiator presence on the bus as well as the user
3589 1.42 fvdl * data for any target mode initiator.
3590 1.28 leo */
3591 1.42 fvdl if (ahc_alloc_tstate(ahc, ahc->our_id, 'A') == NULL) {
3592 1.42 fvdl printf("%s: unable to allocate tmode_tstate. "
3593 1.42 fvdl "Failing attach\n", ahc_name(ahc));
3594 1.42 fvdl return (-1);
3595 1.28 leo }
3596 1.42 fvdl
3597 1.42 fvdl if ((ahc->features & AHC_TWIN) != 0) {
3598 1.42 fvdl if (ahc_alloc_tstate(ahc, ahc->our_id_b, 'B') == NULL) {
3599 1.42 fvdl printf("%s: unable to allocate tmode_tstate. "
3600 1.42 fvdl "Failing attach\n", ahc_name(ahc));
3601 1.42 fvdl return (-1);
3602 1.42 fvdl }
3603 1.42 fvdl printf("Twin Channel, A SCSI Id=%d, B SCSI Id=%d, primary %c, ",
3604 1.42 fvdl ahc->our_id, ahc->our_id_b,
3605 1.42 fvdl ahc->flags & AHC_CHANNEL_B_PRIMARY? 'B': 'A');
3606 1.42 fvdl } else {
3607 1.42 fvdl if ((ahc->features & AHC_WIDE) != 0) {
3608 1.42 fvdl printf("Wide ");
3609 1.42 fvdl } else {
3610 1.42 fvdl printf("Single ");
3611 1.42 fvdl }
3612 1.42 fvdl printf("Channel %c, SCSI Id=%d, ", ahc->channel, ahc->our_id);
3613 1.28 leo }
3614 1.42 fvdl
3615 1.42 fvdl ahc_outb(ahc, SEQ_FLAGS, 0);
3616 1.42 fvdl
3617 1.42 fvdl if (ahc->scb_data->maxhscbs < AHC_SCB_MAX) {
3618 1.42 fvdl ahc->flags |= AHC_PAGESCBS;
3619 1.42 fvdl printf("%d/%d SCBs\n", ahc->scb_data->maxhscbs, AHC_SCB_MAX);
3620 1.42 fvdl } else {
3621 1.42 fvdl ahc->flags &= ~AHC_PAGESCBS;
3622 1.42 fvdl printf("%d SCBs\n", ahc->scb_data->maxhscbs);
3623 1.28 leo }
3624 1.6 mycroft
3625 1.6 mycroft #ifdef AHC_DEBUG
3626 1.42 fvdl if (ahc_debug & AHC_SHOWMISC) {
3627 1.42 fvdl printf("%s: hardware scb %d bytes; kernel scb %d bytes; "
3628 1.6 mycroft "ahc_dma %d bytes\n",
3629 1.6 mycroft ahc_name(ahc),
3630 1.42 fvdl sizeof(struct hardware_scb),
3631 1.42 fvdl sizeof(struct scb),
3632 1.6 mycroft sizeof(struct ahc_dma_seg));
3633 1.6 mycroft }
3634 1.6 mycroft #endif /* AHC_DEBUG */
3635 1.6 mycroft
3636 1.6 mycroft /* Set the SCSI Id, SXFRCTL0, SXFRCTL1, and SIMODE1, for both channels*/
3637 1.42 fvdl if (ahc->features & AHC_TWIN) {
3638 1.42 fvdl
3639 1.1 mycroft /*
3640 1.1 mycroft * The device is gated to channel B after a chip reset,
3641 1.1 mycroft * so set those values first
3642 1.1 mycroft */
3643 1.42 fvdl term = (ahc->flags & AHC_TERM_ENB_B) != 0 ? STPWEN : 0;
3644 1.42 fvdl if ((ahc->features & AHC_ULTRA2) != 0)
3645 1.42 fvdl ahc_outb(ahc, SCSIID_ULTRA2, ahc->our_id_b);
3646 1.6 mycroft else
3647 1.42 fvdl ahc_outb(ahc, SCSIID, ahc->our_id_b);
3648 1.42 fvdl scsi_conf = ahc_inb(ahc, SCSICONF + 1);
3649 1.42 fvdl ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL))
3650 1.42 fvdl |term|ENSTIMER|ACTNEGEN);
3651 1.42 fvdl ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
3652 1.42 fvdl ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN);
3653 1.42 fvdl
3654 1.42 fvdl if ((scsi_conf & RESET_SCSI) != 0
3655 1.42 fvdl && (ahc->flags & AHC_INITIATORMODE) != 0)
3656 1.42 fvdl ahc->flags |= AHC_RESET_BUS_B;
3657 1.6 mycroft
3658 1.1 mycroft /* Select Channel A */
3659 1.42 fvdl ahc_outb(ahc, SBLKCTL, ahc_inb(ahc, SBLKCTL) & ~SELBUSB);
3660 1.6 mycroft }
3661 1.42 fvdl term = (ahc->flags & AHC_TERM_ENB_A) != 0 ? STPWEN : 0;
3662 1.42 fvdl if ((ahc->features & AHC_ULTRA2) != 0)
3663 1.42 fvdl ahc_outb(ahc, SCSIID_ULTRA2, ahc->our_id);
3664 1.6 mycroft else
3665 1.42 fvdl ahc_outb(ahc, SCSIID, ahc->our_id);
3666 1.42 fvdl scsi_conf = ahc_inb(ahc, SCSICONF);
3667 1.42 fvdl ahc_outb(ahc, SXFRCTL1, (scsi_conf & (ENSPCHK|STIMESEL))
3668 1.42 fvdl |term
3669 1.42 fvdl |ENSTIMER|ACTNEGEN);
3670 1.42 fvdl ahc_outb(ahc, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
3671 1.42 fvdl ahc_outb(ahc, SXFRCTL0, DFON|SPIOEN);
3672 1.42 fvdl
3673 1.42 fvdl if ((scsi_conf & RESET_SCSI) != 0
3674 1.42 fvdl && (ahc->flags & AHC_INITIATORMODE) != 0)
3675 1.42 fvdl ahc->flags |= AHC_RESET_BUS_A;
3676 1.6 mycroft
3677 1.1 mycroft /*
3678 1.1 mycroft * Look at the information that board initialization or
3679 1.42 fvdl * the board bios has left us.
3680 1.1 mycroft */
3681 1.42 fvdl ultraenb = 0;
3682 1.42 fvdl tagenable = ALL_TARGETS_MASK;
3683 1.1 mycroft
3684 1.6 mycroft /* Grab the disconnection disable table and invert it for our needs */
3685 1.42 fvdl if (ahc->flags & AHC_USEDEFAULTS) {
3686 1.16 christos printf("%s: Host Adapter Bios disabled. Using default SCSI "
3687 1.6 mycroft "device parameters\n", ahc_name(ahc));
3688 1.42 fvdl ahc->flags |= AHC_EXTENDED_TRANS_A|AHC_EXTENDED_TRANS_B|
3689 1.42 fvdl AHC_TERM_ENB_A|AHC_TERM_ENB_B;
3690 1.42 fvdl discenable = ALL_TARGETS_MASK;
3691 1.42 fvdl if ((ahc->features & AHC_ULTRA) != 0)
3692 1.42 fvdl ultraenb = ALL_TARGETS_MASK;
3693 1.42 fvdl } else {
3694 1.42 fvdl discenable = ~((ahc_inb(ahc, DISC_DSB + 1) << 8)
3695 1.42 fvdl | ahc_inb(ahc, DISC_DSB));
3696 1.42 fvdl if ((ahc->features & (AHC_ULTRA|AHC_ULTRA2)) != 0)
3697 1.42 fvdl ultraenb = (ahc_inb(ahc, ULTRA_ENB + 1) << 8)
3698 1.42 fvdl | ahc_inb(ahc, ULTRA_ENB);
3699 1.6 mycroft }
3700 1.6 mycroft
3701 1.42 fvdl if ((ahc->features & (AHC_WIDE|AHC_TWIN)) == 0)
3702 1.6 mycroft max_targ = 7;
3703 1.6 mycroft
3704 1.42 fvdl for (i = 0; i <= max_targ; i++) {
3705 1.42 fvdl struct ahc_initiator_tinfo *tinfo;
3706 1.42 fvdl struct tmode_tstate *tstate;
3707 1.42 fvdl u_int our_id;
3708 1.42 fvdl u_int target_id;
3709 1.42 fvdl char channel;
3710 1.42 fvdl
3711 1.42 fvdl channel = 'A';
3712 1.42 fvdl our_id = ahc->our_id;
3713 1.42 fvdl target_id = i;
3714 1.42 fvdl if (i > 7 && (ahc->features & AHC_TWIN) != 0) {
3715 1.42 fvdl channel = 'B';
3716 1.42 fvdl our_id = ahc->our_id_b;
3717 1.42 fvdl target_id = i % 8;
3718 1.42 fvdl }
3719 1.42 fvdl tinfo = ahc_fetch_transinfo(ahc, channel, our_id,
3720 1.42 fvdl target_id, &tstate);
3721 1.42 fvdl /* Default to async narrow across the board */
3722 1.42 fvdl bzero(tinfo, sizeof(*tinfo));
3723 1.6 mycroft if (ahc->flags & AHC_USEDEFAULTS) {
3724 1.42 fvdl if ((ahc->features & AHC_WIDE) != 0)
3725 1.42 fvdl tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT;
3726 1.42 fvdl
3727 1.42 fvdl /*
3728 1.42 fvdl * These will be truncated when we determine the
3729 1.42 fvdl * connection type we have with the target.
3730 1.42 fvdl */
3731 1.42 fvdl tinfo->user.period = ahc_syncrates->period;
3732 1.42 fvdl tinfo->user.offset = ~0;
3733 1.42 fvdl } else {
3734 1.42 fvdl u_int scsirate;
3735 1.42 fvdl u_int16_t mask;
3736 1.42 fvdl
3737 1.6 mycroft /* Take the settings leftover in scratch RAM. */
3738 1.42 fvdl scsirate = ahc_inb(ahc, TARG_SCSIRATE + i);
3739 1.42 fvdl mask = (0x01 << i);
3740 1.42 fvdl if ((ahc->features & AHC_ULTRA2) != 0) {
3741 1.42 fvdl u_int offset;
3742 1.42 fvdl u_int maxsync;
3743 1.6 mycroft
3744 1.42 fvdl if ((scsirate & SOFS) == 0x0F) {
3745 1.42 fvdl /*
3746 1.42 fvdl * Haven't negotiated yet,
3747 1.42 fvdl * so the format is different.
3748 1.42 fvdl */
3749 1.42 fvdl scsirate = (scsirate & SXFR) >> 4
3750 1.42 fvdl | (ultraenb & mask)
3751 1.42 fvdl ? 0x08 : 0x0
3752 1.42 fvdl | (scsirate & WIDEXFER);
3753 1.42 fvdl offset = MAX_OFFSET_ULTRA2;
3754 1.42 fvdl } else
3755 1.42 fvdl offset = ahc_inb(ahc, TARG_OFFSET + i);
3756 1.42 fvdl maxsync = AHC_SYNCRATE_ULTRA2;
3757 1.42 fvdl if ((ahc->features & AHC_DT) != 0)
3758 1.42 fvdl maxsync = AHC_SYNCRATE_DT;
3759 1.42 fvdl tinfo->user.period =
3760 1.42 fvdl ahc_find_period(ahc, scsirate, maxsync);
3761 1.42 fvdl if (offset == 0)
3762 1.42 fvdl tinfo->user.period = 0;
3763 1.42 fvdl else
3764 1.42 fvdl tinfo->user.offset = ~0;
3765 1.42 fvdl } else if ((scsirate & SOFS) != 0) {
3766 1.42 fvdl tinfo->user.period =
3767 1.42 fvdl ahc_find_period(ahc, scsirate,
3768 1.42 fvdl (ultraenb & mask)
3769 1.42 fvdl ? AHC_SYNCRATE_ULTRA
3770 1.42 fvdl : AHC_SYNCRATE_FAST);
3771 1.42 fvdl if (tinfo->user.period != 0)
3772 1.42 fvdl tinfo->user.offset = ~0;
3773 1.6 mycroft }
3774 1.42 fvdl if ((scsirate & WIDEXFER) != 0
3775 1.42 fvdl && (ahc->features & AHC_WIDE) != 0)
3776 1.42 fvdl tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT;
3777 1.42 fvdl }
3778 1.42 fvdl tinfo->goal = tinfo->user; /* force negotiation */
3779 1.42 fvdl tstate->ultraenb = ultraenb;
3780 1.42 fvdl tstate->discenable = discenable;
3781 1.42 fvdl tstate->tagenable = 0; /* Wait until the XPT says its okay */
3782 1.49 fvdl tstate->tagdisable = 0;
3783 1.42 fvdl }
3784 1.42 fvdl ahc->user_discenable = discenable;
3785 1.42 fvdl ahc->user_tagenable = tagenable;
3786 1.42 fvdl
3787 1.42 fvdl /*
3788 1.42 fvdl * Tell the sequencer where it can find our arrays in memory.
3789 1.42 fvdl */
3790 1.42 fvdl physaddr = ahc->scb_data->hscb_busaddr;
3791 1.42 fvdl ahc_outb(ahc, HSCB_ADDR, physaddr & 0xFF);
3792 1.42 fvdl ahc_outb(ahc, HSCB_ADDR + 1, (physaddr >> 8) & 0xFF);
3793 1.42 fvdl ahc_outb(ahc, HSCB_ADDR + 2, (physaddr >> 16) & 0xFF);
3794 1.42 fvdl ahc_outb(ahc, HSCB_ADDR + 3, (physaddr >> 24) & 0xFF);
3795 1.42 fvdl
3796 1.42 fvdl physaddr = ahc->shared_data_busaddr;
3797 1.42 fvdl ahc_outb(ahc, SCBID_ADDR, physaddr & 0xFF);
3798 1.42 fvdl ahc_outb(ahc, SCBID_ADDR + 1, (physaddr >> 8) & 0xFF);
3799 1.42 fvdl ahc_outb(ahc, SCBID_ADDR + 2, (physaddr >> 16) & 0xFF);
3800 1.42 fvdl ahc_outb(ahc, SCBID_ADDR + 3, (physaddr >> 24) & 0xFF);
3801 1.42 fvdl
3802 1.42 fvdl /* Target mode incomding command fifo */
3803 1.42 fvdl physaddr += 3 * 256 * sizeof(u_int8_t);
3804 1.42 fvdl ahc_outb(ahc, TMODE_CMDADDR, physaddr & 0xFF);
3805 1.42 fvdl ahc_outb(ahc, TMODE_CMDADDR + 1, (physaddr >> 8) & 0xFF);
3806 1.42 fvdl ahc_outb(ahc, TMODE_CMDADDR + 2, (physaddr >> 16) & 0xFF);
3807 1.42 fvdl ahc_outb(ahc, TMODE_CMDADDR + 3, (physaddr >> 24) & 0xFF);
3808 1.42 fvdl
3809 1.42 fvdl /*
3810 1.42 fvdl * Initialize the group code to command length table.
3811 1.42 fvdl * This overrides the values in TARG_SCSIRATE, so only
3812 1.42 fvdl * setup the table after we have processed that information.
3813 1.42 fvdl */
3814 1.42 fvdl ahc_outb(ahc, CMDSIZE_TABLE, 5);
3815 1.42 fvdl ahc_outb(ahc, CMDSIZE_TABLE + 1, 9);
3816 1.42 fvdl ahc_outb(ahc, CMDSIZE_TABLE + 2, 9);
3817 1.42 fvdl ahc_outb(ahc, CMDSIZE_TABLE + 3, 0);
3818 1.42 fvdl ahc_outb(ahc, CMDSIZE_TABLE + 4, 15);
3819 1.42 fvdl ahc_outb(ahc, CMDSIZE_TABLE + 5, 11);
3820 1.42 fvdl ahc_outb(ahc, CMDSIZE_TABLE + 6, 0);
3821 1.42 fvdl ahc_outb(ahc, CMDSIZE_TABLE + 7, 0);
3822 1.42 fvdl
3823 1.42 fvdl /* Tell the sequencer of our initial queue positions */
3824 1.42 fvdl ahc_outb(ahc, KERNEL_QINPOS, 0);
3825 1.42 fvdl ahc_outb(ahc, QINPOS, 0);
3826 1.42 fvdl ahc_outb(ahc, QOUTPOS, 0);
3827 1.9 explorer
3828 1.6 mycroft #ifdef AHC_DEBUG
3829 1.42 fvdl if (ahc_debug & AHC_SHOWMISC)
3830 1.42 fvdl printf("DISCENABLE == 0x%x\nULTRAENB == 0x%x\n",
3831 1.42 fvdl discenable, ultraenb);
3832 1.6 mycroft #endif
3833 1.1 mycroft
3834 1.42 fvdl /* Don't have any special messages to send to targets */
3835 1.42 fvdl ahc_outb(ahc, TARGET_MSG_REQUEST, 0);
3836 1.42 fvdl ahc_outb(ahc, TARGET_MSG_REQUEST + 1, 0);
3837 1.1 mycroft
3838 1.1 mycroft /*
3839 1.42 fvdl * Use the built in queue management registers
3840 1.42 fvdl * if they are available.
3841 1.1 mycroft */
3842 1.42 fvdl if ((ahc->features & AHC_QUEUE_REGS) != 0) {
3843 1.42 fvdl ahc_outb(ahc, QOFF_CTLSTA, SCB_QSIZE_256);
3844 1.42 fvdl ahc_outb(ahc, SDSCB_QOFF, 0);
3845 1.42 fvdl ahc_outb(ahc, SNSCB_QOFF, 0);
3846 1.42 fvdl ahc_outb(ahc, HNSCB_QOFF, 0);
3847 1.42 fvdl }
3848 1.1 mycroft
3849 1.6 mycroft
3850 1.1 mycroft /* We don't have any waiting selections */
3851 1.42 fvdl ahc_outb(ahc, WAITING_SCBH, SCB_LIST_NULL);
3852 1.6 mycroft
3853 1.6 mycroft /* Our disconnection list is empty too */
3854 1.42 fvdl ahc_outb(ahc, DISCONNECTED_SCBH, SCB_LIST_NULL);
3855 1.6 mycroft
3856 1.6 mycroft /* Message out buffer starts empty */
3857 1.42 fvdl ahc_outb(ahc, MSG_OUT, MSG_NOOP);
3858 1.42 fvdl
3859 1.42 fvdl /*
3860 1.42 fvdl * Setup the allowed SCSI Sequences based on operational mode.
3861 1.42 fvdl * If we are a target, we'll enalbe select in operations once
3862 1.42 fvdl * we've had a lun enabled.
3863 1.42 fvdl */
3864 1.42 fvdl scsiseq_template = ENSELO|ENAUTOATNO|ENAUTOATNP;
3865 1.42 fvdl if ((ahc->flags & AHC_INITIATORMODE) != 0)
3866 1.42 fvdl scsiseq_template |= ENRSELI;
3867 1.42 fvdl ahc_outb(ahc, SCSISEQ_TEMPLATE, scsiseq_template);
3868 1.6 mycroft
3869 1.6 mycroft /*
3870 1.6 mycroft * Load the Sequencer program and Enable the adapter
3871 1.6 mycroft * in "fast" mode.
3872 1.6 mycroft */
3873 1.42 fvdl #ifdef AHC_DEBUG
3874 1.42 fvdl printf("%s: Downloading Sequencer Program...",
3875 1.42 fvdl ahc_name(ahc));
3876 1.13 thorpej #endif
3877 1.6 mycroft
3878 1.6 mycroft ahc_loadseq(ahc);
3879 1.6 mycroft
3880 1.42 fvdl /* We have to wait until after any system dumps... */
3881 1.42 fvdl shutdownhook_establish(ahc_shutdown, ahc);
3882 1.6 mycroft
3883 1.1 mycroft return (0);
3884 1.1 mycroft }
3885 1.1 mycroft
3886 1.52 fvdl static int
3887 1.52 fvdl ahc_ioctl(struct scsipi_link *sc_link, u_long cmd, caddr_t addr, int flag,
3888 1.52 fvdl struct proc *p)
3889 1.52 fvdl {
3890 1.52 fvdl struct ahc_softc *ahc = sc_link->adapter_softc;
3891 1.52 fvdl char channel;
3892 1.52 fvdl int s, ret = ENOTTY;
3893 1.52 fvdl
3894 1.52 fvdl switch (cmd) {
3895 1.52 fvdl case SCBUSIORESET:
3896 1.52 fvdl channel = SIM_CHANNEL(ahc, sc_link);
3897 1.52 fvdl s = splbio();
3898 1.52 fvdl ahc_reset_channel(ahc, channel, TRUE);
3899 1.52 fvdl splx(s);
3900 1.52 fvdl ret = 0;
3901 1.52 fvdl break;
3902 1.52 fvdl default:
3903 1.52 fvdl }
3904 1.52 fvdl
3905 1.52 fvdl return ret;
3906 1.52 fvdl }
3907 1.52 fvdl
3908 1.52 fvdl
3909 1.1 mycroft /*
3910 1.42 fvdl * XXX fvdl the busy_tcl checks and settings should only be done
3911 1.42 fvdl * for the non-tagged queueing case, but we don't do tagged queueing
3912 1.42 fvdl * yet, so..
3913 1.1 mycroft */
3914 1.6 mycroft static int32_t
3915 1.42 fvdl ahc_action(struct scsipi_xfer *xs)
3916 1.1 mycroft {
3917 1.42 fvdl struct scsipi_xfer *first_xs, *next_xs = NULL;
3918 1.42 fvdl struct ahc_softc *ahc;
3919 1.42 fvdl struct scb *scb;
3920 1.42 fvdl struct hardware_scb *hscb;
3921 1.42 fvdl struct ahc_initiator_tinfo *tinfo;
3922 1.42 fvdl struct tmode_tstate *tstate;
3923 1.42 fvdl u_int target_id;
3924 1.42 fvdl u_int our_id;
3925 1.42 fvdl int s, tcl;
3926 1.42 fvdl u_int16_t mask;
3927 1.52 fvdl char channel;
3928 1.42 fvdl int dontqueue = 0, fromqueue = 0;
3929 1.42 fvdl
3930 1.42 fvdl SC_DEBUG(xs->sc_link, SDEV_DB3, ("ahc_action\n"));
3931 1.18 thorpej
3932 1.42 fvdl ahc = (struct ahc_softc *)xs->sc_link->adapter_softc;
3933 1.18 thorpej
3934 1.18 thorpej /* must protect the queue */
3935 1.18 thorpej s = splbio();
3936 1.18 thorpej
3937 1.34 thorpej if (xs == TAILQ_FIRST(&ahc->sc_q)) {
3938 1.42 fvdl /*
3939 1.42 fvdl * Called from ahc_done. Calling with the first entry in
3940 1.42 fvdl * the queue is really just a way of seeing where we're
3941 1.42 fvdl * called from. Now, find the first eligible SCB to send,
3942 1.42 fvdl * e.g. one which will be accepted immediately.
3943 1.42 fvdl */
3944 1.42 fvdl
3945 1.42 fvdl if (ahc->queue_blocked) {
3946 1.42 fvdl splx(s);
3947 1.42 fvdl return (TRY_AGAIN_LATER);
3948 1.42 fvdl }
3949 1.42 fvdl
3950 1.42 fvdl xs = ahc_first_xs(ahc);
3951 1.42 fvdl if (xs == NULL) {
3952 1.42 fvdl splx(s);
3953 1.42 fvdl return (TRY_AGAIN_LATER);
3954 1.42 fvdl }
3955 1.42 fvdl
3956 1.42 fvdl next_xs = TAILQ_NEXT(xs, adapter_q);
3957 1.34 thorpej TAILQ_REMOVE(&ahc->sc_q, xs, adapter_q);
3958 1.18 thorpej fromqueue = 1;
3959 1.18 thorpej goto get_scb;
3960 1.18 thorpej }
3961 1.18 thorpej
3962 1.42 fvdl /*
3963 1.42 fvdl * If no new requests are accepted, just insert into the
3964 1.42 fvdl * private queue to wait for our turn.
3965 1.42 fvdl */
3966 1.42 fvdl tcl = XS_TCL(ahc, xs);
3967 1.45 fvdl
3968 1.42 fvdl if (ahc->queue_blocked ||
3969 1.42 fvdl ahc->devqueue_blocked[xs->sc_link->scsipi_scsi.target] ||
3970 1.51 fvdl (!ahc_istagged_device(ahc, xs, 0) &&
3971 1.45 fvdl ahc_index_busy_tcl(ahc, tcl, FALSE) != SCB_LIST_NULL)) {
3972 1.42 fvdl if (dontqueue) {
3973 1.42 fvdl splx(s);
3974 1.42 fvdl xs->error = XS_DRIVER_STUFFUP;
3975 1.42 fvdl return TRY_AGAIN_LATER;
3976 1.42 fvdl }
3977 1.42 fvdl TAILQ_INSERT_TAIL(&ahc->sc_q, xs, adapter_q);
3978 1.42 fvdl splx(s);
3979 1.42 fvdl return SUCCESSFULLY_QUEUED;
3980 1.42 fvdl }
3981 1.42 fvdl
3982 1.42 fvdl first_xs = ahc_first_xs(ahc);
3983 1.42 fvdl
3984 1.21 mikel /* determine safety of software queueing */
3985 1.37 thorpej dontqueue = xs->xs_control & XS_CTL_POLL;
3986 1.18 thorpej
3987 1.18 thorpej /*
3988 1.18 thorpej * Handle situations where there's already entries in the
3989 1.18 thorpej * queue.
3990 1.18 thorpej */
3991 1.42 fvdl if (first_xs != NULL) {
3992 1.18 thorpej /*
3993 1.18 thorpej * If we can't queue, we have to abort, since
3994 1.18 thorpej * we have to preserve order.
3995 1.18 thorpej */
3996 1.18 thorpej if (dontqueue) {
3997 1.18 thorpej splx(s);
3998 1.18 thorpej xs->error = XS_DRIVER_STUFFUP;
3999 1.18 thorpej return (TRY_AGAIN_LATER);
4000 1.18 thorpej }
4001 1.18 thorpej
4002 1.18 thorpej /*
4003 1.18 thorpej * Swap with the first queue entry.
4004 1.18 thorpej */
4005 1.34 thorpej TAILQ_INSERT_TAIL(&ahc->sc_q, xs, adapter_q);
4006 1.42 fvdl xs = first_xs;
4007 1.42 fvdl next_xs = TAILQ_NEXT(xs, adapter_q);
4008 1.34 thorpej TAILQ_REMOVE(&ahc->sc_q, xs, adapter_q);
4009 1.18 thorpej fromqueue = 1;
4010 1.42 fvdl
4011 1.18 thorpej }
4012 1.18 thorpej
4013 1.42 fvdl get_scb:
4014 1.42 fvdl
4015 1.42 fvdl target_id = xs->sc_link->scsipi_scsi.target;
4016 1.42 fvdl our_id = SIM_SCSI_ID(ahc, xs->sc_link);
4017 1.42 fvdl
4018 1.9 explorer /*
4019 1.42 fvdl * get an scb to use.
4020 1.42 fvdl */
4021 1.42 fvdl if ((scb = ahcgetscb(ahc)) == NULL) {
4022 1.42 fvdl
4023 1.18 thorpej if (dontqueue) {
4024 1.18 thorpej splx(s);
4025 1.18 thorpej xs->error = XS_DRIVER_STUFFUP;
4026 1.18 thorpej return (TRY_AGAIN_LATER);
4027 1.18 thorpej }
4028 1.18 thorpej
4029 1.18 thorpej /*
4030 1.42 fvdl * If we were pulled off the queue, put ourselves
4031 1.42 fvdl * back to where we came from, otherwise tack ourselves
4032 1.42 fvdl * onto the end.
4033 1.42 fvdl */
4034 1.42 fvdl if (fromqueue && next_xs != NULL)
4035 1.42 fvdl TAILQ_INSERT_BEFORE(xs, next_xs, adapter_q);
4036 1.42 fvdl else
4037 1.42 fvdl TAILQ_INSERT_TAIL(&ahc->sc_q, xs, adapter_q);
4038 1.42 fvdl
4039 1.42 fvdl splx(s);
4040 1.42 fvdl return (SUCCESSFULLY_QUEUED);
4041 1.42 fvdl }
4042 1.42 fvdl
4043 1.42 fvdl tcl = XS_TCL(ahc, xs);
4044 1.42 fvdl
4045 1.42 fvdl #ifdef DIAGNOSTIC
4046 1.51 fvdl if (!ahc_istagged_device(ahc, xs, 0) &&
4047 1.45 fvdl ahc_index_busy_tcl(ahc, tcl, FALSE) != SCB_LIST_NULL)
4048 1.42 fvdl panic("ahc: queuing for busy target");
4049 1.42 fvdl #endif
4050 1.42 fvdl
4051 1.42 fvdl scb->xs = xs;
4052 1.42 fvdl hscb = scb->hscb;
4053 1.42 fvdl hscb->tcl = tcl;
4054 1.42 fvdl
4055 1.51 fvdl if (ahc_istagged_device(ahc, xs, 0))
4056 1.45 fvdl scb->hscb->control |= MSG_SIMPLE_Q_TAG;
4057 1.45 fvdl else
4058 1.45 fvdl ahc_busy_tcl(ahc, scb);
4059 1.42 fvdl
4060 1.42 fvdl splx(s);
4061 1.52 fvdl
4062 1.52 fvdl channel = SIM_CHANNEL(ahc, xs->sc_link);
4063 1.52 fvdl if (ahc->inited_channels[channel - 'A'] == 0) {
4064 1.54 fvdl if ((channel == 'A' && (ahc->flags & AHC_RESET_BUS_A)) ||
4065 1.54 fvdl (channel == 'B' && (ahc->flags & AHC_RESET_BUS_B))) {
4066 1.54 fvdl s = splbio();
4067 1.54 fvdl ahc_reset_channel(ahc, channel, TRUE);
4068 1.54 fvdl splx(s);
4069 1.54 fvdl }
4070 1.52 fvdl ahc->inited_channels[channel - 'A'] = 1;
4071 1.52 fvdl }
4072 1.52 fvdl
4073 1.42 fvdl /*
4074 1.42 fvdl * Put all the arguments for the xfer in the scb
4075 1.42 fvdl */
4076 1.42 fvdl
4077 1.42 fvdl mask = SCB_TARGET_MASK(scb);
4078 1.42 fvdl tinfo = ahc_fetch_transinfo(ahc, SIM_CHANNEL(ahc, xs->sc_link), our_id,
4079 1.42 fvdl target_id, &tstate);
4080 1.42 fvdl if (ahc->inited_targets[target_id] == 0) {
4081 1.42 fvdl struct ahc_devinfo devinfo;
4082 1.42 fvdl
4083 1.42 fvdl s = splbio();
4084 1.42 fvdl ahc_compile_devinfo(&devinfo, our_id, target_id,
4085 1.42 fvdl xs->sc_link->scsipi_scsi.lun, SIM_CHANNEL(ahc, xs->sc_link),
4086 1.42 fvdl ROLE_INITIATOR);
4087 1.42 fvdl ahc_update_target_msg_request(ahc, &devinfo, tinfo, TRUE,
4088 1.42 fvdl FALSE);
4089 1.42 fvdl ahc->inited_targets[target_id] = 1;
4090 1.42 fvdl splx(s);
4091 1.42 fvdl }
4092 1.42 fvdl
4093 1.42 fvdl hscb->scsirate = tinfo->scsirate;
4094 1.42 fvdl hscb->scsioffset = tinfo->current.offset;
4095 1.42 fvdl if ((tstate->ultraenb & mask) != 0)
4096 1.42 fvdl hscb->control |= ULTRAENB;
4097 1.42 fvdl
4098 1.42 fvdl if ((tstate->discenable & mask) != 0)
4099 1.42 fvdl hscb->control |= DISCENB;
4100 1.55 fvdl
4101 1.55 fvdl if (xs->xs_status & XS_STS_DEBUG) {
4102 1.55 fvdl scsi_print_addr(xs->sc_link);
4103 1.55 fvdl printf("redoing command that caused queue full\n");
4104 1.55 fvdl }
4105 1.42 fvdl
4106 1.42 fvdl if (xs->xs_control & XS_CTL_RESET) {
4107 1.48 thorpej hscb->cmdpointer = 0;
4108 1.42 fvdl scb->flags |= SCB_DEVICE_RESET;
4109 1.42 fvdl hscb->control |= MK_MESSAGE;
4110 1.42 fvdl return ahc_execute_scb(scb, NULL, 0);
4111 1.42 fvdl }
4112 1.42 fvdl
4113 1.42 fvdl return ahc_setup_data(ahc, xs, scb);
4114 1.42 fvdl }
4115 1.42 fvdl
4116 1.42 fvdl static int
4117 1.42 fvdl ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
4118 1.42 fvdl {
4119 1.42 fvdl struct scb *scb;
4120 1.42 fvdl struct scsipi_xfer *xs;
4121 1.42 fvdl struct ahc_softc *ahc;
4122 1.42 fvdl int s;
4123 1.42 fvdl
4124 1.42 fvdl scb = (struct scb *)arg;
4125 1.42 fvdl xs = scb->xs;
4126 1.42 fvdl ahc = (struct ahc_softc *)xs->sc_link->adapter_softc;
4127 1.42 fvdl
4128 1.42 fvdl
4129 1.42 fvdl if (nsegments != 0) {
4130 1.42 fvdl struct ahc_dma_seg *sg;
4131 1.42 fvdl bus_dma_segment_t *end_seg;
4132 1.42 fvdl int op;
4133 1.42 fvdl
4134 1.42 fvdl end_seg = dm_segs + nsegments;
4135 1.42 fvdl
4136 1.42 fvdl /* Copy the first SG into the data pointer area */
4137 1.42 fvdl scb->hscb->data = dm_segs->ds_addr;
4138 1.42 fvdl scb->hscb->datalen = dm_segs->ds_len;
4139 1.42 fvdl
4140 1.42 fvdl /* Copy the segments into our SG list */
4141 1.42 fvdl sg = scb->sg_list;
4142 1.42 fvdl while (dm_segs < end_seg) {
4143 1.42 fvdl sg->addr = dm_segs->ds_addr;
4144 1.42 fvdl sg->len = dm_segs->ds_len;
4145 1.42 fvdl ahc_swap_sg(sg);
4146 1.42 fvdl sg++;
4147 1.42 fvdl dm_segs++;
4148 1.42 fvdl }
4149 1.42 fvdl
4150 1.42 fvdl /* Note where to find the SG entries in bus space */
4151 1.42 fvdl scb->hscb->SG_pointer = scb->sg_list_phys;
4152 1.42 fvdl
4153 1.42 fvdl if (xs->xs_control & XS_CTL_DATA_IN)
4154 1.42 fvdl op = BUS_DMASYNC_PREREAD;
4155 1.34 thorpej else
4156 1.42 fvdl op = BUS_DMASYNC_PREWRITE;
4157 1.42 fvdl
4158 1.42 fvdl bus_dmamap_sync(ahc->parent_dmat, scb->dmamap, 0,
4159 1.42 fvdl scb->dmamap->dm_mapsize, op);
4160 1.18 thorpej
4161 1.42 fvdl } else {
4162 1.42 fvdl scb->hscb->SG_pointer = 0;
4163 1.42 fvdl scb->hscb->data = 0;
4164 1.42 fvdl scb->hscb->datalen = 0;
4165 1.9 explorer }
4166 1.42 fvdl
4167 1.42 fvdl scb->sg_count = scb->hscb->SG_count = nsegments;
4168 1.18 thorpej
4169 1.42 fvdl s = splbio();
4170 1.18 thorpej
4171 1.9 explorer /*
4172 1.42 fvdl * Last time we need to check if this SCB needs to
4173 1.42 fvdl * be aborted.
4174 1.9 explorer */
4175 1.42 fvdl if (xs->xs_status & XS_STS_DONE) {
4176 1.51 fvdl if (!ahc_istagged_device(ahc, xs, 0))
4177 1.45 fvdl ahc_index_busy_tcl(ahc, scb->hscb->tcl, TRUE);
4178 1.42 fvdl if (nsegments != 0)
4179 1.42 fvdl bus_dmamap_unload(ahc->parent_dmat, scb->dmamap);
4180 1.42 fvdl ahcfreescb(ahc, scb);
4181 1.42 fvdl splx(s);
4182 1.42 fvdl return (COMPLETE);
4183 1.42 fvdl }
4184 1.6 mycroft
4185 1.42 fvdl #ifdef DIAGNOSTIC
4186 1.42 fvdl if (scb->sg_count > 255)
4187 1.42 fvdl panic("ahc bad sg_count");
4188 1.29 leo #endif
4189 1.6 mycroft
4190 1.42 fvdl ahc_swap_hscb(scb->hscb);
4191 1.42 fvdl
4192 1.42 fvdl LIST_INSERT_HEAD(&ahc->pending_ccbs, scb, plinks);
4193 1.6 mycroft
4194 1.42 fvdl scb->flags |= SCB_ACTIVE;
4195 1.6 mycroft
4196 1.42 fvdl if (!(xs->xs_control & XS_CTL_POLL))
4197 1.44 thorpej callout_reset(&scb->xs->xs_callout, (xs->timeout * hz) / 1000,
4198 1.44 thorpej ahc_timeout, scb);
4199 1.42 fvdl
4200 1.42 fvdl if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
4201 1.42 fvdl #if 0
4202 1.42 fvdl printf("Continueing Immediate Command %d:%d\n",
4203 1.42 fvdl xs->sc_link->scsipi_scsi.target,
4204 1.42 fvdl xs->sc_link->scsipi_scsi.lun);
4205 1.42 fvdl #endif
4206 1.42 fvdl pause_sequencer(ahc);
4207 1.42 fvdl if ((ahc->flags & AHC_PAGESCBS) == 0)
4208 1.42 fvdl ahc_outb(ahc, SCBPTR, scb->hscb->tag);
4209 1.42 fvdl ahc_outb(ahc, SCB_TAG, scb->hscb->tag);
4210 1.42 fvdl ahc_outb(ahc, RETURN_1, CONT_MSG_LOOP);
4211 1.42 fvdl unpause_sequencer(ahc);
4212 1.42 fvdl } else {
4213 1.6 mycroft
4214 1.42 fvdl #if 0
4215 1.42 fvdl printf("tag %x at qpos %u vaddr %p paddr 0x%lx\n",
4216 1.42 fvdl scb->hscb->tag, ahc->qinfifonext,
4217 1.42 fvdl &ahc->qinfifo[ahc->qinfifonext],
4218 1.42 fvdl ahc->shared_data_busaddr + 1024 + ahc->qinfifonext);
4219 1.28 leo #endif
4220 1.28 leo
4221 1.42 fvdl ahc->qinfifo[ahc->qinfifonext++] = scb->hscb->tag;
4222 1.42 fvdl
4223 1.42 fvdl bus_dmamap_sync(ahc->parent_dmat, ahc->shared_data_dmamap,
4224 1.42 fvdl QINFIFO_OFFSET * 256, 256, BUS_DMASYNC_PREWRITE);
4225 1.42 fvdl
4226 1.42 fvdl if ((ahc->features & AHC_QUEUE_REGS) != 0) {
4227 1.42 fvdl ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext);
4228 1.42 fvdl } else {
4229 1.42 fvdl pause_sequencer(ahc);
4230 1.42 fvdl ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext);
4231 1.42 fvdl unpause_sequencer(ahc);
4232 1.42 fvdl }
4233 1.42 fvdl }
4234 1.1 mycroft
4235 1.6 mycroft #ifdef AHC_DEBUG
4236 1.42 fvdl if (ahc_debug & AHC_SHOWCMDS) {
4237 1.42 fvdl scsi_print_addr(xs->sc_link);
4238 1.42 fvdl printf("opcode %d tag %x len %d flags %x control %x fpos %u"
4239 1.42 fvdl " rate %x\n",
4240 1.42 fvdl xs->cmdstore.opcode, scb->hscb->tag, scb->hscb->datalen,
4241 1.42 fvdl scb->flags, scb->hscb->control, ahc->qinfifonext,
4242 1.42 fvdl scb->hscb->scsirate);
4243 1.42 fvdl }
4244 1.1 mycroft #endif
4245 1.1 mycroft
4246 1.42 fvdl if (!(xs->xs_control & XS_CTL_POLL)) {
4247 1.1 mycroft splx(s);
4248 1.1 mycroft return (SUCCESSFULLY_QUEUED);
4249 1.1 mycroft }
4250 1.1 mycroft /*
4251 1.6 mycroft * If we can't use interrupts, poll for completion
4252 1.1 mycroft */
4253 1.6 mycroft SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_poll\n"));
4254 1.6 mycroft do {
4255 1.6 mycroft if (ahc_poll(ahc, xs->timeout)) {
4256 1.37 thorpej if (!(xs->xs_control & XS_CTL_SILENT))
4257 1.16 christos printf("cmd fail\n");
4258 1.1 mycroft ahc_timeout(scb);
4259 1.6 mycroft break;
4260 1.6 mycroft }
4261 1.37 thorpej } while (!(xs->xs_status & XS_STS_DONE));
4262 1.42 fvdl splx(s);
4263 1.1 mycroft return (COMPLETE);
4264 1.1 mycroft }
4265 1.1 mycroft
4266 1.42 fvdl static int
4267 1.42 fvdl ahc_poll(struct ahc_softc *ahc, int wait)
4268 1.42 fvdl {
4269 1.42 fvdl while (--wait) {
4270 1.42 fvdl DELAY(1000);
4271 1.42 fvdl if (ahc_inb(ahc, INTSTAT) & INT_PEND)
4272 1.42 fvdl break;
4273 1.42 fvdl }
4274 1.42 fvdl
4275 1.42 fvdl if (wait == 0) {
4276 1.42 fvdl printf("%s: board is not responding\n", ahc_name(ahc));
4277 1.42 fvdl return (EIO);
4278 1.42 fvdl }
4279 1.42 fvdl
4280 1.42 fvdl ahc_intr((void *)ahc);
4281 1.42 fvdl return (0);
4282 1.42 fvdl }
4283 1.42 fvdl
4284 1.42 fvdl static int
4285 1.42 fvdl ahc_setup_data(struct ahc_softc *ahc, struct scsipi_xfer *xs,
4286 1.42 fvdl struct scb *scb)
4287 1.42 fvdl {
4288 1.42 fvdl struct hardware_scb *hscb;
4289 1.42 fvdl
4290 1.42 fvdl hscb = scb->hscb;
4291 1.42 fvdl xs->resid = xs->status = 0;
4292 1.42 fvdl
4293 1.42 fvdl hscb->cmdlen = xs->cmdlen;
4294 1.42 fvdl memcpy(hscb->cmdstore, xs->cmd, xs->cmdlen);
4295 1.42 fvdl hscb->cmdpointer = hscb->cmdstore_busaddr;
4296 1.42 fvdl
4297 1.42 fvdl /* Only use S/G if there is a transfer */
4298 1.42 fvdl if (xs->datalen) {
4299 1.42 fvdl int error;
4300 1.42 fvdl
4301 1.42 fvdl error = bus_dmamap_load(ahc->parent_dmat,
4302 1.42 fvdl scb->dmamap, xs->data,
4303 1.42 fvdl xs->datalen, NULL,
4304 1.42 fvdl (xs->xs_control & XS_CTL_NOSLEEP) ?
4305 1.42 fvdl BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
4306 1.42 fvdl if (error) {
4307 1.51 fvdl if (!ahc_istagged_device(ahc, xs, 0))
4308 1.45 fvdl ahc_index_busy_tcl(ahc, hscb->tcl, TRUE);
4309 1.42 fvdl return (TRY_AGAIN_LATER); /* XXX fvdl */
4310 1.42 fvdl }
4311 1.42 fvdl error = ahc_execute_scb(scb,
4312 1.42 fvdl scb->dmamap->dm_segs,
4313 1.42 fvdl scb->dmamap->dm_nsegs);
4314 1.42 fvdl return error;
4315 1.42 fvdl } else {
4316 1.42 fvdl return ahc_execute_scb(scb, NULL, 0);
4317 1.42 fvdl }
4318 1.42 fvdl }
4319 1.42 fvdl
4320 1.42 fvdl static void
4321 1.42 fvdl ahc_freeze_devq(struct ahc_softc *ahc, struct scsipi_link *sc_link)
4322 1.42 fvdl {
4323 1.42 fvdl int target;
4324 1.42 fvdl char channel;
4325 1.42 fvdl int lun;
4326 1.42 fvdl
4327 1.42 fvdl target = sc_link->scsipi_scsi.target;
4328 1.42 fvdl lun = sc_link->scsipi_scsi.lun;
4329 1.42 fvdl channel = sc_link->scsipi_scsi.channel;
4330 1.42 fvdl
4331 1.42 fvdl ahc_search_qinfifo(ahc, target, channel, lun,
4332 1.42 fvdl /*tag*/SCB_LIST_NULL, ROLE_UNKNOWN,
4333 1.42 fvdl SCB_REQUEUE, SEARCH_COMPLETE);
4334 1.42 fvdl }
4335 1.1 mycroft
4336 1.6 mycroft static void
4337 1.42 fvdl ahcallocscbs(struct ahc_softc *ahc)
4338 1.1 mycroft {
4339 1.42 fvdl struct scb_data *scb_data;
4340 1.42 fvdl struct scb *next_scb;
4341 1.42 fvdl struct sg_map_node *sg_map;
4342 1.42 fvdl bus_addr_t physaddr;
4343 1.42 fvdl struct ahc_dma_seg *segs;
4344 1.42 fvdl int newcount;
4345 1.42 fvdl int i;
4346 1.42 fvdl
4347 1.42 fvdl scb_data = ahc->scb_data;
4348 1.42 fvdl if (scb_data->numscbs >= AHC_SCB_MAX)
4349 1.42 fvdl /* Can't allocate any more */
4350 1.42 fvdl return;
4351 1.42 fvdl
4352 1.42 fvdl next_scb = &scb_data->scbarray[scb_data->numscbs];
4353 1.42 fvdl
4354 1.42 fvdl sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT);
4355 1.42 fvdl
4356 1.42 fvdl if (sg_map == NULL)
4357 1.42 fvdl return;
4358 1.42 fvdl
4359 1.42 fvdl if (ahc_createdmamem(ahc->parent_dmat, PAGE_SIZE, ahc->sc_dmaflags,
4360 1.42 fvdl &sg_map->sg_dmamap,
4361 1.42 fvdl (caddr_t *)&sg_map->sg_vaddr, &sg_map->sg_physaddr,
4362 1.42 fvdl &sg_map->sg_dmasegs, &sg_map->sg_nseg, ahc_name(ahc),
4363 1.42 fvdl "SG space") < 0) {
4364 1.42 fvdl free(sg_map, M_DEVBUF);
4365 1.42 fvdl return;
4366 1.42 fvdl }
4367 1.1 mycroft
4368 1.42 fvdl SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links);
4369 1.42 fvdl
4370 1.42 fvdl segs = sg_map->sg_vaddr;
4371 1.42 fvdl physaddr = sg_map->sg_physaddr;
4372 1.1 mycroft
4373 1.42 fvdl newcount = (PAGE_SIZE / (AHC_NSEG * sizeof(struct ahc_dma_seg)));
4374 1.42 fvdl for (i = 0; scb_data->numscbs < AHC_SCB_MAX && i < newcount; i++) {
4375 1.42 fvdl int error;
4376 1.9 explorer
4377 1.42 fvdl next_scb->sg_list = segs;
4378 1.42 fvdl /*
4379 1.42 fvdl * The sequencer always starts with the second entry.
4380 1.42 fvdl * The first entry is embedded in the scb.
4381 1.42 fvdl */
4382 1.42 fvdl next_scb->sg_list_phys = physaddr + sizeof(struct ahc_dma_seg);
4383 1.42 fvdl next_scb->flags = SCB_FREE;
4384 1.42 fvdl error = bus_dmamap_create(ahc->parent_dmat,
4385 1.42 fvdl AHC_MAXTRANSFER_SIZE, AHC_NSEG, MAXBSIZE, 0,
4386 1.42 fvdl BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW|ahc->sc_dmaflags,
4387 1.42 fvdl &next_scb->dmamap);
4388 1.42 fvdl if (error != 0)
4389 1.42 fvdl break;
4390 1.42 fvdl next_scb->hscb = &scb_data->hscbs[scb_data->numscbs];
4391 1.42 fvdl next_scb->hscb->tag = ahc->scb_data->numscbs;
4392 1.42 fvdl next_scb->hscb->cmdstore_busaddr =
4393 1.42 fvdl ahc_hscb_busaddr(ahc, next_scb->hscb->tag)
4394 1.42 fvdl + offsetof(struct hardware_scb, cmdstore);
4395 1.42 fvdl next_scb->hscb->cmdstore_busaddr =
4396 1.42 fvdl htole32(next_scb->hscb->cmdstore_busaddr);
4397 1.42 fvdl SLIST_INSERT_HEAD(&ahc->scb_data->free_scbs, next_scb, links);
4398 1.42 fvdl segs += AHC_NSEG;
4399 1.42 fvdl physaddr += (AHC_NSEG * sizeof(struct ahc_dma_seg));
4400 1.42 fvdl next_scb++;
4401 1.42 fvdl ahc->scb_data->numscbs++;
4402 1.6 mycroft }
4403 1.42 fvdl #ifdef AHC_DEBUG
4404 1.42 fvdl if (ahc_debug & AHC_SHOWSCBALLOC)
4405 1.42 fvdl printf("%s: allocated %d new SCBs count now %d\n",
4406 1.42 fvdl ahc_name(ahc), i - 1, ahc->scb_data->numscbs);
4407 1.42 fvdl #endif
4408 1.42 fvdl }
4409 1.42 fvdl
4410 1.42 fvdl #ifdef AHC_DUMP_SEQ
4411 1.42 fvdl static void
4412 1.42 fvdl ahc_dumpseq(struct ahc_softc* ahc)
4413 1.42 fvdl {
4414 1.42 fvdl int i;
4415 1.42 fvdl int max_prog;
4416 1.42 fvdl
4417 1.42 fvdl if ((ahc->chip & AHC_BUS_MASK) < AHC_PCI)
4418 1.42 fvdl max_prog = 448;
4419 1.42 fvdl else if ((ahc->features & AHC_ULTRA2) != 0)
4420 1.42 fvdl max_prog = 768;
4421 1.42 fvdl else
4422 1.42 fvdl max_prog = 512;
4423 1.42 fvdl
4424 1.42 fvdl ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
4425 1.42 fvdl ahc_outb(ahc, SEQADDR0, 0);
4426 1.42 fvdl ahc_outb(ahc, SEQADDR1, 0);
4427 1.42 fvdl for (i = 0; i < max_prog; i++) {
4428 1.42 fvdl u_int8_t ins_bytes[4];
4429 1.42 fvdl
4430 1.42 fvdl ahc_insb(ahc, SEQRAM, ins_bytes, 4);
4431 1.42 fvdl printf("0x%08x\n", ins_bytes[0] << 24
4432 1.42 fvdl | ins_bytes[1] << 16
4433 1.42 fvdl | ins_bytes[2] << 8
4434 1.42 fvdl | ins_bytes[3]);
4435 1.6 mycroft }
4436 1.42 fvdl }
4437 1.42 fvdl #endif
4438 1.42 fvdl
4439 1.42 fvdl static void
4440 1.42 fvdl ahc_loadseq(struct ahc_softc *ahc)
4441 1.42 fvdl {
4442 1.42 fvdl struct patch *cur_patch;
4443 1.42 fvdl int i;
4444 1.42 fvdl int downloaded;
4445 1.42 fvdl int skip_addr;
4446 1.42 fvdl u_int8_t download_consts[4];
4447 1.42 fvdl
4448 1.42 fvdl /* Setup downloadable constant table */
4449 1.42 fvdl #if 0
4450 1.42 fvdl /* No downloaded constants are currently defined. */
4451 1.42 fvdl download_consts[TMODE_NUMCMDS] = ahc->num_targetcmds;
4452 1.42 fvdl #endif
4453 1.42 fvdl
4454 1.42 fvdl cur_patch = patches;
4455 1.42 fvdl downloaded = 0;
4456 1.42 fvdl skip_addr = 0;
4457 1.42 fvdl ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
4458 1.42 fvdl ahc_outb(ahc, SEQADDR0, 0);
4459 1.42 fvdl ahc_outb(ahc, SEQADDR1, 0);
4460 1.42 fvdl
4461 1.42 fvdl for (i = 0; i < sizeof(seqprog)/4; i++) {
4462 1.42 fvdl if (ahc_check_patch(ahc, &cur_patch, i, &skip_addr) == 0) {
4463 1.6 mycroft /*
4464 1.42 fvdl * Don't download this instruction as it
4465 1.42 fvdl * is in a patch that was removed.
4466 1.6 mycroft */
4467 1.42 fvdl continue;
4468 1.42 fvdl }
4469 1.42 fvdl ahc_download_instr(ahc, i, download_consts);
4470 1.42 fvdl downloaded++;
4471 1.6 mycroft }
4472 1.42 fvdl ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS|FASTMODE);
4473 1.42 fvdl restart_sequencer(ahc);
4474 1.42 fvdl
4475 1.9 explorer #ifdef AHC_DEBUG
4476 1.42 fvdl printf(" %d instructions downloaded\n", downloaded);
4477 1.9 explorer #endif
4478 1.1 mycroft }
4479 1.1 mycroft
4480 1.42 fvdl static int
4481 1.42 fvdl ahc_check_patch(struct ahc_softc *ahc, struct patch **start_patch,
4482 1.42 fvdl int start_instr, int *skip_addr)
4483 1.42 fvdl {
4484 1.42 fvdl struct patch *cur_patch;
4485 1.42 fvdl struct patch *last_patch;
4486 1.42 fvdl int num_patches;
4487 1.42 fvdl
4488 1.42 fvdl num_patches = sizeof(patches)/sizeof(struct patch);
4489 1.42 fvdl last_patch = &patches[num_patches];
4490 1.42 fvdl cur_patch = *start_patch;
4491 1.42 fvdl
4492 1.42 fvdl while (cur_patch < last_patch && start_instr == cur_patch->begin) {
4493 1.42 fvdl
4494 1.42 fvdl if (cur_patch->patch_func(ahc) == 0) {
4495 1.42 fvdl
4496 1.42 fvdl /* Start rejecting code */
4497 1.42 fvdl *skip_addr = start_instr + cur_patch->skip_instr;
4498 1.42 fvdl cur_patch += cur_patch->skip_patch;
4499 1.42 fvdl } else {
4500 1.42 fvdl /* Accepted this patch. Advance to the next
4501 1.42 fvdl * one and wait for our intruction pointer to
4502 1.42 fvdl * hit this point.
4503 1.42 fvdl */
4504 1.42 fvdl cur_patch++;
4505 1.28 leo }
4506 1.28 leo }
4507 1.42 fvdl
4508 1.42 fvdl *start_patch = cur_patch;
4509 1.42 fvdl if (start_instr < *skip_addr)
4510 1.42 fvdl /* Still skipping */
4511 1.42 fvdl return (0);
4512 1.42 fvdl
4513 1.42 fvdl return (1);
4514 1.28 leo }
4515 1.28 leo
4516 1.42 fvdl static void
4517 1.42 fvdl ahc_download_instr(struct ahc_softc *ahc, int instrptr, u_int8_t *dconsts)
4518 1.1 mycroft {
4519 1.42 fvdl union ins_formats instr;
4520 1.42 fvdl struct ins_format1 *fmt1_ins;
4521 1.42 fvdl struct ins_format3 *fmt3_ins;
4522 1.42 fvdl u_int opcode;
4523 1.42 fvdl
4524 1.42 fvdl /* Structure copy */
4525 1.42 fvdl instr = *(union ins_formats*)&seqprog[instrptr * 4];
4526 1.42 fvdl
4527 1.42 fvdl instr.integer = le32toh(instr.integer);
4528 1.42 fvdl
4529 1.42 fvdl fmt1_ins = &instr.format1;
4530 1.42 fvdl fmt3_ins = NULL;
4531 1.42 fvdl
4532 1.42 fvdl /* Pull the opcode */
4533 1.42 fvdl opcode = instr.format1.opcode;
4534 1.42 fvdl switch (opcode) {
4535 1.42 fvdl case AIC_OP_JMP:
4536 1.42 fvdl case AIC_OP_JC:
4537 1.42 fvdl case AIC_OP_JNC:
4538 1.42 fvdl case AIC_OP_CALL:
4539 1.42 fvdl case AIC_OP_JNE:
4540 1.42 fvdl case AIC_OP_JNZ:
4541 1.42 fvdl case AIC_OP_JE:
4542 1.42 fvdl case AIC_OP_JZ:
4543 1.42 fvdl {
4544 1.42 fvdl struct patch *cur_patch;
4545 1.42 fvdl int address_offset;
4546 1.42 fvdl u_int address;
4547 1.42 fvdl int skip_addr;
4548 1.42 fvdl int i;
4549 1.42 fvdl
4550 1.42 fvdl fmt3_ins = &instr.format3;
4551 1.42 fvdl address_offset = 0;
4552 1.42 fvdl address = fmt3_ins->address;
4553 1.42 fvdl cur_patch = patches;
4554 1.42 fvdl skip_addr = 0;
4555 1.42 fvdl
4556 1.42 fvdl for (i = 0; i < address;) {
4557 1.42 fvdl
4558 1.42 fvdl ahc_check_patch(ahc, &cur_patch, i, &skip_addr);
4559 1.42 fvdl
4560 1.42 fvdl if (skip_addr > i) {
4561 1.42 fvdl int end_addr;
4562 1.42 fvdl
4563 1.42 fvdl end_addr = MIN(address, skip_addr);
4564 1.42 fvdl address_offset += end_addr - i;
4565 1.42 fvdl i = skip_addr;
4566 1.42 fvdl } else {
4567 1.42 fvdl i++;
4568 1.42 fvdl }
4569 1.1 mycroft }
4570 1.42 fvdl address -= address_offset;
4571 1.42 fvdl fmt3_ins->address = address;
4572 1.42 fvdl /* FALLTHROUGH */
4573 1.42 fvdl }
4574 1.42 fvdl case AIC_OP_OR:
4575 1.42 fvdl case AIC_OP_AND:
4576 1.42 fvdl case AIC_OP_XOR:
4577 1.42 fvdl case AIC_OP_ADD:
4578 1.42 fvdl case AIC_OP_ADC:
4579 1.42 fvdl case AIC_OP_BMOV:
4580 1.42 fvdl if (fmt1_ins->parity != 0) {
4581 1.42 fvdl fmt1_ins->immediate = dconsts[fmt1_ins->immediate];
4582 1.42 fvdl }
4583 1.42 fvdl fmt1_ins->parity = 0;
4584 1.42 fvdl /* FALLTHROUGH */
4585 1.42 fvdl case AIC_OP_ROL:
4586 1.42 fvdl if ((ahc->features & AHC_ULTRA2) != 0) {
4587 1.42 fvdl int i, count;
4588 1.42 fvdl
4589 1.42 fvdl /* Calculate odd parity for the instruction */
4590 1.42 fvdl for (i = 0, count = 0; i < 31; i++) {
4591 1.42 fvdl u_int32_t mask;
4592 1.42 fvdl
4593 1.42 fvdl mask = 0x01 << i;
4594 1.42 fvdl if ((instr.integer & mask) != 0)
4595 1.42 fvdl count++;
4596 1.42 fvdl }
4597 1.42 fvdl if ((count & 0x01) == 0)
4598 1.42 fvdl instr.format1.parity = 1;
4599 1.42 fvdl } else {
4600 1.42 fvdl /* Compress the instruction for older sequencers */
4601 1.42 fvdl if (fmt3_ins != NULL) {
4602 1.42 fvdl instr.integer =
4603 1.42 fvdl fmt3_ins->immediate
4604 1.42 fvdl | (fmt3_ins->source << 8)
4605 1.42 fvdl | (fmt3_ins->address << 16)
4606 1.42 fvdl | (fmt3_ins->opcode << 25);
4607 1.42 fvdl } else {
4608 1.42 fvdl instr.integer =
4609 1.42 fvdl fmt1_ins->immediate
4610 1.42 fvdl | (fmt1_ins->source << 8)
4611 1.42 fvdl | (fmt1_ins->destination << 16)
4612 1.42 fvdl | (fmt1_ins->ret << 24)
4613 1.42 fvdl | (fmt1_ins->opcode << 25);
4614 1.1 mycroft }
4615 1.1 mycroft }
4616 1.42 fvdl instr.integer = htole32(instr.integer);
4617 1.42 fvdl ahc_outsb(ahc, SEQRAM, instr.bytes, 4);
4618 1.42 fvdl break;
4619 1.42 fvdl default:
4620 1.42 fvdl panic("Unknown opcode encountered in seq program");
4621 1.6 mycroft break;
4622 1.1 mycroft }
4623 1.1 mycroft }
4624 1.1 mycroft
4625 1.42 fvdl static void
4626 1.42 fvdl ahc_set_recoveryscb(struct ahc_softc *ahc, struct scb *scb)
4627 1.1 mycroft {
4628 1.1 mycroft
4629 1.42 fvdl if ((scb->flags & SCB_RECOVERY_SCB) == 0) {
4630 1.42 fvdl struct scb *scbp;
4631 1.6 mycroft
4632 1.42 fvdl scb->flags |= SCB_RECOVERY_SCB;
4633 1.6 mycroft
4634 1.42 fvdl /*
4635 1.42 fvdl * Take all queued, but not sent SCBs out of the equation.
4636 1.42 fvdl * Also ensure that no new CCBs are queued to us while we
4637 1.42 fvdl * try to fix this problem.
4638 1.42 fvdl */
4639 1.42 fvdl ahc->queue_blocked = 1;
4640 1.1 mycroft
4641 1.42 fvdl /*
4642 1.42 fvdl * Go through all of our pending SCBs and remove
4643 1.42 fvdl * any scheduled timeouts for them. We will reschedule
4644 1.42 fvdl * them after we've successfully fixed this problem.
4645 1.42 fvdl */
4646 1.42 fvdl scbp = ahc->pending_ccbs.lh_first;
4647 1.42 fvdl while (scbp != NULL) {
4648 1.44 thorpej callout_stop(&scbp->xs->xs_callout);
4649 1.42 fvdl scbp = scbp->plinks.le_next;
4650 1.42 fvdl }
4651 1.6 mycroft }
4652 1.6 mycroft }
4653 1.6 mycroft
4654 1.6 mycroft static void
4655 1.42 fvdl ahc_timeout(void *arg)
4656 1.6 mycroft {
4657 1.42 fvdl struct scb *scb;
4658 1.42 fvdl struct ahc_softc *ahc;
4659 1.9 explorer int s, found;
4660 1.42 fvdl u_int last_phase;
4661 1.42 fvdl int target;
4662 1.42 fvdl int lun;
4663 1.42 fvdl int i;
4664 1.6 mycroft char channel;
4665 1.6 mycroft
4666 1.42 fvdl scb = (struct scb *)arg;
4667 1.42 fvdl ahc = (struct ahc_softc *)scb->xs->sc_link->adapter_softc;
4668 1.42 fvdl
4669 1.6 mycroft s = splbio();
4670 1.6 mycroft
4671 1.42 fvdl /*
4672 1.42 fvdl * Ensure that the card doesn't do anything
4673 1.42 fvdl * behind our back. Also make sure that we
4674 1.42 fvdl * didn't "just" miss an interrupt that would
4675 1.42 fvdl * affect this timeout.
4676 1.42 fvdl */
4677 1.42 fvdl do {
4678 1.42 fvdl ahc_intr(ahc);
4679 1.42 fvdl pause_sequencer(ahc);
4680 1.42 fvdl } while (ahc_inb(ahc, INTSTAT) & INT_PEND);
4681 1.42 fvdl
4682 1.42 fvdl if ((scb->flags & SCB_ACTIVE) == 0) {
4683 1.6 mycroft /* Previous timeout took care of me already */
4684 1.42 fvdl printf("Timedout SCB handled by another timeout\n");
4685 1.42 fvdl unpause_sequencer(ahc);
4686 1.6 mycroft splx(s);
4687 1.6 mycroft return;
4688 1.6 mycroft }
4689 1.6 mycroft
4690 1.42 fvdl target = SCB_TARGET(scb);
4691 1.42 fvdl channel = SCB_CHANNEL(scb);
4692 1.42 fvdl lun = SCB_LUN(scb);
4693 1.6 mycroft
4694 1.25 bouyer scsi_print_addr(scb->xs->sc_link);
4695 1.42 fvdl printf("SCB %x - timed out ", scb->hscb->tag);
4696 1.6 mycroft /*
4697 1.6 mycroft * Take a snapshot of the bus state and print out
4698 1.6 mycroft * some information so we can track down driver bugs.
4699 1.6 mycroft */
4700 1.42 fvdl last_phase = ahc_inb(ahc, LASTPHASE);
4701 1.6 mycroft
4702 1.42 fvdl for (i = 0; i < num_phases; i++) {
4703 1.42 fvdl if (last_phase == phase_table[i].phase)
4704 1.6 mycroft break;
4705 1.6 mycroft }
4706 1.42 fvdl printf("%s", phase_table[i].phasemsg);
4707 1.6 mycroft
4708 1.42 fvdl printf(", SEQADDR == 0x%x\n",
4709 1.42 fvdl ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
4710 1.42 fvdl printf("SCSIRATE == 0x%x\n", ahc_inb(ahc, SCSIRATE));
4711 1.6 mycroft
4712 1.42 fvdl #ifdef AHC_DEBUG
4713 1.42 fvdl ahc_print_scb(scb);
4714 1.42 fvdl #endif
4715 1.6 mycroft
4716 1.42 fvdl #if 0
4717 1.42 fvdl printf("SSTAT1 == 0x%x\n", ahc_inb(ahc, SSTAT1));
4718 1.42 fvdl printf("SSTAT3 == 0x%x\n", ahc_inb(ahc, SSTAT3));
4719 1.42 fvdl printf("SCSIPHASE == 0x%x\n", ahc_inb(ahc, SCSIPHASE));
4720 1.42 fvdl printf("SCSIOFFSET == 0x%x\n", ahc_inb(ahc, SCSIOFFSET));
4721 1.42 fvdl printf("SEQ_FLAGS == 0x%x\n", ahc_inb(ahc, SEQ_FLAGS));
4722 1.42 fvdl printf("SCB_DATAPTR == 0x%x\n", ahc_inb(ahc, SCB_DATAPTR)
4723 1.42 fvdl | ahc_inb(ahc, SCB_DATAPTR + 1) << 8
4724 1.42 fvdl | ahc_inb(ahc, SCB_DATAPTR + 2) << 16
4725 1.42 fvdl | ahc_inb(ahc, SCB_DATAPTR + 3) << 24);
4726 1.42 fvdl printf("SCB_DATACNT == 0x%x\n", ahc_inb(ahc, SCB_DATACNT)
4727 1.42 fvdl | ahc_inb(ahc, SCB_DATACNT + 1) << 8
4728 1.42 fvdl | ahc_inb(ahc, SCB_DATACNT + 2) << 16);
4729 1.42 fvdl printf("SCB_SGCOUNT == 0x%x\n", ahc_inb(ahc, SCB_SGCOUNT));
4730 1.42 fvdl printf("CCSCBCTL == 0x%x\n", ahc_inb(ahc, CCSCBCTL));
4731 1.42 fvdl printf("CCSCBCNT == 0x%x\n", ahc_inb(ahc, CCSCBCNT));
4732 1.42 fvdl printf("DFCNTRL == 0x%x\n", ahc_inb(ahc, DFCNTRL));
4733 1.42 fvdl printf("DFSTATUS == 0x%x\n", ahc_inb(ahc, DFSTATUS));
4734 1.42 fvdl printf("CCHCNT == 0x%x\n", ahc_inb(ahc, CCHCNT));
4735 1.42 fvdl if (scb->sg_count > 0) {
4736 1.42 fvdl for (i = 0; i < scb->sg_count; i++) {
4737 1.42 fvdl printf("sg[%d] - Addr 0x%x : Length %d\n",
4738 1.42 fvdl i,
4739 1.42 fvdl le32toh(scb->sg_list[i].addr),
4740 1.42 fvdl le32toh(scb->sg_list[i].len));
4741 1.42 fvdl }
4742 1.42 fvdl }
4743 1.42 fvdl #endif
4744 1.42 fvdl if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) {
4745 1.6 mycroft /*
4746 1.6 mycroft * Been down this road before.
4747 1.6 mycroft * Do a full bus reset.
4748 1.6 mycroft */
4749 1.42 fvdl bus_reset:
4750 1.42 fvdl ahcsetccbstatus(scb->xs, XS_TIMEOUT);
4751 1.42 fvdl found = ahc_reset_channel(ahc, channel, /*Initiate Reset*/TRUE);
4752 1.42 fvdl printf("%s: Issued Channel %c Bus Reset. "
4753 1.42 fvdl "%d SCBs aborted\n", ahc_name(ahc), channel, found);
4754 1.42 fvdl } else {
4755 1.6 mycroft /*
4756 1.42 fvdl * If we are a target, transition to bus free and report
4757 1.42 fvdl * the timeout.
4758 1.42 fvdl *
4759 1.42 fvdl * The target/initiator that is holding up the bus may not
4760 1.6 mycroft * be the same as the one that triggered this timeout
4761 1.6 mycroft * (different commands have different timeout lengths).
4762 1.42 fvdl * If the bus is idle and we are actiing as the initiator
4763 1.42 fvdl * for this request, queue a BDR message to the timed out
4764 1.42 fvdl * target. Otherwise, if the timed out transaction is
4765 1.42 fvdl * active:
4766 1.42 fvdl * Initiator transaction:
4767 1.42 fvdl * Stuff the message buffer with a BDR message and assert
4768 1.42 fvdl * ATN in the hopes that the target will let go of the bus
4769 1.42 fvdl * and go to the mesgout phase. If this fails, we'll
4770 1.42 fvdl * get another timeout 2 seconds later which will attempt
4771 1.42 fvdl * a bus reset.
4772 1.6 mycroft *
4773 1.42 fvdl * Target transaction:
4774 1.42 fvdl * Transition to BUS FREE and report the error.
4775 1.42 fvdl * It's good to be the target!
4776 1.42 fvdl */
4777 1.42 fvdl u_int active_scb_index;
4778 1.42 fvdl
4779 1.42 fvdl active_scb_index = ahc_inb(ahc, SCB_TAG);
4780 1.42 fvdl
4781 1.42 fvdl if (last_phase != P_BUSFREE
4782 1.42 fvdl && (active_scb_index < ahc->scb_data->numscbs)) {
4783 1.42 fvdl struct scb *active_scb;
4784 1.42 fvdl
4785 1.42 fvdl /*
4786 1.42 fvdl * If the active SCB is not from our device,
4787 1.42 fvdl * assume that another device is hogging the bus
4788 1.42 fvdl * and wait for it's timeout to expire before
4789 1.42 fvdl * taking additional action.
4790 1.42 fvdl */
4791 1.42 fvdl active_scb = &ahc->scb_data->scbarray[active_scb_index];
4792 1.42 fvdl if (active_scb->hscb->tcl != scb->hscb->tcl) {
4793 1.42 fvdl u_int newtimeout;
4794 1.42 fvdl
4795 1.42 fvdl scsi_print_addr(scb->xs->sc_link);
4796 1.42 fvdl printf("Other SCB Timeout%s",
4797 1.42 fvdl (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0
4798 1.42 fvdl ? " again\n" : "\n");
4799 1.42 fvdl scb->flags |= SCB_OTHERTCL_TIMEOUT;
4800 1.42 fvdl newtimeout = MAX(active_scb->xs->timeout,
4801 1.42 fvdl scb->xs->timeout);
4802 1.44 thorpej callout_reset(&scb->xs->xs_callout,
4803 1.44 thorpej (newtimeout * hz) / 1000,
4804 1.44 thorpej ahc_timeout, scb);
4805 1.42 fvdl splx(s);
4806 1.42 fvdl return;
4807 1.42 fvdl }
4808 1.42 fvdl
4809 1.42 fvdl /* It's us */
4810 1.42 fvdl if ((scb->hscb->control & TARGET_SCB) != 0) {
4811 1.42 fvdl
4812 1.42 fvdl /*
4813 1.42 fvdl * Send back any queued up transactions
4814 1.42 fvdl * and properly record the error condition.
4815 1.42 fvdl */
4816 1.42 fvdl ahc_freeze_devq(ahc, scb->xs->sc_link);
4817 1.42 fvdl ahcsetccbstatus(scb->xs, XS_TIMEOUT);
4818 1.42 fvdl ahc_freeze_ccb(scb);
4819 1.42 fvdl ahc_done(ahc, scb);
4820 1.42 fvdl
4821 1.42 fvdl /* Will clear us from the bus */
4822 1.42 fvdl restart_sequencer(ahc);
4823 1.42 fvdl return;
4824 1.42 fvdl }
4825 1.42 fvdl
4826 1.42 fvdl ahc_set_recoveryscb(ahc, active_scb);
4827 1.42 fvdl ahc_outb(ahc, MSG_OUT, MSG_BUS_DEV_RESET);
4828 1.42 fvdl ahc_outb(ahc, SCSISIGO, last_phase|ATNO);
4829 1.42 fvdl scsi_print_addr(active_scb->xs->sc_link);
4830 1.42 fvdl printf("BDR message in message buffer\n");
4831 1.42 fvdl active_scb->flags |= SCB_DEVICE_RESET;
4832 1.44 thorpej callout_reset(&active_scb->xs->xs_callout,
4833 1.44 thorpej 2 * hz, ahc_timeout, active_scb);
4834 1.42 fvdl unpause_sequencer(ahc);
4835 1.42 fvdl } else {
4836 1.42 fvdl int disconnected;
4837 1.42 fvdl
4838 1.42 fvdl /* XXX Shouldn't panic. Just punt instead */
4839 1.42 fvdl if ((scb->hscb->control & TARGET_SCB) != 0)
4840 1.42 fvdl panic("Timed-out target SCB but bus idle");
4841 1.42 fvdl
4842 1.42 fvdl if (last_phase != P_BUSFREE
4843 1.42 fvdl && (ahc_inb(ahc, SSTAT0) & TARGET) != 0) {
4844 1.42 fvdl /* XXX What happened to the SCB? */
4845 1.42 fvdl /* Hung target selection. Goto busfree */
4846 1.42 fvdl printf("%s: Hung target selection\n",
4847 1.42 fvdl ahc_name(ahc));
4848 1.42 fvdl restart_sequencer(ahc);
4849 1.42 fvdl return;
4850 1.42 fvdl }
4851 1.42 fvdl
4852 1.42 fvdl if (ahc_search_qinfifo(ahc, target, channel, lun,
4853 1.42 fvdl scb->hscb->tag, ROLE_INITIATOR,
4854 1.42 fvdl /*status*/0, SEARCH_COUNT) > 0) {
4855 1.42 fvdl disconnected = FALSE;
4856 1.42 fvdl } else {
4857 1.42 fvdl disconnected = TRUE;
4858 1.42 fvdl }
4859 1.42 fvdl
4860 1.42 fvdl if (disconnected) {
4861 1.42 fvdl u_int active_scb;
4862 1.1 mycroft
4863 1.42 fvdl ahc_set_recoveryscb(ahc, scb);
4864 1.42 fvdl /*
4865 1.42 fvdl * Simply set the MK_MESSAGE control bit.
4866 1.42 fvdl */
4867 1.42 fvdl scb->hscb->control |= MK_MESSAGE;
4868 1.42 fvdl scb->flags |= SCB_QUEUED_MSG
4869 1.42 fvdl | SCB_DEVICE_RESET;
4870 1.42 fvdl
4871 1.42 fvdl /*
4872 1.42 fvdl * Mark the cached copy of this SCB in the
4873 1.42 fvdl * disconnected list too, so that a reconnect
4874 1.42 fvdl * at this point causes a BDR or abort.
4875 1.42 fvdl */
4876 1.42 fvdl active_scb = ahc_inb(ahc, SCBPTR);
4877 1.42 fvdl if (ahc_search_disc_list(ahc, target,
4878 1.42 fvdl channel, lun,
4879 1.42 fvdl scb->hscb->tag,
4880 1.42 fvdl /*stop_on_first*/TRUE,
4881 1.42 fvdl /*remove*/FALSE,
4882 1.42 fvdl /*save_state*/FALSE)) {
4883 1.42 fvdl u_int scb_control;
4884 1.42 fvdl
4885 1.42 fvdl scb_control = ahc_inb(ahc, SCB_CONTROL);
4886 1.42 fvdl scb_control |= MK_MESSAGE;
4887 1.42 fvdl ahc_outb(ahc, SCB_CONTROL, scb_control);
4888 1.6 mycroft }
4889 1.42 fvdl ahc_outb(ahc, SCBPTR, active_scb);
4890 1.42 fvdl ahc_index_busy_tcl(ahc, scb->hscb->tcl,
4891 1.42 fvdl /*unbusy*/TRUE);
4892 1.42 fvdl
4893 1.42 fvdl /*
4894 1.42 fvdl * Actually re-queue this SCB in case we can
4895 1.42 fvdl * select the device before it reconnects.
4896 1.42 fvdl * Clear out any entries in the QINFIFO first
4897 1.42 fvdl * so we are the next SCB for this target
4898 1.42 fvdl * to run.
4899 1.42 fvdl */
4900 1.42 fvdl ahc_search_qinfifo(ahc, SCB_TARGET(scb),
4901 1.42 fvdl channel, SCB_LUN(scb),
4902 1.42 fvdl SCB_LIST_NULL,
4903 1.42 fvdl ROLE_INITIATOR,
4904 1.42 fvdl SCB_REQUEUE,
4905 1.42 fvdl SEARCH_COMPLETE);
4906 1.25 bouyer scsi_print_addr(scb->xs->sc_link);
4907 1.42 fvdl printf("Queuing a BDR SCB\n");
4908 1.42 fvdl ahc->qinfifo[ahc->qinfifonext++] =
4909 1.42 fvdl scb->hscb->tag;
4910 1.42 fvdl
4911 1.42 fvdl bus_dmamap_sync(ahc->parent_dmat,
4912 1.42 fvdl ahc->shared_data_dmamap,
4913 1.42 fvdl QINFIFO_OFFSET * 256, 256,
4914 1.42 fvdl BUS_DMASYNC_PREWRITE);
4915 1.42 fvdl
4916 1.42 fvdl if ((ahc->features & AHC_QUEUE_REGS) != 0) {
4917 1.42 fvdl ahc_outb(ahc, HNSCB_QOFF,
4918 1.42 fvdl ahc->qinfifonext);
4919 1.42 fvdl } else {
4920 1.42 fvdl ahc_outb(ahc, KERNEL_QINPOS,
4921 1.42 fvdl ahc->qinfifonext);
4922 1.6 mycroft }
4923 1.44 thorpej callout_reset(&scb->xs->xs_callout, 2 * hz,
4924 1.44 thorpej ahc_timeout, scb);
4925 1.42 fvdl unpause_sequencer(ahc);
4926 1.42 fvdl } else {
4927 1.42 fvdl /* Go "immediatly" to the bus reset */
4928 1.42 fvdl /* This shouldn't happen */
4929 1.42 fvdl ahc_set_recoveryscb(ahc, scb);
4930 1.42 fvdl scsi_print_addr(scb->xs->sc_link);
4931 1.42 fvdl printf("SCB %x: Immediate reset. "
4932 1.42 fvdl "Flags = 0x%x\n", scb->hscb->tag,
4933 1.42 fvdl scb->flags);
4934 1.42 fvdl goto bus_reset;
4935 1.6 mycroft }
4936 1.6 mycroft }
4937 1.1 mycroft }
4938 1.6 mycroft splx(s);
4939 1.1 mycroft }
4940 1.1 mycroft
4941 1.6 mycroft static int
4942 1.42 fvdl ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel,
4943 1.42 fvdl int lun, u_int tag, role_t role, scb_flag status,
4944 1.42 fvdl ahc_search_action action)
4945 1.42 fvdl {
4946 1.42 fvdl struct scb *scbp;
4947 1.42 fvdl u_int8_t qinpos;
4948 1.42 fvdl u_int8_t qintail;
4949 1.42 fvdl int found;
4950 1.1 mycroft
4951 1.42 fvdl qinpos = ahc_inb(ahc, QINPOS);
4952 1.42 fvdl qintail = ahc->qinfifonext;
4953 1.42 fvdl found = 0;
4954 1.6 mycroft
4955 1.1 mycroft /*
4956 1.42 fvdl * Start with an empty queue. Entries that are not chosen
4957 1.42 fvdl * for removal will be re-added to the queue as we go.
4958 1.1 mycroft */
4959 1.42 fvdl ahc->qinfifonext = qinpos;
4960 1.42 fvdl
4961 1.42 fvdl bus_dmamap_sync(ahc->parent_dmat, ahc->shared_data_dmamap,
4962 1.42 fvdl QINFIFO_OFFSET * 256, 256, BUS_DMASYNC_POSTREAD);
4963 1.1 mycroft
4964 1.42 fvdl while (qinpos != qintail) {
4965 1.42 fvdl scbp = &ahc->scb_data->scbarray[ahc->qinfifo[qinpos]];
4966 1.42 fvdl if (ahc_match_scb(scbp, target, channel, lun, tag, role)) {
4967 1.42 fvdl /*
4968 1.42 fvdl * We found an scb that needs to be removed.
4969 1.42 fvdl */
4970 1.42 fvdl switch (action) {
4971 1.42 fvdl case SEARCH_COMPLETE:
4972 1.42 fvdl if (!(scbp->xs->xs_status & XS_STS_DONE)) {
4973 1.42 fvdl scbp->flags |= status;
4974 1.42 fvdl scbp->xs->error = XS_NOERROR;
4975 1.42 fvdl }
4976 1.42 fvdl ahc_freeze_ccb(scbp);
4977 1.42 fvdl ahc_done(ahc, scbp);
4978 1.42 fvdl break;
4979 1.42 fvdl case SEARCH_COUNT:
4980 1.42 fvdl ahc->qinfifo[ahc->qinfifonext++] =
4981 1.42 fvdl scbp->hscb->tag;
4982 1.42 fvdl break;
4983 1.42 fvdl case SEARCH_REMOVE:
4984 1.42 fvdl break;
4985 1.1 mycroft }
4986 1.42 fvdl found++;
4987 1.42 fvdl } else {
4988 1.42 fvdl ahc->qinfifo[ahc->qinfifonext++] = scbp->hscb->tag;
4989 1.1 mycroft }
4990 1.42 fvdl qinpos++;
4991 1.42 fvdl }
4992 1.42 fvdl
4993 1.42 fvdl bus_dmamap_sync(ahc->parent_dmat, ahc->shared_data_dmamap,
4994 1.42 fvdl QINFIFO_OFFSET * 256, 256, BUS_DMASYNC_PREWRITE);
4995 1.42 fvdl
4996 1.42 fvdl if ((ahc->features & AHC_QUEUE_REGS) != 0) {
4997 1.42 fvdl ahc_outb(ahc, HNSCB_QOFF, ahc->qinfifonext);
4998 1.42 fvdl } else {
4999 1.42 fvdl ahc_outb(ahc, KERNEL_QINPOS, ahc->qinfifonext);
5000 1.6 mycroft }
5001 1.1 mycroft
5002 1.42 fvdl return (found);
5003 1.42 fvdl }
5004 1.42 fvdl
5005 1.42 fvdl /*
5006 1.42 fvdl * Abort all SCBs that match the given description (target/channel/lun/tag),
5007 1.42 fvdl * setting their status to the passed in status if the status has not already
5008 1.42 fvdl * been modified from CAM_REQ_INPROG. This routine assumes that the sequencer
5009 1.42 fvdl * is paused before it is called.
5010 1.42 fvdl */
5011 1.42 fvdl static int
5012 1.42 fvdl ahc_abort_scbs(struct ahc_softc *ahc, int target, char channel,
5013 1.42 fvdl int lun, u_int tag, role_t role, int status)
5014 1.42 fvdl {
5015 1.42 fvdl struct scb *scbp;
5016 1.42 fvdl u_int active_scb;
5017 1.42 fvdl int i;
5018 1.42 fvdl int found;
5019 1.42 fvdl
5020 1.42 fvdl /* restore this when we're done */
5021 1.42 fvdl active_scb = ahc_inb(ahc, SCBPTR);
5022 1.42 fvdl
5023 1.42 fvdl found = ahc_search_qinfifo(ahc, target, channel, lun, SCB_LIST_NULL,
5024 1.42 fvdl role, SCB_REQUEUE, SEARCH_COMPLETE);
5025 1.42 fvdl
5026 1.6 mycroft /*
5027 1.6 mycroft * Search waiting for selection list.
5028 1.6 mycroft */
5029 1.6 mycroft {
5030 1.42 fvdl u_int8_t next, prev;
5031 1.6 mycroft
5032 1.42 fvdl next = ahc_inb(ahc, WAITING_SCBH); /* Start at head of list. */
5033 1.6 mycroft prev = SCB_LIST_NULL;
5034 1.6 mycroft
5035 1.6 mycroft while (next != SCB_LIST_NULL) {
5036 1.42 fvdl u_int8_t scb_index;
5037 1.42 fvdl
5038 1.42 fvdl ahc_outb(ahc, SCBPTR, next);
5039 1.42 fvdl scb_index = ahc_inb(ahc, SCB_TAG);
5040 1.42 fvdl if (scb_index >= ahc->scb_data->numscbs) {
5041 1.42 fvdl panic("Waiting List inconsistency. "
5042 1.42 fvdl "SCB index == %d, yet numscbs == %d.",
5043 1.42 fvdl scb_index, ahc->scb_data->numscbs);
5044 1.6 mycroft }
5045 1.42 fvdl scbp = &ahc->scb_data->scbarray[scb_index];
5046 1.42 fvdl if (ahc_match_scb(scbp, target, channel,
5047 1.42 fvdl lun, SCB_LIST_NULL, role)) {
5048 1.42 fvdl
5049 1.42 fvdl next = ahc_abort_wscb(ahc, next, prev);
5050 1.42 fvdl } else {
5051 1.42 fvdl
5052 1.6 mycroft prev = next;
5053 1.42 fvdl next = ahc_inb(ahc, SCB_NEXT);
5054 1.6 mycroft }
5055 1.6 mycroft }
5056 1.1 mycroft }
5057 1.1 mycroft /*
5058 1.42 fvdl * Go through the disconnected list and remove any entries we
5059 1.42 fvdl * have queued for completion, 0'ing their control byte too.
5060 1.42 fvdl * We save the active SCB and restore it ourselves, so there
5061 1.42 fvdl * is no reason for this search to restore it too.
5062 1.42 fvdl */
5063 1.42 fvdl ahc_search_disc_list(ahc, target, channel, lun, tag,
5064 1.42 fvdl /*stop_on_first*/FALSE, /*remove*/TRUE,
5065 1.42 fvdl /*save_state*/FALSE);
5066 1.42 fvdl
5067 1.42 fvdl /*
5068 1.42 fvdl * Go through the hardware SCB array looking for commands that
5069 1.42 fvdl * were active but not on any list.
5070 1.42 fvdl */
5071 1.42 fvdl for(i = 0; i < ahc->scb_data->maxhscbs; i++) {
5072 1.42 fvdl u_int scbid;
5073 1.42 fvdl
5074 1.42 fvdl ahc_outb(ahc, SCBPTR, i);
5075 1.42 fvdl scbid = ahc_inb(ahc, SCB_TAG);
5076 1.42 fvdl scbp = &ahc->scb_data->scbarray[scbid];
5077 1.42 fvdl if (scbid < ahc->scb_data->numscbs
5078 1.42 fvdl && ahc_match_scb(scbp, target, channel, lun, tag, role))
5079 1.42 fvdl ahc_add_curscb_to_free_list(ahc);
5080 1.42 fvdl }
5081 1.42 fvdl
5082 1.42 fvdl /*
5083 1.42 fvdl * Go through the pending CCB list and look for
5084 1.42 fvdl * commands for this target that are still active.
5085 1.42 fvdl * These are other tagged commands that were
5086 1.42 fvdl * disconnected when the reset occured.
5087 1.6 mycroft */
5088 1.42 fvdl {
5089 1.42 fvdl struct scb *scb;
5090 1.42 fvdl
5091 1.42 fvdl scb = ahc->pending_ccbs.lh_first;
5092 1.42 fvdl while (scb != NULL) {
5093 1.42 fvdl scbp = scb;
5094 1.42 fvdl scb = scb->plinks.le_next;
5095 1.42 fvdl if (ahc_match_scb(scbp, target, channel,
5096 1.42 fvdl lun, tag, role)) {
5097 1.42 fvdl if (!(scbp->xs->xs_status & XS_STS_DONE))
5098 1.42 fvdl ahcsetccbstatus(scbp->xs, status);
5099 1.42 fvdl ahc_freeze_ccb(scbp);
5100 1.42 fvdl ahc_done(ahc, scbp);
5101 1.42 fvdl found++;
5102 1.6 mycroft }
5103 1.6 mycroft }
5104 1.42 fvdl }
5105 1.42 fvdl ahc_outb(ahc, SCBPTR, active_scb);
5106 1.6 mycroft return found;
5107 1.6 mycroft }
5108 1.6 mycroft
5109 1.42 fvdl static int
5110 1.42 fvdl ahc_search_disc_list(struct ahc_softc *ahc, int target, char channel,
5111 1.42 fvdl int lun, u_int tag, int stop_on_first, int remove,
5112 1.42 fvdl int save_state)
5113 1.42 fvdl {
5114 1.42 fvdl struct scb *scbp;
5115 1.42 fvdl u_int next;
5116 1.42 fvdl u_int prev;
5117 1.42 fvdl u_int count;
5118 1.42 fvdl u_int active_scb;
5119 1.42 fvdl
5120 1.42 fvdl count = 0;
5121 1.42 fvdl next = ahc_inb(ahc, DISCONNECTED_SCBH);
5122 1.42 fvdl prev = SCB_LIST_NULL;
5123 1.42 fvdl
5124 1.42 fvdl if (save_state) {
5125 1.42 fvdl /* restore this when we're done */
5126 1.42 fvdl active_scb = ahc_inb(ahc, SCBPTR);
5127 1.42 fvdl } else
5128 1.42 fvdl /* Silence compiler */
5129 1.42 fvdl active_scb = SCB_LIST_NULL;
5130 1.42 fvdl
5131 1.42 fvdl while (next != SCB_LIST_NULL) {
5132 1.42 fvdl u_int scb_index;
5133 1.42 fvdl
5134 1.42 fvdl ahc_outb(ahc, SCBPTR, next);
5135 1.42 fvdl scb_index = ahc_inb(ahc, SCB_TAG);
5136 1.42 fvdl if (scb_index >= ahc->scb_data->numscbs) {
5137 1.42 fvdl panic("Disconnected List inconsistency. "
5138 1.42 fvdl "SCB index == %d, yet numscbs == %d.",
5139 1.42 fvdl scb_index, ahc->scb_data->numscbs);
5140 1.42 fvdl }
5141 1.42 fvdl scbp = &ahc->scb_data->scbarray[scb_index];
5142 1.42 fvdl if (ahc_match_scb(scbp, target, channel, lun,
5143 1.42 fvdl tag, ROLE_INITIATOR)) {
5144 1.42 fvdl count++;
5145 1.42 fvdl if (remove) {
5146 1.42 fvdl next =
5147 1.42 fvdl ahc_rem_scb_from_disc_list(ahc, prev, next);
5148 1.42 fvdl } else {
5149 1.42 fvdl prev = next;
5150 1.42 fvdl next = ahc_inb(ahc, SCB_NEXT);
5151 1.42 fvdl }
5152 1.42 fvdl if (stop_on_first)
5153 1.42 fvdl break;
5154 1.42 fvdl } else {
5155 1.42 fvdl prev = next;
5156 1.42 fvdl next = ahc_inb(ahc, SCB_NEXT);
5157 1.42 fvdl }
5158 1.42 fvdl }
5159 1.42 fvdl if (save_state)
5160 1.42 fvdl ahc_outb(ahc, SCBPTR, active_scb);
5161 1.42 fvdl return (count);
5162 1.42 fvdl }
5163 1.42 fvdl
5164 1.42 fvdl static u_int
5165 1.42 fvdl ahc_rem_scb_from_disc_list(struct ahc_softc *ahc, u_int prev, u_int scbptr)
5166 1.42 fvdl {
5167 1.42 fvdl u_int next;
5168 1.42 fvdl
5169 1.42 fvdl ahc_outb(ahc, SCBPTR, scbptr);
5170 1.42 fvdl next = ahc_inb(ahc, SCB_NEXT);
5171 1.42 fvdl
5172 1.42 fvdl ahc_outb(ahc, SCB_CONTROL, 0);
5173 1.42 fvdl
5174 1.42 fvdl ahc_add_curscb_to_free_list(ahc);
5175 1.42 fvdl
5176 1.42 fvdl if (prev != SCB_LIST_NULL) {
5177 1.42 fvdl ahc_outb(ahc, SCBPTR, prev);
5178 1.42 fvdl ahc_outb(ahc, SCB_NEXT, next);
5179 1.42 fvdl } else
5180 1.42 fvdl ahc_outb(ahc, DISCONNECTED_SCBH, next);
5181 1.42 fvdl
5182 1.42 fvdl return (next);
5183 1.42 fvdl }
5184 1.42 fvdl
5185 1.42 fvdl static void
5186 1.42 fvdl ahc_add_curscb_to_free_list(struct ahc_softc *ahc)
5187 1.42 fvdl {
5188 1.42 fvdl /* Invalidate the tag so that ahc_find_scb doesn't think it's active */
5189 1.42 fvdl ahc_outb(ahc, SCB_TAG, SCB_LIST_NULL);
5190 1.42 fvdl
5191 1.42 fvdl ahc_outb(ahc, SCB_NEXT, ahc_inb(ahc, FREE_SCBH));
5192 1.42 fvdl ahc_outb(ahc, FREE_SCBH, ahc_inb(ahc, SCBPTR));
5193 1.42 fvdl }
5194 1.42 fvdl
5195 1.6 mycroft /*
5196 1.6 mycroft * Manipulate the waiting for selection list and return the
5197 1.6 mycroft * scb that follows the one that we remove.
5198 1.6 mycroft */
5199 1.42 fvdl static u_int
5200 1.42 fvdl ahc_abort_wscb(struct ahc_softc *ahc, u_int scbpos, u_int prev)
5201 1.6 mycroft {
5202 1.42 fvdl u_int curscb, next;
5203 1.42 fvdl
5204 1.6 mycroft /*
5205 1.6 mycroft * Select the SCB we want to abort and
5206 1.6 mycroft * pull the next pointer out of it.
5207 1.6 mycroft */
5208 1.42 fvdl curscb = ahc_inb(ahc, SCBPTR);
5209 1.42 fvdl ahc_outb(ahc, SCBPTR, scbpos);
5210 1.42 fvdl next = ahc_inb(ahc, SCB_NEXT);
5211 1.6 mycroft
5212 1.6 mycroft /* Clear the necessary fields */
5213 1.42 fvdl ahc_outb(ahc, SCB_CONTROL, 0);
5214 1.42 fvdl
5215 1.42 fvdl ahc_add_curscb_to_free_list(ahc);
5216 1.6 mycroft
5217 1.6 mycroft /* update the waiting list */
5218 1.42 fvdl if (prev == SCB_LIST_NULL) {
5219 1.6 mycroft /* First in the list */
5220 1.42 fvdl ahc_outb(ahc, WAITING_SCBH, next);
5221 1.42 fvdl
5222 1.42 fvdl /*
5223 1.42 fvdl * Ensure we aren't attempting to perform
5224 1.42 fvdl * selection for this entry.
5225 1.42 fvdl */
5226 1.42 fvdl ahc_outb(ahc, SCSISEQ, (ahc_inb(ahc, SCSISEQ) & ~ENSELO));
5227 1.42 fvdl } else {
5228 1.1 mycroft /*
5229 1.6 mycroft * Select the scb that pointed to us
5230 1.6 mycroft * and update its next pointer.
5231 1.1 mycroft */
5232 1.42 fvdl ahc_outb(ahc, SCBPTR, prev);
5233 1.42 fvdl ahc_outb(ahc, SCB_NEXT, next);
5234 1.1 mycroft }
5235 1.42 fvdl
5236 1.1 mycroft /*
5237 1.42 fvdl * Point us back at the original scb position.
5238 1.42 fvdl */
5239 1.42 fvdl ahc_outb(ahc, SCBPTR, curscb);
5240 1.6 mycroft return next;
5241 1.6 mycroft }
5242 1.6 mycroft
5243 1.6 mycroft static void
5244 1.42 fvdl ahc_clear_intstat(struct ahc_softc *ahc)
5245 1.42 fvdl {
5246 1.42 fvdl /* Clear any interrupt conditions this may have caused */
5247 1.42 fvdl ahc_outb(ahc, CLRSINT0, CLRSELDO|CLRSELDI|CLRSELINGO);
5248 1.42 fvdl ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRATNO|CLRSCSIRSTI
5249 1.42 fvdl |CLRBUSFREE|CLRSCSIPERR|CLRPHASECHG|
5250 1.42 fvdl CLRREQINIT);
5251 1.42 fvdl ahc_outb(ahc, CLRINT, CLRSCSIINT);
5252 1.42 fvdl }
5253 1.42 fvdl
5254 1.42 fvdl static void
5255 1.42 fvdl ahc_reset_current_bus(struct ahc_softc *ahc)
5256 1.42 fvdl {
5257 1.42 fvdl u_int8_t scsiseq;
5258 1.42 fvdl
5259 1.42 fvdl ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENSCSIRST);
5260 1.42 fvdl scsiseq = ahc_inb(ahc, SCSISEQ);
5261 1.42 fvdl ahc_outb(ahc, SCSISEQ, scsiseq | SCSIRSTO);
5262 1.42 fvdl DELAY(AHC_BUSRESET_DELAY);
5263 1.42 fvdl /* Turn off the bus reset */
5264 1.42 fvdl ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO);
5265 1.42 fvdl
5266 1.42 fvdl ahc_clear_intstat(ahc);
5267 1.42 fvdl
5268 1.42 fvdl /* Re-enable reset interrupts */
5269 1.42 fvdl ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) | ENSCSIRST);
5270 1.42 fvdl }
5271 1.42 fvdl
5272 1.42 fvdl static int
5273 1.42 fvdl ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset)
5274 1.6 mycroft {
5275 1.42 fvdl u_int initiator, target, max_scsiid;
5276 1.42 fvdl u_int sblkctl;
5277 1.42 fvdl u_int our_id;
5278 1.42 fvdl int found;
5279 1.42 fvdl int restart_needed;
5280 1.42 fvdl char cur_channel;
5281 1.42 fvdl
5282 1.42 fvdl ahc->pending_device = NULL;
5283 1.42 fvdl
5284 1.42 fvdl pause_sequencer(ahc);
5285 1.42 fvdl
5286 1.42 fvdl /*
5287 1.42 fvdl * Run our command complete fifos to ensure that we perform
5288 1.42 fvdl * completion processing on any commands that 'completed'
5289 1.42 fvdl * before the reset occurred.
5290 1.42 fvdl */
5291 1.42 fvdl ahc_run_qoutfifo(ahc);
5292 1.42 fvdl
5293 1.42 fvdl /*
5294 1.42 fvdl * Reset the bus if we are initiating this reset
5295 1.42 fvdl */
5296 1.42 fvdl sblkctl = ahc_inb(ahc, SBLKCTL);
5297 1.42 fvdl cur_channel = 'A';
5298 1.42 fvdl if ((ahc->features & AHC_TWIN) != 0
5299 1.42 fvdl && ((sblkctl & SELBUSB) != 0))
5300 1.42 fvdl cur_channel = 'B';
5301 1.42 fvdl if (cur_channel != channel) {
5302 1.42 fvdl /* Case 1: Command for another bus is active
5303 1.42 fvdl * Stealthily reset the other bus without
5304 1.42 fvdl * upsetting the current bus.
5305 1.42 fvdl */
5306 1.42 fvdl ahc_outb(ahc, SBLKCTL, sblkctl ^ SELBUSB);
5307 1.42 fvdl ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
5308 1.42 fvdl ahc_outb(ahc, SCSISEQ,
5309 1.42 fvdl ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP));
5310 1.42 fvdl if (initiate_reset)
5311 1.42 fvdl ahc_reset_current_bus(ahc);
5312 1.42 fvdl ahc_clear_intstat(ahc);
5313 1.42 fvdl ahc_outb(ahc, SBLKCTL, sblkctl);
5314 1.42 fvdl restart_needed = FALSE;
5315 1.42 fvdl } else {
5316 1.42 fvdl /* Case 2: A command from this bus is active or we're idle */
5317 1.42 fvdl ahc_clear_msg_state(ahc);
5318 1.42 fvdl ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENBUSFREE);
5319 1.42 fvdl ahc_outb(ahc, SCSISEQ,
5320 1.42 fvdl ahc_inb(ahc, SCSISEQ) & (ENSELI|ENRSELI|ENAUTOATNP));
5321 1.42 fvdl if (initiate_reset)
5322 1.42 fvdl ahc_reset_current_bus(ahc);
5323 1.42 fvdl ahc_clear_intstat(ahc);
5324 1.6 mycroft
5325 1.42 fvdl /*
5326 1.42 fvdl * Since we are going to restart the sequencer, avoid
5327 1.42 fvdl * a race in the sequencer that could cause corruption
5328 1.42 fvdl * of our Q pointers by starting over from index 0.
5329 1.1 mycroft */
5330 1.42 fvdl ahc->qoutfifonext = 0;
5331 1.42 fvdl if ((ahc->features & AHC_QUEUE_REGS) != 0)
5332 1.42 fvdl ahc_outb(ahc, SDSCB_QOFF, 0);
5333 1.42 fvdl else
5334 1.42 fvdl ahc_outb(ahc, QOUTPOS, 0);
5335 1.42 fvdl restart_needed = TRUE;
5336 1.42 fvdl }
5337 1.42 fvdl
5338 1.42 fvdl /*
5339 1.42 fvdl * Clean up all the state information for the
5340 1.42 fvdl * pending transactions on this bus.
5341 1.42 fvdl */
5342 1.42 fvdl found = ahc_abort_scbs(ahc, AHC_TARGET_WILDCARD, channel,
5343 1.42 fvdl AHC_LUN_WILDCARD, SCB_LIST_NULL,
5344 1.42 fvdl ROLE_UNKNOWN, XS_RESET);
5345 1.42 fvdl if (channel == 'B') {
5346 1.42 fvdl our_id = ahc->our_id_b;
5347 1.42 fvdl } else {
5348 1.42 fvdl our_id = ahc->our_id;
5349 1.6 mycroft }
5350 1.42 fvdl
5351 1.42 fvdl max_scsiid = (ahc->features & AHC_WIDE) ? 15 : 7;
5352 1.42 fvdl
5353 1.42 fvdl /*
5354 1.42 fvdl * Revert to async/narrow transfers until we renegotiate.
5355 1.42 fvdl */
5356 1.42 fvdl for (target = 0; target <= max_scsiid; target++) {
5357 1.42 fvdl
5358 1.42 fvdl if (ahc->enabled_targets[target] == NULL)
5359 1.42 fvdl continue;
5360 1.42 fvdl for (initiator = 0; initiator <= max_scsiid; initiator++) {
5361 1.42 fvdl struct ahc_devinfo devinfo;
5362 1.42 fvdl
5363 1.42 fvdl ahc_compile_devinfo(&devinfo, target, initiator,
5364 1.42 fvdl AHC_LUN_WILDCARD,
5365 1.42 fvdl channel, ROLE_UNKNOWN);
5366 1.42 fvdl ahc_set_width(ahc, &devinfo,
5367 1.42 fvdl MSG_EXT_WDTR_BUS_8_BIT,
5368 1.42 fvdl AHC_TRANS_CUR, /*paused*/TRUE, FALSE);
5369 1.42 fvdl ahc_set_syncrate(ahc, &devinfo,
5370 1.42 fvdl /*syncrate*/NULL, /*period*/0,
5371 1.42 fvdl /*offset*/0, AHC_TRANS_CUR,
5372 1.42 fvdl /*paused*/TRUE, FALSE);
5373 1.42 fvdl }
5374 1.42 fvdl }
5375 1.42 fvdl
5376 1.42 fvdl if (restart_needed)
5377 1.42 fvdl restart_sequencer(ahc);
5378 1.42 fvdl else
5379 1.42 fvdl unpause_sequencer(ahc);
5380 1.42 fvdl return found;
5381 1.42 fvdl }
5382 1.42 fvdl
5383 1.42 fvdl static int
5384 1.42 fvdl ahc_match_scb(struct scb *scb, int target, char channel,
5385 1.42 fvdl int lun, u_int tag, role_t role)
5386 1.42 fvdl {
5387 1.42 fvdl int targ = SCB_TARGET(scb);
5388 1.42 fvdl char chan = SCB_CHANNEL(scb);
5389 1.42 fvdl int slun = SCB_LUN(scb);
5390 1.42 fvdl int match;
5391 1.42 fvdl
5392 1.42 fvdl match = ((chan == channel) || (channel == ALL_CHANNELS));
5393 1.42 fvdl if (match != 0)
5394 1.42 fvdl match = ((targ == target) || (target == AHC_TARGET_WILDCARD));
5395 1.42 fvdl if (match != 0)
5396 1.42 fvdl match = ((lun == slun) || (lun == AHC_LUN_WILDCARD));
5397 1.42 fvdl
5398 1.42 fvdl return match;
5399 1.6 mycroft }
5400 1.6 mycroft
5401 1.6 mycroft static void
5402 1.42 fvdl ahc_construct_sdtr(struct ahc_softc *ahc, u_int period, u_int offset)
5403 1.6 mycroft {
5404 1.42 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED;
5405 1.42 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_SDTR_LEN;
5406 1.42 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_SDTR;
5407 1.42 fvdl ahc->msgout_buf[ahc->msgout_index++] = period;
5408 1.42 fvdl ahc->msgout_buf[ahc->msgout_index++] = offset;
5409 1.42 fvdl ahc->msgout_len += 5;
5410 1.42 fvdl }
5411 1.1 mycroft
5412 1.42 fvdl static void
5413 1.42 fvdl ahc_construct_wdtr(struct ahc_softc *ahc, u_int bus_width)
5414 1.42 fvdl {
5415 1.42 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_EXTENDED;
5416 1.42 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_WDTR_LEN;
5417 1.42 fvdl ahc->msgout_buf[ahc->msgout_index++] = MSG_EXT_WDTR;
5418 1.42 fvdl ahc->msgout_buf[ahc->msgout_index++] = bus_width;
5419 1.42 fvdl ahc->msgout_len += 4;
5420 1.1 mycroft }
5421 1.1 mycroft
5422 1.6 mycroft static void
5423 1.42 fvdl ahc_calc_residual(struct scb *scb)
5424 1.1 mycroft {
5425 1.42 fvdl struct hardware_scb *hscb;
5426 1.1 mycroft
5427 1.42 fvdl hscb = scb->hscb;
5428 1.6 mycroft
5429 1.6 mycroft /*
5430 1.42 fvdl * If the disconnected flag is still set, this is bogus
5431 1.42 fvdl * residual information left over from a sequencer
5432 1.42 fvdl * pagin/pageout, so ignore this case.
5433 1.6 mycroft */
5434 1.42 fvdl if ((scb->hscb->control & DISCONNECTED) == 0) {
5435 1.42 fvdl u_int32_t resid;
5436 1.42 fvdl int resid_sgs;
5437 1.42 fvdl int sg;
5438 1.42 fvdl
5439 1.42 fvdl /*
5440 1.42 fvdl * Remainder of the SG where the transfer
5441 1.42 fvdl * stopped.
5442 1.42 fvdl */
5443 1.42 fvdl resid = (hscb->residual_data_count[2] << 16)
5444 1.42 fvdl | (hscb->residual_data_count[1] <<8)
5445 1.42 fvdl | (hscb->residual_data_count[0]);
5446 1.1 mycroft
5447 1.6 mycroft /*
5448 1.42 fvdl * Add up the contents of all residual
5449 1.42 fvdl * SG segments that are after the SG where
5450 1.42 fvdl * the transfer stopped.
5451 1.6 mycroft */
5452 1.42 fvdl resid_sgs = scb->hscb->residual_SG_count - 1/*current*/;
5453 1.42 fvdl sg = scb->sg_count - resid_sgs;
5454 1.42 fvdl while (resid_sgs > 0) {
5455 1.42 fvdl
5456 1.42 fvdl resid += le32toh(scb->sg_list[sg].len);
5457 1.42 fvdl sg++;
5458 1.42 fvdl resid_sgs--;
5459 1.6 mycroft }
5460 1.42 fvdl scb->xs->resid = resid;
5461 1.42 fvdl }
5462 1.42 fvdl
5463 1.42 fvdl /*
5464 1.42 fvdl * Clean out the residual information in this SCB for its
5465 1.42 fvdl * next consumer.
5466 1.42 fvdl */
5467 1.42 fvdl hscb->residual_SG_count = 0;
5468 1.42 fvdl
5469 1.42 fvdl #ifdef AHC_DEBUG
5470 1.42 fvdl if (ahc_debug & AHC_SHOWMISC) {
5471 1.42 fvdl scsi_print_addr(scb->xs->sc_link);
5472 1.42 fvdl printf("Handled Residual of %ld bytes\n" ,(long)scb->xs->resid);
5473 1.42 fvdl }
5474 1.42 fvdl #endif
5475 1.42 fvdl }
5476 1.42 fvdl
5477 1.42 fvdl static void
5478 1.42 fvdl ahc_update_pending_syncrates(struct ahc_softc *ahc)
5479 1.42 fvdl {
5480 1.42 fvdl struct scb *scb;
5481 1.42 fvdl int pending_ccb_count;
5482 1.42 fvdl int i;
5483 1.42 fvdl u_int saved_scbptr;
5484 1.42 fvdl
5485 1.42 fvdl /*
5486 1.42 fvdl * Traverse the pending SCB list and ensure that all of the
5487 1.42 fvdl * SCBs there have the proper settings.
5488 1.42 fvdl */
5489 1.42 fvdl scb = LIST_FIRST(&ahc->pending_ccbs);
5490 1.42 fvdl pending_ccb_count = 0;
5491 1.42 fvdl while (scb != NULL) {
5492 1.42 fvdl struct ahc_devinfo devinfo;
5493 1.42 fvdl struct scsipi_xfer *xs;
5494 1.42 fvdl struct scb *pending_scb;
5495 1.42 fvdl struct hardware_scb *pending_hscb;
5496 1.42 fvdl struct ahc_initiator_tinfo *tinfo;
5497 1.42 fvdl struct tmode_tstate *tstate;
5498 1.42 fvdl u_int our_id, remote_id;
5499 1.42 fvdl
5500 1.42 fvdl xs = scb->xs;
5501 1.42 fvdl pending_scb = scb;
5502 1.42 fvdl pending_hscb = pending_scb->hscb;
5503 1.42 fvdl our_id = SCB_IS_SCSIBUS_B(pending_scb)
5504 1.42 fvdl ? ahc->our_id_b : ahc->our_id;
5505 1.42 fvdl remote_id = xs->sc_link->scsipi_scsi.target;
5506 1.42 fvdl ahc_compile_devinfo(&devinfo, our_id, remote_id,
5507 1.42 fvdl SCB_LUN(pending_scb),
5508 1.42 fvdl SCB_CHANNEL(pending_scb),
5509 1.42 fvdl ROLE_UNKNOWN);
5510 1.42 fvdl tinfo = ahc_fetch_transinfo(ahc, devinfo.channel,
5511 1.42 fvdl our_id, remote_id, &tstate);
5512 1.42 fvdl pending_hscb->control &= ~ULTRAENB;
5513 1.42 fvdl if ((tstate->ultraenb & devinfo.target_mask) != 0)
5514 1.42 fvdl pending_hscb->control |= ULTRAENB;
5515 1.42 fvdl pending_hscb->scsirate = tinfo->scsirate;
5516 1.42 fvdl pending_hscb->scsioffset = tinfo->current.offset;
5517 1.42 fvdl pending_ccb_count++;
5518 1.42 fvdl scb = LIST_NEXT(scb, plinks);
5519 1.42 fvdl }
5520 1.42 fvdl
5521 1.42 fvdl if (pending_ccb_count == 0)
5522 1.42 fvdl return;
5523 1.42 fvdl
5524 1.42 fvdl saved_scbptr = ahc_inb(ahc, SCBPTR);
5525 1.42 fvdl /* Ensure that the hscbs down on the card match the new information */
5526 1.42 fvdl for (i = 0; i < ahc->scb_data->maxhscbs; i++) {
5527 1.42 fvdl u_int scb_tag;
5528 1.42 fvdl
5529 1.42 fvdl ahc_outb(ahc, SCBPTR, i);
5530 1.42 fvdl scb_tag = ahc_inb(ahc, SCB_TAG);
5531 1.42 fvdl if (scb_tag != SCB_LIST_NULL) {
5532 1.42 fvdl struct ahc_devinfo devinfo;
5533 1.42 fvdl struct scb *pending_scb;
5534 1.42 fvdl struct scsipi_xfer *xs;
5535 1.42 fvdl struct hardware_scb *pending_hscb;
5536 1.42 fvdl struct ahc_initiator_tinfo *tinfo;
5537 1.42 fvdl struct tmode_tstate *tstate;
5538 1.42 fvdl u_int our_id, remote_id;
5539 1.42 fvdl u_int control;
5540 1.42 fvdl
5541 1.42 fvdl pending_scb = &ahc->scb_data->scbarray[scb_tag];
5542 1.42 fvdl if (pending_scb->flags == SCB_FREE)
5543 1.42 fvdl continue;
5544 1.42 fvdl pending_hscb = pending_scb->hscb;
5545 1.42 fvdl xs = pending_scb->xs;
5546 1.42 fvdl our_id = SCB_IS_SCSIBUS_B(pending_scb)
5547 1.42 fvdl ? ahc->our_id_b : ahc->our_id;
5548 1.42 fvdl remote_id = xs->sc_link->scsipi_scsi.target;
5549 1.42 fvdl ahc_compile_devinfo(&devinfo, our_id, remote_id,
5550 1.42 fvdl SCB_LUN(pending_scb),
5551 1.42 fvdl SCB_CHANNEL(pending_scb),
5552 1.42 fvdl ROLE_UNKNOWN);
5553 1.42 fvdl tinfo = ahc_fetch_transinfo(ahc, devinfo.channel,
5554 1.42 fvdl our_id, remote_id, &tstate);
5555 1.42 fvdl control = ahc_inb(ahc, SCB_CONTROL);
5556 1.42 fvdl control &= ~ULTRAENB;
5557 1.42 fvdl if ((tstate->ultraenb & devinfo.target_mask) != 0)
5558 1.42 fvdl control |= ULTRAENB;
5559 1.42 fvdl ahc_outb(ahc, SCB_CONTROL, control);
5560 1.42 fvdl ahc_outb(ahc, SCB_SCSIRATE, tinfo->scsirate);
5561 1.42 fvdl ahc_outb(ahc, SCB_SCSIOFFSET, tinfo->current.offset);
5562 1.6 mycroft }
5563 1.1 mycroft }
5564 1.42 fvdl ahc_outb(ahc, SCBPTR, saved_scbptr);
5565 1.6 mycroft }
5566 1.1 mycroft
5567 1.42 fvdl #if UNUSED
5568 1.42 fvdl static void
5569 1.42 fvdl ahc_dump_targcmd(struct target_cmd *cmd)
5570 1.6 mycroft {
5571 1.42 fvdl u_int8_t *byte;
5572 1.42 fvdl u_int8_t *last_byte;
5573 1.6 mycroft int i;
5574 1.42 fvdl
5575 1.42 fvdl byte = &cmd->initiator_channel;
5576 1.42 fvdl /* Debugging info for received commands */
5577 1.42 fvdl last_byte = &cmd[1].initiator_channel;
5578 1.42 fvdl
5579 1.42 fvdl i = 0;
5580 1.42 fvdl while (byte < last_byte) {
5581 1.42 fvdl if (i == 0)
5582 1.42 fvdl printf("\t");
5583 1.42 fvdl printf("%#x", *byte++);
5584 1.42 fvdl i++;
5585 1.42 fvdl if (i == 8) {
5586 1.42 fvdl printf("\n");
5587 1.42 fvdl i = 0;
5588 1.42 fvdl } else {
5589 1.42 fvdl printf(", ");
5590 1.42 fvdl }
5591 1.1 mycroft }
5592 1.6 mycroft }
5593 1.42 fvdl #endif
5594 1.42 fvdl
5595 1.42 fvdl static void
5596 1.42 fvdl ahc_shutdown(void *arg)
5597 1.6 mycroft {
5598 1.42 fvdl struct ahc_softc *ahc;
5599 1.42 fvdl int i;
5600 1.42 fvdl u_int sxfrctl1_a, sxfrctl1_b;
5601 1.42 fvdl
5602 1.42 fvdl ahc = (struct ahc_softc *)arg;
5603 1.42 fvdl
5604 1.42 fvdl pause_sequencer(ahc);
5605 1.42 fvdl
5606 1.42 fvdl /*
5607 1.42 fvdl * Preserve the value of the SXFRCTL1 register for all channels.
5608 1.42 fvdl * It contains settings that affect termination and we don't want
5609 1.42 fvdl * to disturb the integrity of the bus during shutdown in case
5610 1.42 fvdl * we are in a multi-initiator setup.
5611 1.42 fvdl */
5612 1.42 fvdl sxfrctl1_b = 0;
5613 1.42 fvdl if ((ahc->features & AHC_TWIN) != 0) {
5614 1.42 fvdl u_int sblkctl;
5615 1.42 fvdl
5616 1.42 fvdl sblkctl = ahc_inb(ahc, SBLKCTL);
5617 1.42 fvdl ahc_outb(ahc, SBLKCTL, sblkctl | SELBUSB);
5618 1.42 fvdl sxfrctl1_b = ahc_inb(ahc, SXFRCTL1);
5619 1.42 fvdl ahc_outb(ahc, SBLKCTL, sblkctl & ~SELBUSB);
5620 1.42 fvdl }
5621 1.42 fvdl
5622 1.42 fvdl sxfrctl1_a = ahc_inb(ahc, SXFRCTL1);
5623 1.42 fvdl
5624 1.42 fvdl /* This will reset most registers to 0, but not all */
5625 1.42 fvdl ahc_reset(ahc);
5626 1.1 mycroft
5627 1.42 fvdl if ((ahc->features & AHC_TWIN) != 0) {
5628 1.42 fvdl u_int sblkctl;
5629 1.42 fvdl
5630 1.42 fvdl sblkctl = ahc_inb(ahc, SBLKCTL);
5631 1.42 fvdl ahc_outb(ahc, SBLKCTL, sblkctl | SELBUSB);
5632 1.42 fvdl ahc_outb(ahc, SXFRCTL1, sxfrctl1_b);
5633 1.42 fvdl ahc_outb(ahc, SBLKCTL, sblkctl & ~SELBUSB);
5634 1.42 fvdl }
5635 1.42 fvdl ahc_outb(ahc, SXFRCTL1, sxfrctl1_a);
5636 1.14 gibbs
5637 1.42 fvdl ahc_outb(ahc, SCSISEQ, 0);
5638 1.42 fvdl ahc_outb(ahc, SXFRCTL0, 0);
5639 1.42 fvdl ahc_outb(ahc, DSPCISTATUS, 0);
5640 1.14 gibbs
5641 1.42 fvdl for (i = TARG_SCSIRATE; i < HA_274_BIOSCTRL; i++)
5642 1.42 fvdl ahc_outb(ahc, i, 0);
5643 1.14 gibbs }
5644 1.14 gibbs
5645 1.42 fvdl #if defined(AHC_DEBUG) && 0
5646 1.14 gibbs static void
5647 1.42 fvdl ahc_dumptinfo(struct ahc_softc *ahc, struct ahc_initiator_tinfo *tinfo)
5648 1.14 gibbs {
5649 1.42 fvdl printf("%s: tinfo: rate %u\n", ahc_name(ahc), tinfo->scsirate);
5650 1.42 fvdl
5651 1.42 fvdl printf("\tcurrent:\n");
5652 1.42 fvdl printf("\t\twidth %u period %u offset %u flags %x\n",
5653 1.42 fvdl tinfo->current.width, tinfo->current.period,
5654 1.42 fvdl tinfo->current.offset, tinfo->current.ppr_flags);
5655 1.42 fvdl
5656 1.42 fvdl printf("\tgoal:\n");
5657 1.42 fvdl printf("\t\twidth %u period %u offset %u flags %x\n",
5658 1.42 fvdl tinfo->goal.width, tinfo->goal.period,
5659 1.42 fvdl tinfo->goal.offset, tinfo->goal.ppr_flags);
5660 1.42 fvdl
5661 1.42 fvdl printf("\tuser:\n");
5662 1.42 fvdl printf("\t\twidth %u period %u offset %u flags %x\n",
5663 1.42 fvdl tinfo->user.width, tinfo->user.period,
5664 1.42 fvdl tinfo->user.offset, tinfo->user.ppr_flags);
5665 1.1 mycroft }
5666 1.42 fvdl #endif
5667 1.45 fvdl
5668 1.45 fvdl static void
5669 1.45 fvdl ahc_check_tags(struct ahc_softc *ahc, struct scsipi_xfer *xs)
5670 1.45 fvdl {
5671 1.45 fvdl struct scsipi_inquiry_data *inq;
5672 1.45 fvdl struct ahc_devinfo devinfo;
5673 1.49 fvdl struct tmode_tstate *tstate;
5674 1.45 fvdl int target_id, our_id;
5675 1.49 fvdl char channel;
5676 1.45 fvdl
5677 1.45 fvdl if (xs->cmd->opcode != INQUIRY || xs->error != XS_NOERROR)
5678 1.45 fvdl return;
5679 1.45 fvdl
5680 1.49 fvdl if (xs->sc_link->quirks & SDEV_NOTAG)
5681 1.49 fvdl return;
5682 1.49 fvdl
5683 1.45 fvdl target_id = xs->sc_link->scsipi_scsi.target;
5684 1.45 fvdl our_id = SIM_SCSI_ID(ahc, xs->sc_link);
5685 1.49 fvdl channel = SIM_CHANNEL(ahc, xs->sc_link);
5686 1.49 fvdl
5687 1.49 fvdl (void)ahc_fetch_transinfo(ahc, channel, our_id, target_id, &tstate);
5688 1.49 fvdl ahc_compile_devinfo(&devinfo, our_id, target_id,
5689 1.49 fvdl xs->sc_link->scsipi_scsi.lun, channel, ROLE_INITIATOR);
5690 1.49 fvdl
5691 1.49 fvdl if (tstate->tagdisable & devinfo.target_mask)
5692 1.49 fvdl return;
5693 1.45 fvdl
5694 1.45 fvdl /*
5695 1.45 fvdl * Sneak a look at the results of the SCSI Inquiry
5696 1.45 fvdl * command and see if we can do Tagged queing. This
5697 1.45 fvdl * should really be done by the higher level drivers.
5698 1.45 fvdl */
5699 1.45 fvdl inq = (struct scsipi_inquiry_data *)xs->data;
5700 1.51 fvdl if ((inq->flags3 & SID_CmdQue) && !(ahc_istagged_device(ahc, xs, 1))) {
5701 1.45 fvdl printf("%s: target %d using tagged queuing\n",
5702 1.45 fvdl ahc_name(ahc), xs->sc_link->scsipi_scsi.target);
5703 1.45 fvdl
5704 1.45 fvdl ahc_set_tags(ahc, &devinfo, TRUE);
5705 1.45 fvdl
5706 1.45 fvdl if (ahc->scb_data->maxhscbs >= 16 ||
5707 1.45 fvdl (ahc->flags & AHC_PAGESCBS)) {
5708 1.46 fvdl /* Default to 16 tags */
5709 1.49 fvdl xs->sc_link->openings = 16;
5710 1.45 fvdl } else {
5711 1.45 fvdl /*
5712 1.45 fvdl * Default to 4 tags on whimpy
5713 1.45 fvdl * cards that don't have much SCB
5714 1.45 fvdl * space and can't page. This prevents
5715 1.45 fvdl * a single device from hogging all
5716 1.45 fvdl * slots. We should really have a better
5717 1.45 fvdl * way of providing fairness.
5718 1.45 fvdl */
5719 1.49 fvdl xs->sc_link->openings = 4;
5720 1.45 fvdl }
5721 1.45 fvdl }
5722 1.45 fvdl }
5723 1.45 fvdl
5724 1.45 fvdl static int
5725 1.51 fvdl ahc_istagged_device(struct ahc_softc *ahc, struct scsipi_xfer *xs,
5726 1.51 fvdl int nocmdcheck)
5727 1.45 fvdl {
5728 1.45 fvdl char channel;
5729 1.45 fvdl u_int our_id, target;
5730 1.45 fvdl struct tmode_tstate *tstate;
5731 1.45 fvdl struct ahc_devinfo devinfo;
5732 1.49 fvdl
5733 1.49 fvdl if (xs->sc_link->quirks & SDEV_NOTAG)
5734 1.51 fvdl return 0;
5735 1.51 fvdl
5736 1.51 fvdl /*
5737 1.51 fvdl * XXX never do these commands with tags. Should really be
5738 1.51 fvdl * in a higher layer.
5739 1.51 fvdl */
5740 1.51 fvdl if (!nocmdcheck && (xs->cmd->opcode == INQUIRY ||
5741 1.51 fvdl xs->cmd->opcode == TEST_UNIT_READY ||
5742 1.51 fvdl xs->cmd->opcode == REQUEST_SENSE))
5743 1.49 fvdl return 0;
5744 1.45 fvdl
5745 1.45 fvdl channel = SIM_CHANNEL(ahc, xs->sc_link);
5746 1.45 fvdl our_id = SIM_SCSI_ID(ahc, xs->sc_link);
5747 1.45 fvdl target = xs->sc_link->scsipi_scsi.target;
5748 1.45 fvdl (void)ahc_fetch_transinfo(ahc, channel, our_id, target, &tstate);
5749 1.45 fvdl
5750 1.45 fvdl ahc_compile_devinfo(&devinfo, our_id, target,
5751 1.45 fvdl xs->sc_link->scsipi_scsi.lun, channel, ROLE_INITIATOR);
5752 1.45 fvdl
5753 1.45 fvdl return (tstate->tagenable & devinfo.target_mask);
5754 1.45 fvdl }
5755