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