1 1.43 andvar /* $NetBSD: aic7xxx_osm.c,v 1.43 2023/08/01 21:26:28 andvar Exp $ */ 2 1.2 fvdl 3 1.1 fvdl /* 4 1.1 fvdl * Bus independent FreeBSD shim for the aic7xxx based adaptec SCSI controllers 5 1.1 fvdl * 6 1.1 fvdl * Copyright (c) 1994-2001 Justin T. Gibbs. 7 1.1 fvdl * All rights reserved. 8 1.1 fvdl * 9 1.1 fvdl * Redistribution and use in source and binary forms, with or without 10 1.1 fvdl * modification, are permitted provided that the following conditions 11 1.1 fvdl * are met: 12 1.1 fvdl * 1. Redistributions of source code must retain the above copyright 13 1.1 fvdl * notice, this list of conditions, and the following disclaimer, 14 1.1 fvdl * without modification. 15 1.1 fvdl * 2. The name of the author may not be used to endorse or promote products 16 1.1 fvdl * derived from this software without specific prior written permission. 17 1.1 fvdl * 18 1.1 fvdl * Alternatively, this software may be distributed under the terms of the 19 1.1 fvdl * GNU Public License ("GPL"). 20 1.1 fvdl * 21 1.1 fvdl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 22 1.1 fvdl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 1.1 fvdl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 1.1 fvdl * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 25 1.1 fvdl * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 1.1 fvdl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 1.1 fvdl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 1.1 fvdl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 1.1 fvdl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 1.1 fvdl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 1.1 fvdl * SUCH DAMAGE. 32 1.1 fvdl * 33 1.1 fvdl * //depot/aic7xxx/freebsd/dev/aic7xxx/aic7xxx_osm.c#12 $ 34 1.1 fvdl * 35 1.1 fvdl * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx_osm.c,v 1.31 2002/11/30 19:08:58 scottl Exp $ 36 1.1 fvdl */ 37 1.1 fvdl /* 38 1.1 fvdl * Ported from FreeBSD by Pascal Renauld, Network Storage Solutions, Inc. - April 2003 39 1.1 fvdl */ 40 1.10 lukem 41 1.10 lukem #include <sys/cdefs.h> 42 1.43 andvar __KERNEL_RCSID(0, "$NetBSD: aic7xxx_osm.c,v 1.43 2023/08/01 21:26:28 andvar Exp $"); 43 1.10 lukem 44 1.1 fvdl #include <dev/ic/aic7xxx_osm.h> 45 1.1 fvdl #include <dev/ic/aic7xxx_inline.h> 46 1.1 fvdl 47 1.1 fvdl #ifndef AHC_TMODE_ENABLE 48 1.1 fvdl #define AHC_TMODE_ENABLE 0 49 1.1 fvdl #endif 50 1.1 fvdl 51 1.1 fvdl 52 1.35 tsutsui static void ahc_action(struct scsipi_channel *chan, 53 1.35 tsutsui scsipi_adapter_req_t req, void *arg); 54 1.35 tsutsui static void ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, 55 1.35 tsutsui int nsegments); 56 1.1 fvdl static int ahc_poll(struct ahc_softc *ahc, int wait); 57 1.1 fvdl static void ahc_setup_data(struct ahc_softc *ahc, 58 1.1 fvdl struct scsipi_xfer *xs, struct scb *scb); 59 1.1 fvdl static void ahc_set_recoveryscb(struct ahc_softc *ahc, struct scb *scb); 60 1.21 tsutsui static int ahc_ioctl(struct scsipi_channel *channel, u_long cmd, 61 1.25 christos void *addr, int flag, struct proc *p); 62 1.1 fvdl 63 1.37 dyoung static bool ahc_pmf_suspend(device_t, const pmf_qual_t *); 64 1.37 dyoung static bool ahc_pmf_resume(device_t, const pmf_qual_t *); 65 1.33 tsutsui static bool ahc_pmf_shutdown(device_t, int); 66 1.1 fvdl 67 1.1 fvdl 68 1.1 fvdl /* 69 1.1 fvdl * Attach all the sub-devices we can find 70 1.1 fvdl */ 71 1.1 fvdl int 72 1.1 fvdl ahc_attach(struct ahc_softc *ahc) 73 1.1 fvdl { 74 1.1 fvdl u_long s; 75 1.1 fvdl int i; 76 1.1 fvdl char ahc_info[256]; 77 1.1 fvdl 78 1.1 fvdl LIST_INIT(&ahc->pending_scbs); 79 1.1 fvdl for (i = 0; i < AHC_NUM_TARGETS; i++) 80 1.1 fvdl TAILQ_INIT(&ahc->untagged_queues[i]); 81 1.1 fvdl 82 1.21 tsutsui ahc_lock(ahc, &s); 83 1.1 fvdl 84 1.28 cegger ahc->sc_adapter.adapt_dev = ahc->sc_dev; 85 1.1 fvdl ahc->sc_adapter.adapt_nchannels = (ahc->features & AHC_TWIN) ? 2 : 1; 86 1.16 perry 87 1.19 bouyer ahc->sc_adapter.adapt_openings = ahc->scb_data->numscbs - 1; 88 1.1 fvdl ahc->sc_adapter.adapt_max_periph = 16; 89 1.1 fvdl 90 1.1 fvdl ahc->sc_adapter.adapt_ioctl = ahc_ioctl; 91 1.1 fvdl ahc->sc_adapter.adapt_minphys = ahc_minphys; 92 1.1 fvdl ahc->sc_adapter.adapt_request = ahc_action; 93 1.1 fvdl 94 1.1 fvdl ahc->sc_channel.chan_adapter = &ahc->sc_adapter; 95 1.21 tsutsui ahc->sc_channel.chan_bustype = &scsi_bustype; 96 1.21 tsutsui ahc->sc_channel.chan_channel = 0; 97 1.21 tsutsui ahc->sc_channel.chan_ntargets = (ahc->features & AHC_WIDE) ? 16 : 8; 98 1.21 tsutsui ahc->sc_channel.chan_nluns = 8 /*AHC_NUM_LUNS*/; 99 1.21 tsutsui ahc->sc_channel.chan_id = ahc->our_id; 100 1.19 bouyer ahc->sc_channel.chan_flags |= SCSIPI_CHAN_CANGROW; 101 1.1 fvdl 102 1.1 fvdl if (ahc->features & AHC_TWIN) { 103 1.1 fvdl ahc->sc_channel_b = ahc->sc_channel; 104 1.1 fvdl ahc->sc_channel_b.chan_id = ahc->our_id_b; 105 1.1 fvdl ahc->sc_channel_b.chan_channel = 1; 106 1.1 fvdl } 107 1.1 fvdl 108 1.15 itojun ahc_controller_info(ahc, ahc_info, sizeof(ahc_info)); 109 1.28 cegger printf("%s: %s\n", device_xname(ahc->sc_dev), ahc_info); 110 1.1 fvdl 111 1.1 fvdl if ((ahc->flags & AHC_PRIMARY_CHANNEL) == 0) { 112 1.28 cegger ahc->sc_child = config_found(ahc->sc_dev, 113 1.41 thorpej &ahc->sc_channel, scsiprint, CFARGS_NONE); 114 1.1 fvdl if (ahc->features & AHC_TWIN) 115 1.28 cegger ahc->sc_child_b = config_found(ahc->sc_dev, 116 1.41 thorpej &ahc->sc_channel_b, scsiprint, CFARGS_NONE); 117 1.1 fvdl } else { 118 1.8 fvdl if (ahc->features & AHC_TWIN) 119 1.28 cegger ahc->sc_child = config_found(ahc->sc_dev, 120 1.41 thorpej &ahc->sc_channel_b, scsiprint, CFARGS_NONE); 121 1.28 cegger ahc->sc_child_b = config_found(ahc->sc_dev, 122 1.41 thorpej &ahc->sc_channel, scsiprint, CFARGS_NONE); 123 1.1 fvdl } 124 1.1 fvdl 125 1.1 fvdl ahc_intr_enable(ahc, TRUE); 126 1.1 fvdl 127 1.7 fvdl if (ahc->flags & AHC_RESET_BUS_A) 128 1.7 fvdl ahc_reset_channel(ahc, 'A', TRUE); 129 1.7 fvdl if ((ahc->features & AHC_TWIN) && ahc->flags & AHC_RESET_BUS_B) 130 1.7 fvdl ahc_reset_channel(ahc, 'B', TRUE); 131 1.7 fvdl 132 1.33 tsutsui if (!pmf_device_register1(ahc->sc_dev, 133 1.33 tsutsui ahc_pmf_suspend, ahc_pmf_resume, ahc_pmf_shutdown)) 134 1.32 tsutsui aprint_error_dev(ahc->sc_dev, 135 1.32 tsutsui "couldn't establish power handler\n"); 136 1.32 tsutsui 137 1.1 fvdl ahc_unlock(ahc, &s); 138 1.1 fvdl return (1); 139 1.1 fvdl } 140 1.1 fvdl 141 1.1 fvdl /* 142 1.32 tsutsui * XXX we should call the real suspend and resume functions here 143 1.33 tsutsui * but pmf(9) stuff on cardbus backend is untested yet 144 1.32 tsutsui */ 145 1.32 tsutsui 146 1.32 tsutsui static bool 147 1.37 dyoung ahc_pmf_suspend(device_t dev, const pmf_qual_t *qual) 148 1.32 tsutsui { 149 1.32 tsutsui struct ahc_softc *sc = device_private(dev); 150 1.32 tsutsui #if 0 151 1.32 tsutsui return (ahc_suspend(sc) == 0); 152 1.32 tsutsui #else 153 1.32 tsutsui ahc_shutdown(sc); 154 1.32 tsutsui return true; 155 1.32 tsutsui #endif 156 1.32 tsutsui } 157 1.32 tsutsui 158 1.32 tsutsui static bool 159 1.37 dyoung ahc_pmf_resume(device_t dev, const pmf_qual_t *qual) 160 1.32 tsutsui { 161 1.32 tsutsui #if 0 162 1.32 tsutsui struct ahc_softc *sc = device_private(dev); 163 1.32 tsutsui 164 1.32 tsutsui return (ahc_resume(sc) == 0); 165 1.32 tsutsui #else 166 1.32 tsutsui return true; 167 1.32 tsutsui #endif 168 1.32 tsutsui } 169 1.32 tsutsui 170 1.33 tsutsui static bool 171 1.33 tsutsui ahc_pmf_shutdown(device_t dev, int howto) 172 1.33 tsutsui { 173 1.33 tsutsui struct ahc_softc *sc = device_private(dev); 174 1.33 tsutsui 175 1.33 tsutsui /* Disable all interrupt sources by resetting the controller */ 176 1.33 tsutsui ahc_shutdown(sc); 177 1.33 tsutsui 178 1.33 tsutsui return true; 179 1.33 tsutsui } 180 1.33 tsutsui 181 1.32 tsutsui /* 182 1.1 fvdl * Catch an interrupt from the adapter 183 1.1 fvdl */ 184 1.1 fvdl void 185 1.1 fvdl ahc_platform_intr(void *arg) 186 1.1 fvdl { 187 1.1 fvdl struct ahc_softc *ahc; 188 1.1 fvdl 189 1.35 tsutsui ahc = arg; 190 1.1 fvdl ahc_intr(ahc); 191 1.1 fvdl } 192 1.1 fvdl 193 1.1 fvdl /* 194 1.1 fvdl * We have an scb which has been processed by the 195 1.1 fvdl * adaptor, now we look to see how the operation 196 1.1 fvdl * went. 197 1.1 fvdl */ 198 1.1 fvdl void 199 1.1 fvdl ahc_done(struct ahc_softc *ahc, struct scb *scb) 200 1.1 fvdl { 201 1.1 fvdl struct scsipi_xfer *xs; 202 1.21 tsutsui struct scsipi_periph *periph; 203 1.1 fvdl u_long s; 204 1.1 fvdl 205 1.1 fvdl xs = scb->xs; 206 1.1 fvdl periph = xs->xs_periph; 207 1.1 fvdl LIST_REMOVE(scb, pending_links); 208 1.1 fvdl if ((scb->flags & SCB_UNTAGGEDQ) != 0) { 209 1.1 fvdl struct scb_tailq *untagged_q; 210 1.1 fvdl int target_offset; 211 1.1 fvdl 212 1.1 fvdl target_offset = SCB_GET_TARGET_OFFSET(ahc, scb); 213 1.1 fvdl untagged_q = &ahc->untagged_queues[target_offset]; 214 1.1 fvdl TAILQ_REMOVE(untagged_q, scb, links.tqe); 215 1.1 fvdl scb->flags &= ~SCB_UNTAGGEDQ; 216 1.1 fvdl ahc_run_untagged_queue(ahc, untagged_q); 217 1.1 fvdl } 218 1.1 fvdl 219 1.1 fvdl callout_stop(&scb->xs->xs_callout); 220 1.1 fvdl 221 1.1 fvdl if (xs->datalen) { 222 1.1 fvdl int op; 223 1.1 fvdl 224 1.1 fvdl if (xs->xs_control & XS_CTL_DATA_IN) 225 1.1 fvdl op = BUS_DMASYNC_POSTREAD; 226 1.1 fvdl else 227 1.1 fvdl op = BUS_DMASYNC_POSTWRITE; 228 1.1 fvdl bus_dmamap_sync(ahc->parent_dmat, scb->dmamap, 0, 229 1.1 fvdl scb->dmamap->dm_mapsize, op); 230 1.1 fvdl bus_dmamap_unload(ahc->parent_dmat, scb->dmamap); 231 1.1 fvdl } 232 1.1 fvdl 233 1.1 fvdl /* 234 1.1 fvdl * If the recovery SCB completes, we have to be 235 1.1 fvdl * out of our timeout. 236 1.1 fvdl */ 237 1.1 fvdl if ((scb->flags & SCB_RECOVERY_SCB) != 0) { 238 1.1 fvdl struct scb *list_scb; 239 1.1 fvdl 240 1.1 fvdl /* 241 1.1 fvdl * We were able to complete the command successfully, 242 1.1 fvdl * so reinstate the timeouts for all other pending 243 1.1 fvdl * commands. 244 1.1 fvdl */ 245 1.1 fvdl LIST_FOREACH(list_scb, &ahc->pending_scbs, pending_links) { 246 1.17 christos if (!(list_scb->xs->xs_control & XS_CTL_POLL)) { 247 1.1 fvdl callout_reset(&list_scb->xs->xs_callout, 248 1.1 fvdl (list_scb->xs->timeout > 1000000) ? 249 1.16 perry (list_scb->xs->timeout / 1000) * hz : 250 1.1 fvdl (list_scb->xs->timeout * hz) / 1000, 251 1.1 fvdl ahc_timeout, list_scb); 252 1.1 fvdl } 253 1.1 fvdl } 254 1.1 fvdl 255 1.1 fvdl if (ahc_get_transaction_status(scb) == CAM_BDR_SENT 256 1.1 fvdl || ahc_get_transaction_status(scb) == CAM_REQ_ABORTED) 257 1.1 fvdl ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); 258 1.1 fvdl scsipi_printaddr(xs->xs_periph); 259 1.16 perry printf("%s: no longer in timeout, status = %x\n", 260 1.1 fvdl ahc_name(ahc), xs->status); 261 1.38 mlelstv 262 1.38 mlelstv scsipi_channel_thaw(&ahc->sc_channel, 1); 263 1.38 mlelstv if (ahc->features & AHC_TWIN) 264 1.38 mlelstv scsipi_channel_thaw(&ahc->sc_channel_b, 1); 265 1.1 fvdl } 266 1.1 fvdl 267 1.1 fvdl /* Don't clobber any existing error state */ 268 1.1 fvdl if (xs->error != XS_NOERROR) { 269 1.1 fvdl /* Don't clobber any existing error state */ 270 1.1 fvdl } else if ((scb->flags & SCB_SENSE) != 0) { 271 1.1 fvdl /* 272 1.1 fvdl * We performed autosense retrieval. 273 1.1 fvdl * 274 1.1 fvdl * Zero any sense not transferred by the 275 1.1 fvdl * device. The SCSI spec mandates that any 276 1.14 wiz * untransferred data should be assumed to be 277 1.1 fvdl * zero. Complete the 'bounce' of sense information 278 1.1 fvdl * through buffers accessible via bus-space by 279 1.1 fvdl * copying it into the clients csio. 280 1.1 fvdl */ 281 1.1 fvdl memset(&xs->sense.scsi_sense, 0, sizeof(xs->sense.scsi_sense)); 282 1.1 fvdl memcpy(&xs->sense.scsi_sense, 283 1.1 fvdl ahc_get_sense_buf(ahc, scb), 284 1.1 fvdl sizeof(xs->sense.scsi_sense)); 285 1.1 fvdl xs->error = XS_SENSE; 286 1.1 fvdl } 287 1.1 fvdl if (scb->flags & SCB_FREEZE_QUEUE) { 288 1.1 fvdl scsipi_periph_thaw(periph, 1); 289 1.1 fvdl scb->flags &= ~SCB_FREEZE_QUEUE; 290 1.1 fvdl } 291 1.1 fvdl 292 1.21 tsutsui ahc_lock(ahc, &s); 293 1.1 fvdl ahc_free_scb(ahc, scb); 294 1.21 tsutsui ahc_unlock(ahc, &s); 295 1.1 fvdl 296 1.1 fvdl scsipi_done(xs); 297 1.1 fvdl } 298 1.1 fvdl 299 1.1 fvdl static int 300 1.25 christos ahc_ioctl(struct scsipi_channel *channel, u_long cmd, void *addr, 301 1.24 christos int flag, struct proc *p) 302 1.1 fvdl { 303 1.35 tsutsui struct ahc_softc *ahc; 304 1.1 fvdl int s, ret = ENOTTY; 305 1.1 fvdl 306 1.35 tsutsui ahc = device_private(channel->chan_adapter->adapt_dev); 307 1.35 tsutsui 308 1.1 fvdl switch (cmd) { 309 1.1 fvdl case SCBUSIORESET: 310 1.1 fvdl s = splbio(); 311 1.5 fvdl ahc_reset_channel(ahc, channel->chan_channel == 1 ? 'B' : 'A', 312 1.5 fvdl TRUE); 313 1.1 fvdl splx(s); 314 1.1 fvdl ret = 0; 315 1.1 fvdl break; 316 1.1 fvdl default: 317 1.1 fvdl break; 318 1.1 fvdl } 319 1.1 fvdl 320 1.1 fvdl return ret; 321 1.1 fvdl } 322 1.1 fvdl 323 1.1 fvdl static void 324 1.1 fvdl ahc_action(struct scsipi_channel *chan, scsipi_adapter_req_t req, void *arg) 325 1.1 fvdl { 326 1.1 fvdl struct ahc_softc *ahc; 327 1.1 fvdl int s; 328 1.1 fvdl struct ahc_initiator_tinfo *tinfo; 329 1.1 fvdl struct ahc_tmode_tstate *tstate; 330 1.1 fvdl 331 1.29 rjs ahc = device_private(chan->chan_adapter->adapt_dev); 332 1.4 fvdl 333 1.1 fvdl switch (req) { 334 1.1 fvdl 335 1.1 fvdl case ADAPTER_REQ_RUN_XFER: 336 1.1 fvdl { 337 1.1 fvdl struct scsipi_xfer *xs; 338 1.1 fvdl struct scsipi_periph *periph; 339 1.21 tsutsui struct scb *scb; 340 1.21 tsutsui struct hardware_scb *hscb; 341 1.1 fvdl u_int target_id; 342 1.1 fvdl u_int our_id; 343 1.17 christos u_long ss; 344 1.1 fvdl 345 1.1 fvdl xs = arg; 346 1.1 fvdl periph = xs->xs_periph; 347 1.1 fvdl 348 1.1 fvdl target_id = periph->periph_target; 349 1.21 tsutsui our_id = ahc->our_id; 350 1.1 fvdl 351 1.1 fvdl SC_DEBUG(xs->xs_periph, SCSIPI_DB3, ("ahc_action\n")); 352 1.1 fvdl 353 1.1 fvdl /* 354 1.1 fvdl * get an scb to use. 355 1.1 fvdl */ 356 1.17 christos ahc_lock(ahc, &ss); 357 1.16 perry if ((scb = ahc_get_scb(ahc)) == NULL) { 358 1.1 fvdl xs->error = XS_RESOURCE_SHORTAGE; 359 1.17 christos ahc_unlock(ahc, &ss); 360 1.1 fvdl scsipi_done(xs); 361 1.1 fvdl return; 362 1.1 fvdl } 363 1.17 christos ahc_unlock(ahc, &ss); 364 1.16 perry 365 1.1 fvdl hscb = scb->hscb; 366 1.16 perry 367 1.1 fvdl SC_DEBUG(periph, SCSIPI_DB3, ("start scb(%p)\n", scb)); 368 1.1 fvdl scb->xs = xs; 369 1.1 fvdl 370 1.1 fvdl /* 371 1.1 fvdl * Put all the arguments for the xfer in the scb 372 1.1 fvdl */ 373 1.1 fvdl hscb->control = 0; 374 1.1 fvdl hscb->scsiid = BUILD_SCSIID(ahc, 0, target_id, our_id); 375 1.1 fvdl hscb->lun = periph->periph_lun; 376 1.1 fvdl if (xs->xs_control & XS_CTL_RESET) { 377 1.1 fvdl hscb->cdb_len = 0; 378 1.1 fvdl scb->flags |= SCB_DEVICE_RESET; 379 1.1 fvdl hscb->control |= MK_MESSAGE; 380 1.1 fvdl ahc_execute_scb(scb, NULL, 0); 381 1.1 fvdl } 382 1.16 perry 383 1.1 fvdl ahc_setup_data(ahc, xs, scb); 384 1.1 fvdl 385 1.1 fvdl break; 386 1.1 fvdl } 387 1.1 fvdl case ADAPTER_REQ_GROW_RESOURCES: 388 1.20 bouyer #ifdef AHC_DEBUG 389 1.19 bouyer printf("%s: ADAPTER_REQ_GROW_RESOURCES\n", ahc_name(ahc)); 390 1.20 bouyer #endif 391 1.21 tsutsui chan->chan_adapter->adapt_openings += ahc_alloc_scbs(ahc); 392 1.19 bouyer if (ahc->scb_data->numscbs >= AHC_SCB_MAX_ALLOC) 393 1.19 bouyer chan->chan_flags &= ~SCSIPI_CHAN_CANGROW; 394 1.1 fvdl return; 395 1.1 fvdl 396 1.1 fvdl case ADAPTER_REQ_SET_XFER_MODE: 397 1.1 fvdl { 398 1.1 fvdl struct scsipi_xfer_mode *xm = arg; 399 1.1 fvdl struct ahc_devinfo devinfo; 400 1.1 fvdl int target_id, our_id, first; 401 1.1 fvdl u_int width; 402 1.1 fvdl char channel; 403 1.22 bouyer u_int ppr_options = 0, period, offset; 404 1.11 fvdl struct ahc_syncrate *syncrate; 405 1.11 fvdl uint16_t old_autoneg; 406 1.1 fvdl 407 1.16 perry target_id = xm->xm_target; 408 1.1 fvdl our_id = chan->chan_id; 409 1.1 fvdl channel = (chan->chan_channel == 1) ? 'B' : 'A'; 410 1.1 fvdl s = splbio(); 411 1.1 fvdl tinfo = ahc_fetch_transinfo(ahc, channel, our_id, target_id, 412 1.1 fvdl &tstate); 413 1.1 fvdl ahc_compile_devinfo(&devinfo, our_id, target_id, 414 1.1 fvdl 0, channel, ROLE_INITIATOR); 415 1.1 fvdl 416 1.11 fvdl old_autoneg = tstate->auto_negotiate; 417 1.11 fvdl 418 1.1 fvdl /* 419 1.1 fvdl * XXX since the period and offset are not provided here, 420 1.1 fvdl * fake things by forcing a renegotiation using the user 421 1.1 fvdl * settings if this is called for the first time (i.e. 422 1.1 fvdl * during probe). Also, cap various values at the user 423 1.1 fvdl * values, assuming that the user set it up that way. 424 1.1 fvdl */ 425 1.1 fvdl if (ahc->inited_target[target_id] == 0) { 426 1.11 fvdl period = tinfo->user.period; 427 1.11 fvdl offset = tinfo->user.offset; 428 1.11 fvdl ppr_options = tinfo->user.ppr_options; 429 1.11 fvdl width = tinfo->user.width; 430 1.1 fvdl tstate->tagenable |= 431 1.1 fvdl (ahc->user_tagenable & devinfo.target_mask); 432 1.1 fvdl tstate->discenable |= 433 1.1 fvdl (ahc->user_discenable & devinfo.target_mask); 434 1.1 fvdl ahc->inited_target[target_id] = 1; 435 1.1 fvdl first = 1; 436 1.1 fvdl } else 437 1.1 fvdl first = 0; 438 1.1 fvdl 439 1.6 fvdl if (xm->xm_mode & (PERIPH_CAP_WIDE16 | PERIPH_CAP_DT)) 440 1.1 fvdl width = MSG_EXT_WDTR_BUS_16_BIT; 441 1.1 fvdl else 442 1.1 fvdl width = MSG_EXT_WDTR_BUS_8_BIT; 443 1.1 fvdl 444 1.1 fvdl ahc_validate_width(ahc, NULL, &width, ROLE_UNKNOWN); 445 1.1 fvdl if (width > tinfo->user.width) 446 1.1 fvdl width = tinfo->user.width; 447 1.11 fvdl ahc_set_width(ahc, &devinfo, width, AHC_TRANS_GOAL, FALSE); 448 1.1 fvdl 449 1.6 fvdl if (!(xm->xm_mode & (PERIPH_CAP_SYNC | PERIPH_CAP_DT))) { 450 1.11 fvdl period = 0; 451 1.11 fvdl offset = 0; 452 1.11 fvdl ppr_options = 0; 453 1.1 fvdl } 454 1.1 fvdl 455 1.1 fvdl if ((xm->xm_mode & PERIPH_CAP_DT) && 456 1.11 fvdl (ppr_options & MSG_EXT_PPR_DT_REQ)) 457 1.11 fvdl ppr_options |= MSG_EXT_PPR_DT_REQ; 458 1.1 fvdl else 459 1.11 fvdl ppr_options &= ~MSG_EXT_PPR_DT_REQ; 460 1.11 fvdl if ((tstate->discenable & devinfo.target_mask) == 0 || 461 1.11 fvdl (tstate->tagenable & devinfo.target_mask) == 0) 462 1.11 fvdl ppr_options &= ~MSG_EXT_PPR_IU_REQ; 463 1.1 fvdl 464 1.1 fvdl if ((xm->xm_mode & PERIPH_CAP_TQING) && 465 1.1 fvdl (ahc->user_tagenable & devinfo.target_mask)) 466 1.1 fvdl tstate->tagenable |= devinfo.target_mask; 467 1.1 fvdl else 468 1.1 fvdl tstate->tagenable &= ~devinfo.target_mask; 469 1.1 fvdl 470 1.11 fvdl syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, 471 1.11 fvdl AHC_SYNCRATE_MAX); 472 1.11 fvdl ahc_validate_offset(ahc, NULL, syncrate, &offset, 473 1.11 fvdl width, ROLE_UNKNOWN); 474 1.11 fvdl 475 1.11 fvdl if (offset == 0) { 476 1.11 fvdl period = 0; 477 1.11 fvdl ppr_options = 0; 478 1.11 fvdl } 479 1.11 fvdl 480 1.11 fvdl if (ppr_options != 0 481 1.11 fvdl && tinfo->user.transport_version >= 3) { 482 1.11 fvdl tinfo->goal.transport_version = 483 1.11 fvdl tinfo->user.transport_version; 484 1.11 fvdl tinfo->curr.transport_version = 485 1.11 fvdl tinfo->user.transport_version; 486 1.11 fvdl } 487 1.11 fvdl 488 1.11 fvdl ahc_set_syncrate(ahc, &devinfo, syncrate, period, offset, 489 1.11 fvdl ppr_options, AHC_TRANS_GOAL, FALSE); 490 1.11 fvdl 491 1.1 fvdl /* 492 1.1 fvdl * If this is the first request, and no negotiation is 493 1.1 fvdl * needed, just confirm the state to the scsipi layer, 494 1.1 fvdl * so that it can print a message. 495 1.1 fvdl */ 496 1.11 fvdl if (old_autoneg == tstate->auto_negotiate && first) { 497 1.9 bouyer xm->xm_mode = 0; 498 1.9 bouyer xm->xm_period = tinfo->curr.period; 499 1.9 bouyer xm->xm_offset = tinfo->curr.offset; 500 1.9 bouyer if (tinfo->curr.width == MSG_EXT_WDTR_BUS_16_BIT) 501 1.9 bouyer xm->xm_mode |= PERIPH_CAP_WIDE16; 502 1.9 bouyer if (tinfo->curr.period) 503 1.9 bouyer xm->xm_mode |= PERIPH_CAP_SYNC; 504 1.9 bouyer if (tstate->tagenable & devinfo.target_mask) 505 1.9 bouyer xm->xm_mode |= PERIPH_CAP_TQING; 506 1.9 bouyer if (tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ) 507 1.9 bouyer xm->xm_mode |= PERIPH_CAP_DT; 508 1.1 fvdl scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, xm); 509 1.9 bouyer } 510 1.1 fvdl splx(s); 511 1.1 fvdl } 512 1.1 fvdl } 513 1.1 fvdl 514 1.1 fvdl return; 515 1.1 fvdl } 516 1.1 fvdl 517 1.1 fvdl static void 518 1.1 fvdl ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments) 519 1.1 fvdl { 520 1.1 fvdl struct scb *scb; 521 1.1 fvdl struct scsipi_xfer *xs; 522 1.1 fvdl struct ahc_softc *ahc; 523 1.1 fvdl struct ahc_initiator_tinfo *tinfo; 524 1.1 fvdl struct ahc_tmode_tstate *tstate; 525 1.1 fvdl 526 1.1 fvdl u_int mask; 527 1.34 tsutsui u_long s; 528 1.1 fvdl 529 1.1 fvdl scb = (struct scb *)arg; 530 1.1 fvdl xs = scb->xs; 531 1.1 fvdl xs->error = 0; 532 1.1 fvdl xs->status = 0; 533 1.1 fvdl xs->xs_status = 0; 534 1.35 tsutsui ahc = device_private( 535 1.35 tsutsui xs->xs_periph->periph_channel->chan_adapter->adapt_dev); 536 1.1 fvdl 537 1.1 fvdl if (nsegments != 0) { 538 1.21 tsutsui struct ahc_dma_seg *sg; 539 1.1 fvdl bus_dma_segment_t *end_seg; 540 1.1 fvdl int op; 541 1.16 perry 542 1.1 fvdl end_seg = dm_segs + nsegments; 543 1.1 fvdl 544 1.1 fvdl /* Copy the segments into our SG list */ 545 1.1 fvdl sg = scb->sg_list; 546 1.1 fvdl while (dm_segs < end_seg) { 547 1.1 fvdl uint32_t len; 548 1.1 fvdl 549 1.1 fvdl sg->addr = ahc_htole32(dm_segs->ds_addr); 550 1.1 fvdl len = dm_segs->ds_len 551 1.18 tsutsui | ((dm_segs->ds_addr >> 8) & AHC_SG_HIGH_ADDR_MASK); 552 1.1 fvdl sg->len = ahc_htole32(len); 553 1.1 fvdl sg++; 554 1.1 fvdl dm_segs++; 555 1.1 fvdl } 556 1.1 fvdl 557 1.1 fvdl /* 558 1.1 fvdl * Note where to find the SG entries in bus space. 559 1.16 perry * We also set the full residual flag which the 560 1.1 fvdl * sequencer will clear as soon as a data transfer 561 1.1 fvdl * occurs. 562 1.1 fvdl */ 563 1.1 fvdl scb->hscb->sgptr = ahc_htole32(scb->sg_list_phys|SG_FULL_RESID); 564 1.1 fvdl 565 1.1 fvdl if (xs->xs_control & XS_CTL_DATA_IN) 566 1.1 fvdl op = BUS_DMASYNC_PREREAD; 567 1.1 fvdl else 568 1.1 fvdl op = BUS_DMASYNC_PREWRITE; 569 1.1 fvdl 570 1.1 fvdl bus_dmamap_sync(ahc->parent_dmat, scb->dmamap, 0, 571 1.1 fvdl scb->dmamap->dm_mapsize, op); 572 1.1 fvdl 573 1.1 fvdl sg--; 574 1.1 fvdl sg->len |= ahc_htole32(AHC_DMA_LAST_SEG); 575 1.16 perry 576 1.1 fvdl /* Copy the first SG into the "current" data pointer area */ 577 1.1 fvdl scb->hscb->dataptr = scb->sg_list->addr; 578 1.1 fvdl scb->hscb->datacnt = scb->sg_list->len; 579 1.1 fvdl } else { 580 1.1 fvdl scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL); 581 1.1 fvdl scb->hscb->dataptr = 0; 582 1.1 fvdl scb->hscb->datacnt = 0; 583 1.1 fvdl } 584 1.1 fvdl 585 1.1 fvdl scb->sg_count = nsegments; 586 1.1 fvdl 587 1.1 fvdl ahc_lock(ahc, &s); 588 1.1 fvdl 589 1.1 fvdl /* 590 1.1 fvdl * Last time we need to check if this SCB needs to 591 1.1 fvdl * be aborted. 592 1.1 fvdl */ 593 1.1 fvdl if (xs->xs_status & XS_STS_DONE) { 594 1.1 fvdl if (nsegments != 0) 595 1.1 fvdl bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap); 596 1.1 fvdl ahc_free_scb(ahc, scb); 597 1.1 fvdl ahc_unlock(ahc, &s); 598 1.1 fvdl scsipi_done(xs); 599 1.1 fvdl return; 600 1.1 fvdl } 601 1.1 fvdl 602 1.1 fvdl tinfo = ahc_fetch_transinfo(ahc, ahc->channel, 603 1.1 fvdl SCSIID_OUR_ID(scb->hscb->scsiid), 604 1.1 fvdl SCSIID_TARGET(ahc, scb->hscb->scsiid), 605 1.1 fvdl &tstate); 606 1.1 fvdl 607 1.1 fvdl mask = SCB_GET_TARGET_MASK(ahc, scb); 608 1.1 fvdl scb->hscb->scsirate = tinfo->scsirate; 609 1.1 fvdl scb->hscb->scsioffset = tinfo->curr.offset; 610 1.1 fvdl 611 1.1 fvdl if ((tstate->ultraenb & mask) != 0) 612 1.1 fvdl scb->hscb->control |= ULTRAENB; 613 1.1 fvdl 614 1.1 fvdl if ((tstate->discenable & mask) != 0) 615 1.21 tsutsui scb->hscb->control |= DISCENB; 616 1.1 fvdl 617 1.1 fvdl if (xs->xs_tag_type) 618 1.1 fvdl scb->hscb->control |= xs->xs_tag_type; 619 1.1 fvdl 620 1.12 fvdl #if 1 /* This looks like it makes sense at first, but it can loop */ 621 1.1 fvdl if ((xs->xs_control & XS_CTL_DISCOVERY) && (tinfo->goal.width == 0 622 1.1 fvdl && tinfo->goal.offset == 0 623 1.1 fvdl && tinfo->goal.ppr_options == 0)) { 624 1.1 fvdl scb->flags |= SCB_NEGOTIATE; 625 1.16 perry scb->hscb->control |= MK_MESSAGE; 626 1.11 fvdl } else 627 1.11 fvdl #endif 628 1.11 fvdl if ((tstate->auto_negotiate & mask) != 0) { 629 1.1 fvdl scb->flags |= SCB_AUTO_NEGOTIATE; 630 1.1 fvdl scb->hscb->control |= MK_MESSAGE; 631 1.1 fvdl } 632 1.1 fvdl 633 1.1 fvdl LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links); 634 1.1 fvdl 635 1.1 fvdl if (!(xs->xs_control & XS_CTL_POLL)) { 636 1.1 fvdl callout_reset(&scb->xs->xs_callout, xs->timeout > 1000000 ? 637 1.1 fvdl (xs->timeout / 1000) * hz : (xs->timeout * hz) / 1000, 638 1.1 fvdl ahc_timeout, scb); 639 1.1 fvdl } 640 1.1 fvdl 641 1.1 fvdl /* 642 1.1 fvdl * We only allow one untagged transaction 643 1.1 fvdl * per target in the initiator role unless 644 1.1 fvdl * we are storing a full busy target *lun* 645 1.1 fvdl * table in SCB space. 646 1.1 fvdl */ 647 1.1 fvdl if ((scb->hscb->control & (TARGET_SCB|TAG_ENB)) == 0 648 1.1 fvdl && (ahc->flags & AHC_SCB_BTT) == 0) { 649 1.1 fvdl struct scb_tailq *untagged_q; 650 1.1 fvdl int target_offset; 651 1.1 fvdl 652 1.1 fvdl target_offset = SCB_GET_TARGET_OFFSET(ahc, scb); 653 1.1 fvdl untagged_q = &(ahc->untagged_queues[target_offset]); 654 1.1 fvdl TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe); 655 1.1 fvdl scb->flags |= SCB_UNTAGGEDQ; 656 1.1 fvdl if (TAILQ_FIRST(untagged_q) != scb) { 657 1.1 fvdl ahc_unlock(ahc, &s); 658 1.1 fvdl return; 659 1.1 fvdl } 660 1.1 fvdl } 661 1.1 fvdl scb->flags |= SCB_ACTIVE; 662 1.1 fvdl 663 1.1 fvdl if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) { 664 1.1 fvdl /* Define a mapping from our tag to the SCB. */ 665 1.1 fvdl ahc->scb_data->scbindex[scb->hscb->tag] = scb; 666 1.1 fvdl ahc_pause(ahc); 667 1.1 fvdl if ((ahc->flags & AHC_PAGESCBS) == 0) 668 1.1 fvdl ahc_outb(ahc, SCBPTR, scb->hscb->tag); 669 1.1 fvdl ahc_outb(ahc, TARG_IMMEDIATE_SCB, scb->hscb->tag); 670 1.1 fvdl ahc_unpause(ahc); 671 1.1 fvdl } else { 672 1.1 fvdl ahc_queue_scb(ahc, scb); 673 1.1 fvdl } 674 1.1 fvdl 675 1.1 fvdl if (!(xs->xs_control & XS_CTL_POLL)) { 676 1.1 fvdl ahc_unlock(ahc, &s); 677 1.1 fvdl return; 678 1.1 fvdl } 679 1.1 fvdl 680 1.1 fvdl /* 681 1.1 fvdl * If we can't use interrupts, poll for completion 682 1.1 fvdl */ 683 1.26 macallan 684 1.1 fvdl SC_DEBUG(xs->xs_periph, SCSIPI_DB3, ("cmd_poll\n")); 685 1.1 fvdl do { 686 1.1 fvdl if (ahc_poll(ahc, xs->timeout)) { 687 1.1 fvdl if (!(xs->xs_control & XS_CTL_SILENT)) 688 1.1 fvdl printf("cmd fail\n"); 689 1.1 fvdl ahc_timeout(scb); 690 1.1 fvdl break; 691 1.1 fvdl } 692 1.1 fvdl } while (!(xs->xs_status & XS_STS_DONE)); 693 1.1 fvdl ahc_unlock(ahc, &s); 694 1.1 fvdl 695 1.1 fvdl return; 696 1.1 fvdl } 697 1.1 fvdl 698 1.1 fvdl static int 699 1.1 fvdl ahc_poll(struct ahc_softc *ahc, int wait) 700 1.1 fvdl { 701 1.1 fvdl while (--wait) { 702 1.1 fvdl DELAY(1000); 703 1.1 fvdl if (ahc_inb(ahc, INTSTAT) & INT_PEND) 704 1.1 fvdl break; 705 1.1 fvdl } 706 1.1 fvdl 707 1.1 fvdl if (wait == 0) { 708 1.1 fvdl printf("%s: board is not responding\n", ahc_name(ahc)); 709 1.1 fvdl return (EIO); 710 1.1 fvdl } 711 1.1 fvdl 712 1.35 tsutsui ahc_intr(ahc); 713 1.1 fvdl return (0); 714 1.1 fvdl } 715 1.1 fvdl 716 1.1 fvdl static void 717 1.1 fvdl ahc_setup_data(struct ahc_softc *ahc, struct scsipi_xfer *xs, 718 1.1 fvdl struct scb *scb) 719 1.1 fvdl { 720 1.1 fvdl struct hardware_scb *hscb; 721 1.16 perry 722 1.1 fvdl hscb = scb->hscb; 723 1.1 fvdl xs->resid = xs->status = 0; 724 1.16 perry 725 1.1 fvdl hscb->cdb_len = xs->cmdlen; 726 1.1 fvdl if (hscb->cdb_len > sizeof(hscb->cdb32)) { 727 1.1 fvdl u_long s; 728 1.1 fvdl 729 1.1 fvdl ahc_set_transaction_status(scb, CAM_REQ_INVALID); 730 1.1 fvdl ahc_lock(ahc, &s); 731 1.1 fvdl ahc_free_scb(ahc, scb); 732 1.1 fvdl ahc_unlock(ahc, &s); 733 1.1 fvdl scsipi_done(xs); 734 1.1 fvdl return; 735 1.1 fvdl } 736 1.1 fvdl 737 1.1 fvdl if (hscb->cdb_len > 12) { 738 1.1 fvdl memcpy(hscb->cdb32, xs->cmd, hscb->cdb_len); 739 1.1 fvdl scb->flags |= SCB_CDB32_PTR; 740 1.1 fvdl } else { 741 1.1 fvdl memcpy(hscb->shared_data.cdb, xs->cmd, hscb->cdb_len); 742 1.1 fvdl } 743 1.16 perry 744 1.1 fvdl /* Only use S/G if there is a transfer */ 745 1.1 fvdl if (xs->datalen) { 746 1.1 fvdl int error; 747 1.1 fvdl 748 1.21 tsutsui error = bus_dmamap_load(ahc->parent_dmat, 749 1.1 fvdl scb->dmamap, xs->data, 750 1.1 fvdl xs->datalen, NULL, 751 1.1 fvdl ((xs->xs_control & XS_CTL_NOSLEEP) ? 752 1.1 fvdl BUS_DMA_NOWAIT : BUS_DMA_WAITOK) | 753 1.1 fvdl BUS_DMA_STREAMING | 754 1.1 fvdl ((xs->xs_control & XS_CTL_DATA_IN) ? 755 1.1 fvdl BUS_DMA_READ : BUS_DMA_WRITE)); 756 1.21 tsutsui if (error) { 757 1.1 fvdl #ifdef AHC_DEBUG 758 1.21 tsutsui printf("%s: in ahc_setup_data(): bus_dmamap_load() " 759 1.1 fvdl "= %d\n", 760 1.1 fvdl ahc_name(ahc), error); 761 1.1 fvdl #endif 762 1.21 tsutsui xs->error = XS_RESOURCE_SHORTAGE; 763 1.21 tsutsui scsipi_done(xs); 764 1.21 tsutsui return; 765 1.21 tsutsui } 766 1.21 tsutsui ahc_execute_scb(scb, 767 1.1 fvdl scb->dmamap->dm_segs, 768 1.1 fvdl scb->dmamap->dm_nsegs); 769 1.1 fvdl } else { 770 1.1 fvdl ahc_execute_scb(scb, NULL, 0); 771 1.1 fvdl } 772 1.1 fvdl } 773 1.1 fvdl 774 1.1 fvdl static void 775 1.1 fvdl ahc_set_recoveryscb(struct ahc_softc *ahc, struct scb *scb) { 776 1.1 fvdl 777 1.1 fvdl if ((scb->flags & SCB_RECOVERY_SCB) == 0) { 778 1.1 fvdl struct scb *list_scb; 779 1.1 fvdl 780 1.1 fvdl scb->flags |= SCB_RECOVERY_SCB; 781 1.1 fvdl 782 1.1 fvdl /* 783 1.1 fvdl * Take all queued, but not sent SCBs out of the equation. 784 1.1 fvdl * Also ensure that no new CCBs are queued to us while we 785 1.1 fvdl * try to fix this problem. 786 1.1 fvdl */ 787 1.1 fvdl scsipi_channel_freeze(&ahc->sc_channel, 1); 788 1.1 fvdl if (ahc->features & AHC_TWIN) 789 1.1 fvdl scsipi_channel_freeze(&ahc->sc_channel_b, 1); 790 1.1 fvdl 791 1.1 fvdl /* 792 1.1 fvdl * Go through all of our pending SCBs and remove 793 1.1 fvdl * any scheduled timeouts for them. We will reschedule 794 1.1 fvdl * them after we've successfully fixed this problem. 795 1.1 fvdl */ 796 1.1 fvdl LIST_FOREACH(list_scb, &ahc->pending_scbs, pending_links) { 797 1.1 fvdl callout_stop(&list_scb->xs->xs_callout); 798 1.1 fvdl } 799 1.1 fvdl } 800 1.1 fvdl } 801 1.1 fvdl 802 1.1 fvdl void 803 1.1 fvdl ahc_timeout(void *arg) 804 1.1 fvdl { 805 1.1 fvdl struct scb *scb; 806 1.1 fvdl struct ahc_softc *ahc; 807 1.34 tsutsui u_long s; 808 1.1 fvdl int found; 809 1.1 fvdl u_int last_phase; 810 1.1 fvdl int target; 811 1.1 fvdl int lun; 812 1.1 fvdl int i; 813 1.1 fvdl char channel; 814 1.1 fvdl 815 1.35 tsutsui scb = arg; 816 1.35 tsutsui ahc = scb->ahc_softc; 817 1.1 fvdl 818 1.1 fvdl ahc_lock(ahc, &s); 819 1.1 fvdl 820 1.1 fvdl ahc_pause_and_flushwork(ahc); 821 1.1 fvdl 822 1.1 fvdl if ((scb->flags & SCB_ACTIVE) == 0) { 823 1.1 fvdl /* Previous timeout took care of me already */ 824 1.1 fvdl printf("%s: Timedout SCB already complete. " 825 1.1 fvdl "Interrupts may not be functioning.\n", ahc_name(ahc)); 826 1.1 fvdl ahc_unpause(ahc); 827 1.1 fvdl ahc_unlock(ahc, &s); 828 1.1 fvdl return; 829 1.1 fvdl } 830 1.1 fvdl 831 1.1 fvdl target = SCB_GET_TARGET(ahc, scb); 832 1.1 fvdl channel = SCB_GET_CHANNEL(ahc, scb); 833 1.1 fvdl lun = SCB_GET_LUN(scb); 834 1.1 fvdl 835 1.1 fvdl ahc_print_path(ahc, scb); 836 1.1 fvdl printf("SCB 0x%x - timed out\n", scb->hscb->tag); 837 1.1 fvdl ahc_dump_card_state(ahc); 838 1.1 fvdl last_phase = ahc_inb(ahc, LASTPHASE); 839 1.1 fvdl if (scb->sg_count > 0) { 840 1.1 fvdl for (i = 0; i < scb->sg_count; i++) { 841 1.1 fvdl printf("sg[%d] - Addr 0x%x : Length %d\n", 842 1.1 fvdl i, 843 1.1 fvdl scb->sg_list[i].addr, 844 1.1 fvdl scb->sg_list[i].len & AHC_SG_LEN_MASK); 845 1.1 fvdl } 846 1.1 fvdl } 847 1.1 fvdl if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) { 848 1.1 fvdl /* 849 1.1 fvdl * Been down this road before. 850 1.1 fvdl * Do a full bus reset. 851 1.1 fvdl */ 852 1.1 fvdl bus_reset: 853 1.1 fvdl ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT); 854 1.1 fvdl found = ahc_reset_channel(ahc, channel, /*Initiate Reset*/TRUE); 855 1.1 fvdl printf("%s: Issued Channel %c Bus Reset. " 856 1.1 fvdl "%d SCBs aborted\n", ahc_name(ahc), channel, found); 857 1.1 fvdl } else { 858 1.1 fvdl /* 859 1.1 fvdl * If we are a target, transition to bus free and report 860 1.1 fvdl * the timeout. 861 1.16 perry * 862 1.1 fvdl * The target/initiator that is holding up the bus may not 863 1.1 fvdl * be the same as the one that triggered this timeout 864 1.1 fvdl * (different commands have different timeout lengths). 865 1.14 wiz * If the bus is idle and we are acting as the initiator 866 1.1 fvdl * for this request, queue a BDR message to the timed out 867 1.1 fvdl * target. Otherwise, if the timed out transaction is 868 1.1 fvdl * active: 869 1.1 fvdl * Initiator transaction: 870 1.1 fvdl * Stuff the message buffer with a BDR message and assert 871 1.1 fvdl * ATN in the hopes that the target will let go of the bus 872 1.1 fvdl * and go to the mesgout phase. If this fails, we'll 873 1.1 fvdl * get another timeout 2 seconds later which will attempt 874 1.1 fvdl * a bus reset. 875 1.1 fvdl * 876 1.1 fvdl * Target transaction: 877 1.1 fvdl * Transition to BUS FREE and report the error. 878 1.1 fvdl * It's good to be the target! 879 1.1 fvdl */ 880 1.1 fvdl u_int active_scb_index; 881 1.1 fvdl u_int saved_scbptr; 882 1.1 fvdl 883 1.1 fvdl saved_scbptr = ahc_inb(ahc, SCBPTR); 884 1.1 fvdl active_scb_index = ahc_inb(ahc, SCB_TAG); 885 1.1 fvdl 886 1.1 fvdl if ((ahc_inb(ahc, SEQ_FLAGS) & NOT_IDENTIFIED) == 0 887 1.1 fvdl && (active_scb_index < ahc->scb_data->numscbs)) { 888 1.1 fvdl struct scb *active_scb; 889 1.1 fvdl 890 1.1 fvdl /* 891 1.1 fvdl * If the active SCB is not us, assume that 892 1.1 fvdl * the active SCB has a longer timeout than 893 1.1 fvdl * the timedout SCB, and wait for the active 894 1.1 fvdl * SCB to timeout. 895 1.16 perry */ 896 1.1 fvdl active_scb = ahc_lookup_scb(ahc, active_scb_index); 897 1.1 fvdl if (active_scb != scb) { 898 1.1 fvdl uint64_t newtimeout; 899 1.1 fvdl 900 1.1 fvdl ahc_print_path(ahc, scb); 901 1.1 fvdl printf("Other SCB Timeout%s", 902 1.21 tsutsui (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0 903 1.1 fvdl ? " again\n" : "\n"); 904 1.1 fvdl scb->flags |= SCB_OTHERTCL_TIMEOUT; 905 1.1 fvdl newtimeout = MAX(active_scb->xs->timeout, 906 1.1 fvdl scb->xs->timeout); 907 1.1 fvdl callout_reset(&scb->xs->xs_callout, 908 1.1 fvdl newtimeout > 1000000 ? 909 1.1 fvdl (newtimeout / 1000) * hz : 910 1.1 fvdl (newtimeout * hz) / 1000, 911 1.1 fvdl ahc_timeout, scb); 912 1.1 fvdl ahc_unpause(ahc); 913 1.1 fvdl ahc_unlock(ahc, &s); 914 1.1 fvdl return; 915 1.16 perry } 916 1.1 fvdl 917 1.1 fvdl /* It's us */ 918 1.1 fvdl if ((scb->flags & SCB_TARGET_SCB) != 0) { 919 1.1 fvdl 920 1.1 fvdl /* 921 1.1 fvdl * Send back any queued up transactions 922 1.1 fvdl * and properly record the error condition. 923 1.1 fvdl */ 924 1.1 fvdl ahc_abort_scbs(ahc, SCB_GET_TARGET(ahc, scb), 925 1.1 fvdl SCB_GET_CHANNEL(ahc, scb), 926 1.1 fvdl SCB_GET_LUN(scb), 927 1.1 fvdl scb->hscb->tag, 928 1.1 fvdl ROLE_TARGET, 929 1.1 fvdl CAM_CMD_TIMEOUT); 930 1.1 fvdl 931 1.1 fvdl /* Will clear us from the bus */ 932 1.1 fvdl ahc_restart(ahc); 933 1.1 fvdl ahc_unlock(ahc, &s); 934 1.1 fvdl return; 935 1.1 fvdl } 936 1.1 fvdl 937 1.1 fvdl ahc_set_recoveryscb(ahc, active_scb); 938 1.1 fvdl ahc_outb(ahc, MSG_OUT, HOST_MSG); 939 1.1 fvdl ahc_outb(ahc, SCSISIGO, last_phase|ATNO); 940 1.1 fvdl ahc_print_path(ahc, active_scb); 941 1.1 fvdl printf("BDR message in message buffer\n"); 942 1.1 fvdl active_scb->flags |= SCB_DEVICE_RESET; 943 1.1 fvdl callout_reset(&active_scb->xs->xs_callout, 944 1.1 fvdl 2 * hz, ahc_timeout, active_scb); 945 1.1 fvdl ahc_unpause(ahc); 946 1.1 fvdl } else { 947 1.21 tsutsui int disconnected; 948 1.1 fvdl 949 1.1 fvdl /* XXX Shouldn't panic. Just punt instead? */ 950 1.1 fvdl if ((scb->flags & SCB_TARGET_SCB) != 0) 951 1.1 fvdl panic("Timed-out target SCB but bus idle"); 952 1.1 fvdl 953 1.1 fvdl if (last_phase != P_BUSFREE 954 1.1 fvdl && (ahc_inb(ahc, SSTAT0) & TARGET) != 0) { 955 1.1 fvdl /* XXX What happened to the SCB? */ 956 1.1 fvdl /* Hung target selection. Goto busfree */ 957 1.1 fvdl printf("%s: Hung target selection\n", 958 1.1 fvdl ahc_name(ahc)); 959 1.1 fvdl ahc_restart(ahc); 960 1.1 fvdl ahc_unlock(ahc, &s); 961 1.1 fvdl return; 962 1.1 fvdl } 963 1.1 fvdl 964 1.1 fvdl if (ahc_search_qinfifo(ahc, target, channel, lun, 965 1.1 fvdl scb->hscb->tag, ROLE_INITIATOR, 966 1.1 fvdl /*status*/0, SEARCH_COUNT) > 0) { 967 1.1 fvdl disconnected = FALSE; 968 1.1 fvdl } else { 969 1.1 fvdl disconnected = TRUE; 970 1.1 fvdl } 971 1.1 fvdl 972 1.1 fvdl if (disconnected) { 973 1.1 fvdl 974 1.1 fvdl ahc_set_recoveryscb(ahc, scb); 975 1.1 fvdl /* 976 1.1 fvdl * Actually re-queue this SCB in an attempt 977 1.1 fvdl * to select the device before it reconnects. 978 1.1 fvdl * In either case (selection or reselection), 979 1.1 fvdl * we will now issue a target reset to the 980 1.1 fvdl * timed-out device. 981 1.1 fvdl * 982 1.1 fvdl * Set the MK_MESSAGE control bit indicating 983 1.1 fvdl * that we desire to send a message. We 984 1.1 fvdl * also set the disconnected flag since 985 1.1 fvdl * in the paging case there is no guarantee 986 1.1 fvdl * that our SCB control byte matches the 987 1.1 fvdl * version on the card. We don't want the 988 1.1 fvdl * sequencer to abort the command thinking 989 1.1 fvdl * an unsolicited reselection occurred. 990 1.1 fvdl */ 991 1.1 fvdl scb->hscb->control |= MK_MESSAGE|DISCONNECTED; 992 1.1 fvdl scb->flags |= SCB_DEVICE_RESET; 993 1.1 fvdl 994 1.1 fvdl /* 995 1.1 fvdl * Remove any cached copy of this SCB in the 996 1.1 fvdl * disconnected list in preparation for the 997 1.1 fvdl * queuing of our abort SCB. We use the 998 1.1 fvdl * same element in the SCB, SCB_NEXT, for 999 1.1 fvdl * both the qinfifo and the disconnected list. 1000 1.1 fvdl */ 1001 1.1 fvdl ahc_search_disc_list(ahc, target, channel, 1002 1.1 fvdl lun, scb->hscb->tag, 1003 1.1 fvdl /*stop_on_first*/TRUE, 1004 1.1 fvdl /*remove*/TRUE, 1005 1.1 fvdl /*save_state*/FALSE); 1006 1.1 fvdl 1007 1.1 fvdl /* 1008 1.1 fvdl * In the non-paging case, the sequencer will 1009 1.1 fvdl * never re-reference the in-core SCB. 1010 1.1 fvdl * To make sure we are notified during 1011 1.43 andvar * reselection, set the MK_MESSAGE flag in 1012 1.1 fvdl * the card's copy of the SCB. 1013 1.1 fvdl */ 1014 1.1 fvdl if ((ahc->flags & AHC_PAGESCBS) == 0) { 1015 1.1 fvdl ahc_outb(ahc, SCBPTR, scb->hscb->tag); 1016 1.1 fvdl ahc_outb(ahc, SCB_CONTROL, 1017 1.1 fvdl ahc_inb(ahc, SCB_CONTROL) 1018 1.1 fvdl | MK_MESSAGE); 1019 1.1 fvdl } 1020 1.1 fvdl 1021 1.1 fvdl /* 1022 1.1 fvdl * Clear out any entries in the QINFIFO first 1023 1.1 fvdl * so we are the next SCB for this target 1024 1.1 fvdl * to run. 1025 1.1 fvdl */ 1026 1.1 fvdl ahc_search_qinfifo(ahc, 1027 1.1 fvdl SCB_GET_TARGET(ahc, scb), 1028 1.1 fvdl channel, SCB_GET_LUN(scb), 1029 1.1 fvdl SCB_LIST_NULL, 1030 1.1 fvdl ROLE_INITIATOR, 1031 1.1 fvdl CAM_REQUEUE_REQ, 1032 1.1 fvdl SEARCH_COMPLETE); 1033 1.1 fvdl ahc_print_path(ahc, scb); 1034 1.1 fvdl printf("Queuing a BDR SCB\n"); 1035 1.1 fvdl ahc_qinfifo_requeue_tail(ahc, scb); 1036 1.1 fvdl ahc_outb(ahc, SCBPTR, saved_scbptr); 1037 1.1 fvdl callout_reset(&scb->xs->xs_callout, 2 * hz, 1038 1.1 fvdl ahc_timeout, scb); 1039 1.1 fvdl ahc_unpause(ahc); 1040 1.1 fvdl } else { 1041 1.42 andvar /* Go "immediately" to the bus reset */ 1042 1.1 fvdl /* This shouldn't happen */ 1043 1.1 fvdl ahc_set_recoveryscb(ahc, scb); 1044 1.1 fvdl ahc_print_path(ahc, scb); 1045 1.1 fvdl printf("SCB %d: Immediate reset. " 1046 1.1 fvdl "Flags = 0x%x\n", scb->hscb->tag, 1047 1.1 fvdl scb->flags); 1048 1.1 fvdl goto bus_reset; 1049 1.1 fvdl } 1050 1.1 fvdl } 1051 1.1 fvdl } 1052 1.1 fvdl ahc_unlock(ahc, &s); 1053 1.1 fvdl } 1054 1.1 fvdl 1055 1.1 fvdl void 1056 1.1 fvdl ahc_platform_set_tags(struct ahc_softc *ahc, 1057 1.1 fvdl struct ahc_devinfo *devinfo, int enable) 1058 1.1 fvdl { 1059 1.21 tsutsui struct ahc_tmode_tstate *tstate; 1060 1.1 fvdl 1061 1.21 tsutsui ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid, 1062 1.21 tsutsui devinfo->target, &tstate); 1063 1.1 fvdl 1064 1.21 tsutsui if (enable) 1065 1.21 tsutsui tstate->tagenable |= devinfo->target_mask; 1066 1.1 fvdl else 1067 1.21 tsutsui tstate->tagenable &= ~devinfo->target_mask; 1068 1.1 fvdl } 1069 1.1 fvdl 1070 1.1 fvdl int 1071 1.24 christos ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) 1072 1.1 fvdl { 1073 1.1 fvdl if (sizeof(struct ahc_platform_data) == 0) 1074 1.1 fvdl return 0; 1075 1.1 fvdl ahc->platform_data = malloc(sizeof(struct ahc_platform_data), M_DEVBUF, 1076 1.39 chs M_WAITOK); 1077 1.1 fvdl return (0); 1078 1.1 fvdl } 1079 1.1 fvdl 1080 1.1 fvdl void 1081 1.1 fvdl ahc_platform_free(struct ahc_softc *ahc) 1082 1.1 fvdl { 1083 1.1 fvdl if (sizeof(struct ahc_platform_data) == 0) 1084 1.1 fvdl return; 1085 1.1 fvdl free(ahc->platform_data, M_DEVBUF); 1086 1.1 fvdl } 1087 1.1 fvdl 1088 1.1 fvdl int 1089 1.24 christos ahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc) 1090 1.1 fvdl { 1091 1.1 fvdl return (0); 1092 1.1 fvdl } 1093 1.1 fvdl 1094 1.1 fvdl int 1095 1.31 tsutsui ahc_detach(struct ahc_softc *ahc, int flags) 1096 1.1 fvdl { 1097 1.1 fvdl int rv = 0; 1098 1.1 fvdl 1099 1.1 fvdl ahc_intr_enable(ahc, FALSE); 1100 1.1 fvdl if (ahc->sc_child != NULL) 1101 1.1 fvdl rv = config_detach(ahc->sc_child, flags); 1102 1.1 fvdl if (rv == 0 && ahc->sc_child_b != NULL) 1103 1.1 fvdl rv = config_detach(ahc->sc_child_b, flags); 1104 1.1 fvdl 1105 1.31 tsutsui pmf_device_deregister(ahc->sc_dev); 1106 1.1 fvdl ahc_free(ahc); 1107 1.1 fvdl 1108 1.1 fvdl return (rv); 1109 1.1 fvdl } 1110 1.1 fvdl 1111 1.1 fvdl 1112 1.1 fvdl void 1113 1.1 fvdl ahc_send_async(struct ahc_softc *ahc, char channel, u_int target, u_int lun, 1114 1.24 christos ac_code code, void *opt_arg) 1115 1.1 fvdl { 1116 1.1 fvdl struct ahc_tmode_tstate *tstate; 1117 1.1 fvdl struct ahc_initiator_tinfo *tinfo; 1118 1.1 fvdl struct ahc_devinfo devinfo; 1119 1.1 fvdl struct scsipi_channel *chan; 1120 1.1 fvdl struct scsipi_xfer_mode xm; 1121 1.1 fvdl 1122 1.1 fvdl chan = channel == 'B' ? &ahc->sc_channel_b : &ahc->sc_channel; 1123 1.1 fvdl switch (code) { 1124 1.1 fvdl case AC_TRANSFER_NEG: 1125 1.1 fvdl tinfo = ahc_fetch_transinfo(ahc, channel, ahc->our_id, target, 1126 1.1 fvdl &tstate); 1127 1.1 fvdl ahc_compile_devinfo(&devinfo, ahc->our_id, target, lun, 1128 1.1 fvdl channel, ROLE_UNKNOWN); 1129 1.1 fvdl /* 1130 1.1 fvdl * Don't bother if negotiating. XXX? 1131 1.1 fvdl */ 1132 1.1 fvdl if (tinfo->curr.period != tinfo->goal.period 1133 1.1 fvdl || tinfo->curr.width != tinfo->goal.width 1134 1.1 fvdl || tinfo->curr.offset != tinfo->goal.offset 1135 1.1 fvdl || tinfo->curr.ppr_options != tinfo->goal.ppr_options) 1136 1.1 fvdl break; 1137 1.1 fvdl xm.xm_target = target; 1138 1.1 fvdl xm.xm_mode = 0; 1139 1.1 fvdl xm.xm_period = tinfo->curr.period; 1140 1.1 fvdl xm.xm_offset = tinfo->curr.offset; 1141 1.16 perry if (tinfo->curr.width == MSG_EXT_WDTR_BUS_16_BIT) 1142 1.1 fvdl xm.xm_mode |= PERIPH_CAP_WIDE16; 1143 1.1 fvdl if (tinfo->curr.period) 1144 1.1 fvdl xm.xm_mode |= PERIPH_CAP_SYNC; 1145 1.1 fvdl if (tstate->tagenable & devinfo.target_mask) 1146 1.1 fvdl xm.xm_mode |= PERIPH_CAP_TQING; 1147 1.6 fvdl if (tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ) 1148 1.6 fvdl xm.xm_mode |= PERIPH_CAP_DT; 1149 1.1 fvdl scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, &xm); 1150 1.1 fvdl break; 1151 1.1 fvdl case AC_BUS_RESET: 1152 1.1 fvdl scsipi_async_event(chan, ASYNC_EVENT_RESET, NULL); 1153 1.1 fvdl case AC_SENT_BDR: 1154 1.1 fvdl default: 1155 1.1 fvdl break; 1156 1.1 fvdl } 1157 1.1 fvdl } 1158