1 1.66 thorpej /* $NetBSD: aha.c,v 1.66 2022/09/25 18:43:32 thorpej Exp $ */ 2 1.1 mycroft 3 1.5 thorpej /*- 4 1.14 thorpej * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 5 1.5 thorpej * All rights reserved. 6 1.5 thorpej * 7 1.5 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.18 mycroft * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace 9 1.18 mycroft * Simulation Facility, NASA Ames Research Center. 10 1.5 thorpej * 11 1.5 thorpej * Redistribution and use in source and binary forms, with or without 12 1.5 thorpej * modification, are permitted provided that the following conditions 13 1.5 thorpej * are met: 14 1.5 thorpej * 1. Redistributions of source code must retain the above copyright 15 1.5 thorpej * notice, this list of conditions and the following disclaimer. 16 1.5 thorpej * 2. Redistributions in binary form must reproduce the above copyright 17 1.5 thorpej * notice, this list of conditions and the following disclaimer in the 18 1.5 thorpej * documentation and/or other materials provided with the distribution. 19 1.5 thorpej * 20 1.5 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.5 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.5 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.5 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.5 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.5 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.5 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.5 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.5 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.5 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.5 thorpej * POSSIBILITY OF SUCH DAMAGE. 31 1.1 mycroft */ 32 1.1 mycroft 33 1.1 mycroft /* 34 1.1 mycroft * Originally written by Julian Elischer (julian (at) tfs.com) 35 1.1 mycroft * for TRW Financial Systems for use under the MACH(2.5) operating system. 36 1.1 mycroft * 37 1.1 mycroft * TRW Financial Systems, in accordance with their agreement with Carnegie 38 1.1 mycroft * Mellon University, makes this software available to CMU to distribute 39 1.1 mycroft * or use in any manner that they see fit as long as this message is kept with 40 1.1 mycroft * the software. For this reason TFS also grants any other persons or 41 1.1 mycroft * organisations permission to use or modify this software. 42 1.1 mycroft * 43 1.1 mycroft * TFS supplies this software to be publicly redistributed 44 1.1 mycroft * on the understanding that TFS is not responsible for the correct 45 1.1 mycroft * functioning of this software in any circumstances. 46 1.1 mycroft */ 47 1.37 lukem 48 1.37 lukem #include <sys/cdefs.h> 49 1.66 thorpej __KERNEL_RCSID(0, "$NetBSD: aha.c,v 1.66 2022/09/25 18:43:32 thorpej Exp $"); 50 1.37 lukem 51 1.37 lukem #include "opt_ddb.h" 52 1.37 lukem 53 1.37 lukem #undef AHADIAG 54 1.1 mycroft 55 1.1 mycroft #include <sys/param.h> 56 1.1 mycroft #include <sys/systm.h> 57 1.26 thorpej #include <sys/callout.h> 58 1.1 mycroft #include <sys/kernel.h> 59 1.1 mycroft #include <sys/errno.h> 60 1.1 mycroft #include <sys/ioctl.h> 61 1.1 mycroft #include <sys/device.h> 62 1.1 mycroft #include <sys/buf.h> 63 1.1 mycroft #include <sys/proc.h> 64 1.1 mycroft 65 1.54 ad #include <sys/bus.h> 66 1.54 ad #include <sys/intr.h> 67 1.1 mycroft 68 1.7 bouyer #include <dev/scsipi/scsi_all.h> 69 1.7 bouyer #include <dev/scsipi/scsipi_all.h> 70 1.7 bouyer #include <dev/scsipi/scsiconf.h> 71 1.1 mycroft 72 1.1 mycroft #include <dev/ic/ahareg.h> 73 1.1 mycroft #include <dev/ic/ahavar.h> 74 1.1 mycroft 75 1.1 mycroft #ifndef DDB 76 1.1 mycroft #define Debugger() panic("should call debugger here (aha1542.c)") 77 1.1 mycroft #endif /* ! DDB */ 78 1.1 mycroft 79 1.5 thorpej #define AHA_MAXXFER ((AHA_NSEG - 1) << PGSHIFT) 80 1.1 mycroft 81 1.1 mycroft #ifdef AHADEBUG 82 1.1 mycroft int aha_debug = 1; 83 1.1 mycroft #endif /* AHADEBUG */ 84 1.1 mycroft 85 1.44 thorpej static int aha_cmd(bus_space_tag_t, bus_space_handle_t, 86 1.44 thorpej struct aha_softc *, int, u_char *, int, u_char *); 87 1.44 thorpej static void aha_finish_ccbs(struct aha_softc *); 88 1.44 thorpej static void aha_free_ccb(struct aha_softc *, struct aha_ccb *); 89 1.44 thorpej static int aha_init_ccb(struct aha_softc *, struct aha_ccb *); 90 1.44 thorpej static struct aha_ccb *aha_get_ccb(struct aha_softc *); 91 1.44 thorpej static struct aha_ccb *aha_ccb_phys_kv(struct aha_softc *, u_long); 92 1.44 thorpej static void aha_queue_ccb(struct aha_softc *, struct aha_ccb *); 93 1.44 thorpej static void aha_collect_mbo(struct aha_softc *); 94 1.44 thorpej static void aha_start_ccbs(struct aha_softc *); 95 1.44 thorpej static void aha_done(struct aha_softc *, struct aha_ccb *); 96 1.44 thorpej static int aha_init(struct aha_softc *); 97 1.44 thorpej static void aha_inquire_setup_information(struct aha_softc *); 98 1.44 thorpej static void ahaminphys(struct buf *); 99 1.44 thorpej static void aha_scsipi_request(struct scsipi_channel *, 100 1.44 thorpej scsipi_adapter_req_t, void *); 101 1.44 thorpej static int aha_poll(struct aha_softc *, struct scsipi_xfer *, int); 102 1.44 thorpej static void aha_timeout(void *arg); 103 1.44 thorpej static int aha_create_ccbs(struct aha_softc *, struct aha_ccb *, int); 104 1.1 mycroft 105 1.1 mycroft #define AHA_RESET_TIMEOUT 2000 /* time to wait for reset (mSec) */ 106 1.1 mycroft #define AHA_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */ 107 1.5 thorpej 108 1.1 mycroft /* 109 1.1 mycroft * aha_cmd(iot, ioh, sc, icnt, ibuf, ocnt, obuf) 110 1.1 mycroft * 111 1.1 mycroft * Activate Adapter command 112 1.1 mycroft * icnt: number of args (outbound bytes including opcode) 113 1.1 mycroft * ibuf: argument buffer 114 1.1 mycroft * ocnt: number of expected returned bytes 115 1.1 mycroft * obuf: result buffer 116 1.1 mycroft * wait: number of seconds to wait for response 117 1.1 mycroft * 118 1.1 mycroft * Performs an adapter command through the ports. Not to be confused with a 119 1.40 wiz * scsi command, which is read in via the DMA; one of the adapter commands 120 1.1 mycroft * tells it to read in a scsi command. 121 1.1 mycroft */ 122 1.44 thorpej static int 123 1.44 thorpej aha_cmd(bus_space_tag_t iot, bus_space_handle_t ioh, struct aha_softc *sc, 124 1.44 thorpej int icnt, u_char *ibuf, int ocnt, u_char *obuf) 125 1.1 mycroft { 126 1.1 mycroft const char *name; 127 1.28 augustss int i; 128 1.1 mycroft int wait; 129 1.42 reinoud u_char sts; 130 1.1 mycroft u_char opcode = ibuf[0]; 131 1.1 mycroft 132 1.1 mycroft if (sc != NULL) 133 1.59 tsutsui name = device_xname(sc->sc_dev); 134 1.1 mycroft else 135 1.1 mycroft name = "(aha probe)"; 136 1.1 mycroft 137 1.1 mycroft /* 138 1.1 mycroft * Calculate a reasonable timeout for the command. 139 1.1 mycroft */ 140 1.1 mycroft switch (opcode) { 141 1.1 mycroft case AHA_INQUIRE_DEVICES: 142 1.1 mycroft wait = 90 * 20000; 143 1.1 mycroft break; 144 1.1 mycroft default: 145 1.1 mycroft wait = 1 * 20000; 146 1.1 mycroft break; 147 1.1 mycroft } 148 1.1 mycroft 149 1.1 mycroft /* 150 1.1 mycroft * Wait for the adapter to go idle, unless it's one of 151 1.1 mycroft * the commands which don't need this 152 1.1 mycroft */ 153 1.1 mycroft if (opcode != AHA_MBO_INTR_EN) { 154 1.1 mycroft for (i = 20000; i; i--) { /* 1 sec? */ 155 1.1 mycroft sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 156 1.1 mycroft if (sts & AHA_STAT_IDLE) 157 1.1 mycroft break; 158 1.1 mycroft delay(50); 159 1.1 mycroft } 160 1.1 mycroft if (!i) { 161 1.1 mycroft printf("%s: aha_cmd, host not idle(0x%x)\n", 162 1.1 mycroft name, sts); 163 1.1 mycroft return (1); 164 1.1 mycroft } 165 1.1 mycroft } 166 1.1 mycroft /* 167 1.1 mycroft * Now that it is idle, if we expect output, preflush the 168 1.1 mycroft * queue feeding to us. 169 1.1 mycroft */ 170 1.1 mycroft if (ocnt) { 171 1.62 msaitoh while ((bus_space_read_1(iot, ioh, AHA_STAT_PORT)) 172 1.62 msaitoh & AHA_STAT_DF) 173 1.1 mycroft bus_space_read_1(iot, ioh, AHA_DATA_PORT); 174 1.1 mycroft } 175 1.1 mycroft /* 176 1.1 mycroft * Output the command and the number of arguments given 177 1.1 mycroft * for each byte, first check the port is empty. 178 1.1 mycroft */ 179 1.1 mycroft while (icnt--) { 180 1.1 mycroft for (i = wait; i; i--) { 181 1.1 mycroft sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 182 1.1 mycroft if (!(sts & AHA_STAT_CDF)) 183 1.1 mycroft break; 184 1.1 mycroft delay(50); 185 1.1 mycroft } 186 1.1 mycroft if (!i) { 187 1.1 mycroft if (opcode != AHA_INQUIRE_REVISION) 188 1.62 msaitoh printf("%s: aha_cmd, cmd/data port full\n", 189 1.62 msaitoh name); 190 1.62 msaitoh bus_space_write_1(iot, ioh, AHA_CTRL_PORT, 191 1.62 msaitoh AHA_CTRL_SRST); 192 1.1 mycroft return (1); 193 1.1 mycroft } 194 1.1 mycroft bus_space_write_1(iot, ioh, AHA_CMD_PORT, *ibuf++); 195 1.1 mycroft } 196 1.1 mycroft /* 197 1.1 mycroft * If we expect input, loop that many times, each time, 198 1.1 mycroft * looking for the data register to have valid data 199 1.1 mycroft */ 200 1.1 mycroft while (ocnt--) { 201 1.1 mycroft for (i = wait; i; i--) { 202 1.1 mycroft sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 203 1.1 mycroft if (sts & AHA_STAT_DF) 204 1.1 mycroft break; 205 1.1 mycroft delay(50); 206 1.1 mycroft } 207 1.1 mycroft if (!i) { 208 1.1 mycroft if (opcode != AHA_INQUIRE_REVISION) 209 1.1 mycroft printf("%s: aha_cmd, cmd/data port empty %d\n", 210 1.1 mycroft name, ocnt); 211 1.62 msaitoh bus_space_write_1(iot, ioh, AHA_CTRL_PORT, 212 1.62 msaitoh AHA_CTRL_SRST); 213 1.1 mycroft return (1); 214 1.1 mycroft } 215 1.1 mycroft *obuf++ = bus_space_read_1(iot, ioh, AHA_DATA_PORT); 216 1.1 mycroft } 217 1.1 mycroft /* 218 1.1 mycroft * Wait for the board to report a finished instruction. 219 1.1 mycroft * We may get an extra interrupt for the HACC signal, but this is 220 1.1 mycroft * unimportant. 221 1.1 mycroft */ 222 1.1 mycroft if (opcode != AHA_MBO_INTR_EN) { 223 1.1 mycroft for (i = 20000; i; i--) { /* 1 sec? */ 224 1.1 mycroft sts = bus_space_read_1(iot, ioh, AHA_INTR_PORT); 225 1.1 mycroft /* XXX Need to save this in the interrupt handler? */ 226 1.1 mycroft if (sts & AHA_INTR_HACC) 227 1.1 mycroft break; 228 1.1 mycroft delay(50); 229 1.1 mycroft } 230 1.1 mycroft if (!i) { 231 1.1 mycroft printf("%s: aha_cmd, host not finished(0x%x)\n", 232 1.1 mycroft name, sts); 233 1.1 mycroft return (1); 234 1.1 mycroft } 235 1.1 mycroft } 236 1.1 mycroft bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_IRST); 237 1.1 mycroft return (0); 238 1.1 mycroft } 239 1.1 mycroft 240 1.1 mycroft void 241 1.58 dsl aha_attach(struct aha_softc *sc, struct aha_probe_data *apd) 242 1.1 mycroft { 243 1.31 bouyer struct scsipi_adapter *adapt = &sc->sc_adapter; 244 1.31 bouyer struct scsipi_channel *chan = &sc->sc_channel; 245 1.1 mycroft 246 1.5 thorpej TAILQ_INIT(&sc->sc_free_ccb); 247 1.5 thorpej TAILQ_INIT(&sc->sc_waiting_ccb); 248 1.20 thorpej 249 1.20 thorpej /* 250 1.31 bouyer * Fill in the scsipi_adapter. 251 1.1 mycroft */ 252 1.31 bouyer memset(adapt, 0, sizeof(*adapt)); 253 1.59 tsutsui adapt->adapt_dev = sc->sc_dev; 254 1.31 bouyer adapt->adapt_nchannels = 1; 255 1.31 bouyer /* adapt_openings initialized below */ 256 1.31 bouyer /* adapt_max_periph initialized below */ 257 1.31 bouyer adapt->adapt_request = aha_scsipi_request; 258 1.31 bouyer adapt->adapt_minphys = ahaminphys; 259 1.31 bouyer 260 1.31 bouyer /* 261 1.31 bouyer * Fill in the scsipi_channel. 262 1.31 bouyer */ 263 1.31 bouyer memset(chan, 0, sizeof(*chan)); 264 1.31 bouyer chan->chan_adapter = adapt; 265 1.32 bouyer chan->chan_bustype = &scsi_bustype; 266 1.31 bouyer chan->chan_channel = 0; 267 1.31 bouyer chan->chan_ntargets = 8; 268 1.31 bouyer chan->chan_nluns = 8; 269 1.31 bouyer chan->chan_id = apd->sc_scsi_dev; 270 1.1 mycroft 271 1.6 hannken aha_inquire_setup_information(sc); 272 1.15 thorpej if (aha_init(sc) != 0) { 273 1.15 thorpej /* Error during initialization! */ 274 1.15 thorpej return; 275 1.15 thorpej } 276 1.6 hannken 277 1.1 mycroft /* 278 1.1 mycroft * ask the adapter what subunits are present 279 1.1 mycroft */ 280 1.65 thorpej config_found(sc->sc_dev, &sc->sc_channel, scsiprint, CFARGS_NONE); 281 1.1 mycroft } 282 1.1 mycroft 283 1.44 thorpej static void 284 1.44 thorpej aha_finish_ccbs(struct aha_softc *sc) 285 1.1 mycroft { 286 1.1 mycroft struct aha_mbx_in *wmbi; 287 1.1 mycroft struct aha_ccb *ccb; 288 1.1 mycroft int i; 289 1.1 mycroft 290 1.1 mycroft wmbi = wmbx->tmbi; 291 1.1 mycroft 292 1.15 thorpej bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control, 293 1.15 thorpej AHA_MBI_OFF(wmbi), sizeof(struct aha_mbx_in), 294 1.15 thorpej BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 295 1.15 thorpej 296 1.1 mycroft if (wmbi->stat == AHA_MBI_FREE) { 297 1.1 mycroft for (i = 0; i < AHA_MBX_SIZE; i++) { 298 1.1 mycroft if (wmbi->stat != AHA_MBI_FREE) { 299 1.1 mycroft printf("%s: mbi not in round-robin order\n", 300 1.59 tsutsui device_xname(sc->sc_dev)); 301 1.1 mycroft goto AGAIN; 302 1.1 mycroft } 303 1.1 mycroft aha_nextmbx(wmbi, wmbx, mbi); 304 1.15 thorpej bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control, 305 1.15 thorpej AHA_MBI_OFF(wmbi), sizeof(struct aha_mbx_in), 306 1.15 thorpej BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 307 1.1 mycroft } 308 1.1 mycroft #ifdef AHADIAGnot 309 1.1 mycroft printf("%s: mbi interrupt with no full mailboxes\n", 310 1.59 tsutsui device_xname(sc->sc_dev)); 311 1.1 mycroft #endif 312 1.1 mycroft return; 313 1.1 mycroft } 314 1.1 mycroft 315 1.1 mycroft AGAIN: 316 1.1 mycroft do { 317 1.1 mycroft ccb = aha_ccb_phys_kv(sc, phystol(wmbi->ccb_addr)); 318 1.1 mycroft if (!ccb) { 319 1.1 mycroft printf("%s: bad mbi ccb pointer; skipping\n", 320 1.59 tsutsui device_xname(sc->sc_dev)); 321 1.1 mycroft goto next; 322 1.1 mycroft } 323 1.1 mycroft 324 1.15 thorpej bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control, 325 1.15 thorpej AHA_CCB_OFF(ccb), sizeof(struct aha_ccb), 326 1.15 thorpej BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 327 1.15 thorpej 328 1.1 mycroft #ifdef AHADEBUG 329 1.1 mycroft if (aha_debug) { 330 1.50 christos u_char *cp = ccb->scsi_cmd; 331 1.1 mycroft printf("op=%x %x %x %x %x %x\n", 332 1.1 mycroft cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]); 333 1.50 christos printf("stat %x for mbi addr = %p, ", 334 1.1 mycroft wmbi->stat, wmbi); 335 1.50 christos printf("ccb addr = %p\n", ccb); 336 1.1 mycroft } 337 1.1 mycroft #endif /* AHADEBUG */ 338 1.1 mycroft 339 1.1 mycroft switch (wmbi->stat) { 340 1.1 mycroft case AHA_MBI_OK: 341 1.1 mycroft case AHA_MBI_ERROR: 342 1.1 mycroft if ((ccb->flags & CCB_ABORT) != 0) { 343 1.1 mycroft /* 344 1.1 mycroft * If we already started an abort, wait for it 345 1.1 mycroft * to complete before clearing the CCB. We 346 1.1 mycroft * could instead just clear CCB_SENDING, but 347 1.1 mycroft * what if the mailbox was already received? 348 1.1 mycroft * The worst that happens here is that we clear 349 1.1 mycroft * the CCB a bit later than we need to. BFD. 350 1.1 mycroft */ 351 1.1 mycroft goto next; 352 1.1 mycroft } 353 1.1 mycroft break; 354 1.1 mycroft 355 1.1 mycroft case AHA_MBI_ABORT: 356 1.1 mycroft case AHA_MBI_UNKNOWN: 357 1.1 mycroft /* 358 1.1 mycroft * Even if the CCB wasn't found, we clear it anyway. 359 1.36 wiz * See preceding comment. 360 1.1 mycroft */ 361 1.1 mycroft break; 362 1.1 mycroft 363 1.1 mycroft default: 364 1.1 mycroft printf("%s: bad mbi status %02x; skipping\n", 365 1.59 tsutsui device_xname(sc->sc_dev), wmbi->stat); 366 1.1 mycroft goto next; 367 1.1 mycroft } 368 1.1 mycroft 369 1.26 thorpej callout_stop(&ccb->xs->xs_callout); 370 1.1 mycroft aha_done(sc, ccb); 371 1.1 mycroft 372 1.1 mycroft next: 373 1.1 mycroft wmbi->stat = AHA_MBI_FREE; 374 1.15 thorpej bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control, 375 1.15 thorpej AHA_MBI_OFF(wmbi), sizeof(struct aha_mbx_in), 376 1.15 thorpej BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 377 1.1 mycroft aha_nextmbx(wmbi, wmbx, mbi); 378 1.15 thorpej bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control, 379 1.47 perry AHA_MBI_OFF(wmbi), sizeof(struct aha_mbx_in), 380 1.15 thorpej BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 381 1.1 mycroft } while (wmbi->stat != AHA_MBI_FREE); 382 1.1 mycroft 383 1.1 mycroft wmbx->tmbi = wmbi; 384 1.1 mycroft } 385 1.1 mycroft 386 1.1 mycroft /* 387 1.1 mycroft * Catch an interrupt from the adaptor 388 1.1 mycroft */ 389 1.1 mycroft int 390 1.58 dsl aha_intr(void *arg) 391 1.1 mycroft { 392 1.1 mycroft struct aha_softc *sc = arg; 393 1.1 mycroft bus_space_tag_t iot = sc->sc_iot; 394 1.1 mycroft bus_space_handle_t ioh = sc->sc_ioh; 395 1.1 mycroft u_char sts; 396 1.1 mycroft 397 1.1 mycroft #ifdef AHADEBUG 398 1.59 tsutsui printf("%s: aha_intr ", device_xname(sc->sc_dev)); 399 1.1 mycroft #endif /*AHADEBUG */ 400 1.1 mycroft 401 1.1 mycroft /* 402 1.43 wiz * First acknowledge the interrupt, Then if it's not telling about 403 1.1 mycroft * a completed operation just return. 404 1.1 mycroft */ 405 1.1 mycroft sts = bus_space_read_1(iot, ioh, AHA_INTR_PORT); 406 1.1 mycroft if ((sts & AHA_INTR_ANYINTR) == 0) 407 1.1 mycroft return (0); 408 1.1 mycroft bus_space_write_1(iot, ioh, AHA_CTRL_PORT, AHA_CTRL_IRST); 409 1.1 mycroft 410 1.1 mycroft #ifdef AHADIAG 411 1.1 mycroft /* Make sure we clear CCB_SENDING before finishing a CCB. */ 412 1.1 mycroft aha_collect_mbo(sc); 413 1.1 mycroft #endif 414 1.1 mycroft 415 1.1 mycroft /* Mail box out empty? */ 416 1.1 mycroft if (sts & AHA_INTR_MBOA) { 417 1.1 mycroft struct aha_toggle toggle; 418 1.1 mycroft 419 1.1 mycroft toggle.cmd.opcode = AHA_MBO_INTR_EN; 420 1.1 mycroft toggle.cmd.enable = 0; 421 1.1 mycroft aha_cmd(iot, ioh, sc, 422 1.1 mycroft sizeof(toggle.cmd), (u_char *)&toggle.cmd, 423 1.1 mycroft 0, (u_char *)0); 424 1.1 mycroft aha_start_ccbs(sc); 425 1.1 mycroft } 426 1.1 mycroft 427 1.1 mycroft /* Mail box in full? */ 428 1.1 mycroft if (sts & AHA_INTR_MBIF) 429 1.1 mycroft aha_finish_ccbs(sc); 430 1.1 mycroft 431 1.1 mycroft return (1); 432 1.1 mycroft } 433 1.1 mycroft 434 1.49 perry static inline void 435 1.52 christos aha_reset_ccb(struct aha_softc *sc, struct aha_ccb *ccb) 436 1.1 mycroft { 437 1.1 mycroft 438 1.1 mycroft ccb->flags = 0; 439 1.1 mycroft } 440 1.1 mycroft 441 1.1 mycroft /* 442 1.1 mycroft * A ccb is put onto the free list. 443 1.1 mycroft */ 444 1.44 thorpej static void 445 1.44 thorpej aha_free_ccb(struct aha_softc *sc, struct aha_ccb *ccb) 446 1.1 mycroft { 447 1.1 mycroft int s; 448 1.1 mycroft 449 1.1 mycroft s = splbio(); 450 1.1 mycroft aha_reset_ccb(sc, ccb); 451 1.1 mycroft TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain); 452 1.1 mycroft splx(s); 453 1.1 mycroft } 454 1.1 mycroft 455 1.44 thorpej static int 456 1.44 thorpej aha_init_ccb(struct aha_softc *sc, struct aha_ccb *ccb) 457 1.1 mycroft { 458 1.5 thorpej bus_dma_tag_t dmat = sc->sc_dmat; 459 1.9 thorpej int hashnum, error; 460 1.26 thorpej 461 1.5 thorpej /* 462 1.15 thorpej * Create the DMA map for this CCB. 463 1.5 thorpej */ 464 1.9 thorpej error = bus_dmamap_create(dmat, AHA_MAXXFER, AHA_NSEG, AHA_MAXXFER, 465 1.9 thorpej 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &ccb->dmamap_xfer); 466 1.9 thorpej if (error) { 467 1.59 tsutsui aprint_error_dev(sc->sc_dev, 468 1.59 tsutsui "unable to create ccb DMA map, error = %d\n", 469 1.56 cegger error); 470 1.9 thorpej return (error); 471 1.9 thorpej } 472 1.5 thorpej 473 1.1 mycroft /* 474 1.1 mycroft * put in the phystokv hash table 475 1.1 mycroft * Never gets taken out. 476 1.1 mycroft */ 477 1.15 thorpej ccb->hashkey = sc->sc_dmamap_control->dm_segs[0].ds_addr + 478 1.15 thorpej AHA_CCB_OFF(ccb); 479 1.1 mycroft hashnum = CCB_HASH(ccb->hashkey); 480 1.1 mycroft ccb->nexthash = sc->sc_ccbhash[hashnum]; 481 1.1 mycroft sc->sc_ccbhash[hashnum] = ccb; 482 1.1 mycroft aha_reset_ccb(sc, ccb); 483 1.9 thorpej return (0); 484 1.1 mycroft } 485 1.1 mycroft 486 1.1 mycroft /* 487 1.15 thorpej * Create a set of ccbs and add them to the free list. Called once 488 1.15 thorpej * by aha_init(). We return the number of CCBs successfully created. 489 1.5 thorpej */ 490 1.44 thorpej static int 491 1.44 thorpej aha_create_ccbs(struct aha_softc *sc, struct aha_ccb *ccbstore, int count) 492 1.5 thorpej { 493 1.5 thorpej struct aha_ccb *ccb; 494 1.15 thorpej int i, error; 495 1.5 thorpej 496 1.34 thorpej memset(ccbstore, 0, sizeof(struct aha_ccb) * count); 497 1.15 thorpej for (i = 0; i < count; i++) { 498 1.15 thorpej ccb = &ccbstore[i]; 499 1.15 thorpej if ((error = aha_init_ccb(sc, ccb)) != 0) { 500 1.59 tsutsui aprint_error_dev(sc->sc_dev, 501 1.59 tsutsui "unable to initialize ccb, error = %d\n", 502 1.56 cegger error); 503 1.15 thorpej goto out; 504 1.9 thorpej } 505 1.5 thorpej TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, chain); 506 1.5 thorpej } 507 1.15 thorpej out: 508 1.15 thorpej return (i); 509 1.5 thorpej } 510 1.5 thorpej 511 1.5 thorpej /* 512 1.1 mycroft * Get a free ccb 513 1.1 mycroft * 514 1.1 mycroft * If there are none, see if we can allocate a new one. If so, put it in 515 1.1 mycroft * the hash table too otherwise either return an error or sleep. 516 1.1 mycroft */ 517 1.1 mycroft struct aha_ccb * 518 1.44 thorpej aha_get_ccb(struct aha_softc *sc) 519 1.1 mycroft { 520 1.1 mycroft struct aha_ccb *ccb; 521 1.1 mycroft int s; 522 1.1 mycroft 523 1.1 mycroft s = splbio(); 524 1.31 bouyer ccb = TAILQ_FIRST(&sc->sc_free_ccb); 525 1.31 bouyer if (ccb != NULL) { 526 1.31 bouyer TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain); 527 1.31 bouyer ccb->flags |= CCB_ALLOC; 528 1.1 mycroft } 529 1.1 mycroft splx(s); 530 1.1 mycroft return (ccb); 531 1.1 mycroft } 532 1.1 mycroft 533 1.1 mycroft /* 534 1.1 mycroft * Given a physical address, find the ccb that it corresponds to. 535 1.1 mycroft */ 536 1.44 thorpej static struct aha_ccb * 537 1.44 thorpej aha_ccb_phys_kv(struct aha_softc *sc, u_long ccb_phys) 538 1.1 mycroft { 539 1.1 mycroft int hashnum = CCB_HASH(ccb_phys); 540 1.1 mycroft struct aha_ccb *ccb = sc->sc_ccbhash[hashnum]; 541 1.1 mycroft 542 1.1 mycroft while (ccb) { 543 1.1 mycroft if (ccb->hashkey == ccb_phys) 544 1.1 mycroft break; 545 1.1 mycroft ccb = ccb->nexthash; 546 1.1 mycroft } 547 1.1 mycroft return (ccb); 548 1.1 mycroft } 549 1.1 mycroft 550 1.1 mycroft /* 551 1.1 mycroft * Queue a CCB to be sent to the controller, and send it if possible. 552 1.1 mycroft */ 553 1.44 thorpej static void 554 1.44 thorpej aha_queue_ccb(struct aha_softc *sc, struct aha_ccb *ccb) 555 1.1 mycroft { 556 1.1 mycroft 557 1.1 mycroft TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain); 558 1.1 mycroft aha_start_ccbs(sc); 559 1.1 mycroft } 560 1.1 mycroft 561 1.1 mycroft /* 562 1.1 mycroft * Garbage collect mailboxes that are no longer in use. 563 1.1 mycroft */ 564 1.44 thorpej static void 565 1.44 thorpej aha_collect_mbo(struct aha_softc *sc) 566 1.1 mycroft { 567 1.1 mycroft struct aha_mbx_out *wmbo; /* Mail Box Out pointer */ 568 1.1 mycroft #ifdef AHADIAG 569 1.1 mycroft struct aha_ccb *ccb; 570 1.1 mycroft #endif 571 1.1 mycroft 572 1.1 mycroft wmbo = wmbx->cmbo; 573 1.1 mycroft 574 1.1 mycroft while (sc->sc_mbofull > 0) { 575 1.15 thorpej bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control, 576 1.15 thorpej AHA_MBO_OFF(wmbo), sizeof(struct aha_mbx_out), 577 1.15 thorpej BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 578 1.1 mycroft if (wmbo->cmd != AHA_MBO_FREE) 579 1.1 mycroft break; 580 1.1 mycroft 581 1.1 mycroft #ifdef AHADIAG 582 1.1 mycroft ccb = aha_ccb_phys_kv(sc, phystol(wmbo->ccb_addr)); 583 1.1 mycroft ccb->flags &= ~CCB_SENDING; 584 1.1 mycroft #endif 585 1.1 mycroft 586 1.1 mycroft --sc->sc_mbofull; 587 1.1 mycroft aha_nextmbx(wmbo, wmbx, mbo); 588 1.1 mycroft } 589 1.1 mycroft 590 1.1 mycroft wmbx->cmbo = wmbo; 591 1.1 mycroft } 592 1.1 mycroft 593 1.1 mycroft /* 594 1.1 mycroft * Send as many CCBs as we have empty mailboxes for. 595 1.1 mycroft */ 596 1.44 thorpej static void 597 1.44 thorpej aha_start_ccbs(struct aha_softc *sc) 598 1.1 mycroft { 599 1.1 mycroft bus_space_tag_t iot = sc->sc_iot; 600 1.1 mycroft bus_space_handle_t ioh = sc->sc_ioh; 601 1.1 mycroft struct aha_mbx_out *wmbo; /* Mail Box Out pointer */ 602 1.1 mycroft struct aha_ccb *ccb; 603 1.1 mycroft 604 1.1 mycroft wmbo = wmbx->tmbo; 605 1.1 mycroft 606 1.1 mycroft while ((ccb = sc->sc_waiting_ccb.tqh_first) != NULL) { 607 1.1 mycroft if (sc->sc_mbofull >= AHA_MBX_SIZE) { 608 1.1 mycroft aha_collect_mbo(sc); 609 1.1 mycroft if (sc->sc_mbofull >= AHA_MBX_SIZE) { 610 1.1 mycroft struct aha_toggle toggle; 611 1.1 mycroft 612 1.1 mycroft toggle.cmd.opcode = AHA_MBO_INTR_EN; 613 1.1 mycroft toggle.cmd.enable = 1; 614 1.1 mycroft aha_cmd(iot, ioh, sc, 615 1.1 mycroft sizeof(toggle.cmd), (u_char *)&toggle.cmd, 616 1.1 mycroft 0, (u_char *)0); 617 1.1 mycroft break; 618 1.1 mycroft } 619 1.1 mycroft } 620 1.1 mycroft 621 1.1 mycroft TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain); 622 1.1 mycroft #ifdef AHADIAG 623 1.1 mycroft ccb->flags |= CCB_SENDING; 624 1.1 mycroft #endif 625 1.1 mycroft 626 1.1 mycroft /* Link ccb to mbo. */ 627 1.15 thorpej ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr + 628 1.15 thorpej AHA_CCB_OFF(ccb), wmbo->ccb_addr); 629 1.1 mycroft if (ccb->flags & CCB_ABORT) 630 1.1 mycroft wmbo->cmd = AHA_MBO_ABORT; 631 1.1 mycroft else 632 1.1 mycroft wmbo->cmd = AHA_MBO_START; 633 1.1 mycroft 634 1.15 thorpej bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control, 635 1.15 thorpej AHA_MBO_OFF(wmbo), sizeof(struct aha_mbx_out), 636 1.15 thorpej BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 637 1.15 thorpej 638 1.1 mycroft /* Tell the card to poll immediately. */ 639 1.1 mycroft bus_space_write_1(iot, ioh, AHA_CMD_PORT, AHA_START_SCSI); 640 1.1 mycroft 641 1.24 thorpej if ((ccb->xs->xs_control & XS_CTL_POLL) == 0) 642 1.26 thorpej callout_reset(&ccb->xs->xs_callout, 643 1.39 bouyer mstohz(ccb->timeout), aha_timeout, ccb); 644 1.1 mycroft 645 1.1 mycroft ++sc->sc_mbofull; 646 1.1 mycroft aha_nextmbx(wmbo, wmbx, mbo); 647 1.1 mycroft } 648 1.1 mycroft 649 1.1 mycroft wmbx->tmbo = wmbo; 650 1.1 mycroft } 651 1.1 mycroft 652 1.1 mycroft /* 653 1.1 mycroft * We have a ccb which has been processed by the 654 1.1 mycroft * adaptor, now we look to see how the operation 655 1.1 mycroft * went. Wake up the owner if waiting 656 1.1 mycroft */ 657 1.44 thorpej static void 658 1.44 thorpej aha_done(struct aha_softc *sc, struct aha_ccb *ccb) 659 1.1 mycroft { 660 1.5 thorpej bus_dma_tag_t dmat = sc->sc_dmat; 661 1.46 thorpej struct scsi_sense_data *s1, *s2; 662 1.7 bouyer struct scsipi_xfer *xs = ccb->xs; 663 1.1 mycroft 664 1.31 bouyer SC_DEBUG(xs->xs_periph, SCSIPI_DB2, ("aha_done\n")); 665 1.5 thorpej 666 1.5 thorpej /* 667 1.5 thorpej * If we were a data transfer, unload the map that described 668 1.5 thorpej * the data buffer. 669 1.5 thorpej */ 670 1.5 thorpej if (xs->datalen) { 671 1.14 thorpej bus_dmamap_sync(dmat, ccb->dmamap_xfer, 0, 672 1.14 thorpej ccb->dmamap_xfer->dm_mapsize, 673 1.24 thorpej (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_POSTREAD : 674 1.5 thorpej BUS_DMASYNC_POSTWRITE); 675 1.5 thorpej bus_dmamap_unload(dmat, ccb->dmamap_xfer); 676 1.5 thorpej } 677 1.5 thorpej 678 1.1 mycroft /* 679 1.1 mycroft * Otherwise, put the results of the operation 680 1.1 mycroft * into the xfer and call whoever started it 681 1.1 mycroft */ 682 1.1 mycroft #ifdef AHADIAG 683 1.1 mycroft if (ccb->flags & CCB_SENDING) { 684 1.59 tsutsui printf("%s: exiting ccb still in transit!\n", 685 1.59 tsutsui device_xname(sc->sc_dev)); 686 1.1 mycroft Debugger(); 687 1.1 mycroft return; 688 1.1 mycroft } 689 1.1 mycroft #endif 690 1.1 mycroft if ((ccb->flags & CCB_ALLOC) == 0) { 691 1.59 tsutsui printf("%s: exiting ccb not allocated!\n", 692 1.59 tsutsui device_xname(sc->sc_dev)); 693 1.1 mycroft Debugger(); 694 1.1 mycroft return; 695 1.1 mycroft } 696 1.1 mycroft if (xs->error == XS_NOERROR) { 697 1.1 mycroft if (ccb->host_stat != AHA_OK) { 698 1.1 mycroft switch (ccb->host_stat) { 699 1.1 mycroft case AHA_SEL_TIMEOUT: /* No response */ 700 1.1 mycroft xs->error = XS_SELTIMEOUT; 701 1.1 mycroft break; 702 1.1 mycroft default: /* Other scsi protocol messes */ 703 1.1 mycroft printf("%s: host_stat %x\n", 704 1.59 tsutsui device_xname(sc->sc_dev), ccb->host_stat); 705 1.1 mycroft xs->error = XS_DRIVER_STUFFUP; 706 1.1 mycroft break; 707 1.1 mycroft } 708 1.1 mycroft } else if (ccb->target_stat != SCSI_OK) { 709 1.1 mycroft switch (ccb->target_stat) { 710 1.1 mycroft case SCSI_CHECK: 711 1.62 msaitoh s1 = (struct scsi_sense_data *) 712 1.62 msaitoh (((char *)(&ccb->scsi_cmd)) + 713 1.1 mycroft ccb->scsi_cmd_length); 714 1.7 bouyer s2 = &xs->sense.scsi_sense; 715 1.1 mycroft *s2 = *s1; 716 1.1 mycroft xs->error = XS_SENSE; 717 1.1 mycroft break; 718 1.1 mycroft case SCSI_BUSY: 719 1.1 mycroft xs->error = XS_BUSY; 720 1.1 mycroft break; 721 1.1 mycroft default: 722 1.1 mycroft printf("%s: target_stat %x\n", 723 1.59 tsutsui device_xname(sc->sc_dev), ccb->target_stat); 724 1.1 mycroft xs->error = XS_DRIVER_STUFFUP; 725 1.1 mycroft break; 726 1.1 mycroft } 727 1.1 mycroft } else 728 1.1 mycroft xs->resid = 0; 729 1.1 mycroft } 730 1.1 mycroft aha_free_ccb(sc, ccb); 731 1.7 bouyer scsipi_done(xs); 732 1.1 mycroft } 733 1.1 mycroft 734 1.1 mycroft /* 735 1.1 mycroft * Find the board and find its irq/drq 736 1.1 mycroft */ 737 1.1 mycroft int 738 1.62 msaitoh aha_find(bus_space_tag_t iot, bus_space_handle_t ioh, 739 1.62 msaitoh struct aha_probe_data *sc) 740 1.1 mycroft { 741 1.1 mycroft int i; 742 1.1 mycroft u_char sts; 743 1.1 mycroft struct aha_config config; 744 1.1 mycroft int irq, drq; 745 1.1 mycroft 746 1.1 mycroft /* 747 1.55 ad * assume invalid status means the board is not present. 748 1.55 ad */ 749 1.55 ad 750 1.55 ad sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 751 1.55 ad if (sts == 0) 752 1.55 ad return (0); 753 1.55 ad if ((sts & (AHA_STAT_STST|AHA_STAT_RSVD|AHA_STAT_CDF)) != 0) 754 1.55 ad return (0); 755 1.55 ad sts = bus_space_read_1(iot, ioh, AHA_INTR_PORT); 756 1.55 ad if ((sts & AHA_INTR_RSVD) != 0) 757 1.55 ad return (0); 758 1.55 ad 759 1.55 ad /* 760 1.1 mycroft * reset board, If it doesn't respond, assume 761 1.1 mycroft * that it's not there.. good for the probe 762 1.1 mycroft */ 763 1.1 mycroft 764 1.62 msaitoh bus_space_write_1(iot, ioh, AHA_CTRL_PORT, 765 1.62 msaitoh AHA_CTRL_HRST | AHA_CTRL_SRST); 766 1.1 mycroft 767 1.1 mycroft delay(100); 768 1.1 mycroft for (i = AHA_RESET_TIMEOUT; i; i--) { 769 1.1 mycroft sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 770 1.1 mycroft if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT)) 771 1.1 mycroft break; 772 1.1 mycroft delay(1000); /* calibrated in msec */ 773 1.1 mycroft } 774 1.1 mycroft if (!i) { 775 1.1 mycroft #ifdef AHADEBUG 776 1.1 mycroft if (aha_debug) 777 1.1 mycroft printf("aha_find: No answer from adaptec board\n"); 778 1.1 mycroft #endif /* AHADEBUG */ 779 1.1 mycroft return (0); 780 1.1 mycroft } 781 1.1 mycroft 782 1.1 mycroft /* 783 1.40 wiz * setup DMA channel from jumpers and save int 784 1.1 mycroft * level 785 1.1 mycroft */ 786 1.1 mycroft delay(1000); /* for Bustek 545 */ 787 1.1 mycroft config.cmd.opcode = AHA_INQUIRE_CONFIG; 788 1.4 mycroft aha_cmd(iot, ioh, (struct aha_softc *)0, 789 1.1 mycroft sizeof(config.cmd), (u_char *)&config.cmd, 790 1.1 mycroft sizeof(config.reply), (u_char *)&config.reply); 791 1.1 mycroft switch (config.reply.chan) { 792 1.1 mycroft case EISADMA: 793 1.1 mycroft drq = -1; 794 1.1 mycroft break; 795 1.1 mycroft case CHAN0: 796 1.1 mycroft drq = 0; 797 1.1 mycroft break; 798 1.1 mycroft case CHAN5: 799 1.1 mycroft drq = 5; 800 1.1 mycroft break; 801 1.1 mycroft case CHAN6: 802 1.1 mycroft drq = 6; 803 1.1 mycroft break; 804 1.1 mycroft case CHAN7: 805 1.1 mycroft drq = 7; 806 1.1 mycroft break; 807 1.1 mycroft default: 808 1.1 mycroft printf("aha_find: illegal drq setting %x\n", config.reply.chan); 809 1.1 mycroft return (0); 810 1.1 mycroft } 811 1.1 mycroft 812 1.1 mycroft switch (config.reply.intr) { 813 1.1 mycroft case INT9: 814 1.1 mycroft irq = 9; 815 1.1 mycroft break; 816 1.1 mycroft case INT10: 817 1.1 mycroft irq = 10; 818 1.1 mycroft break; 819 1.1 mycroft case INT11: 820 1.1 mycroft irq = 11; 821 1.1 mycroft break; 822 1.1 mycroft case INT12: 823 1.1 mycroft irq = 12; 824 1.1 mycroft break; 825 1.1 mycroft case INT14: 826 1.1 mycroft irq = 14; 827 1.1 mycroft break; 828 1.1 mycroft case INT15: 829 1.1 mycroft irq = 15; 830 1.1 mycroft break; 831 1.1 mycroft default: 832 1.1 mycroft printf("aha_find: illegal irq setting %x\n", config.reply.intr); 833 1.1 mycroft return (0); 834 1.1 mycroft } 835 1.1 mycroft 836 1.4 mycroft if (sc) { 837 1.1 mycroft sc->sc_irq = irq; 838 1.1 mycroft sc->sc_drq = drq; 839 1.1 mycroft sc->sc_scsi_dev = config.reply.scsi_dev; 840 1.1 mycroft } 841 1.1 mycroft 842 1.1 mycroft return (1); 843 1.1 mycroft } 844 1.1 mycroft 845 1.1 mycroft /* 846 1.1 mycroft * Start the board, ready for normal operation 847 1.1 mycroft */ 848 1.44 thorpej static int 849 1.44 thorpej aha_init(struct aha_softc *sc) 850 1.1 mycroft { 851 1.1 mycroft bus_space_tag_t iot = sc->sc_iot; 852 1.1 mycroft bus_space_handle_t ioh = sc->sc_ioh; 853 1.5 thorpej bus_dma_segment_t seg; 854 1.1 mycroft struct aha_devices devices; 855 1.1 mycroft struct aha_setup setup; 856 1.1 mycroft struct aha_mailbox mailbox; 857 1.15 thorpej int error, i, j, initial_ccbs, rseg; 858 1.1 mycroft 859 1.1 mycroft /* 860 1.1 mycroft * XXX 861 1.1 mycroft * If we are a 1542C or later, disable the extended BIOS so that the 862 1.1 mycroft * mailbox interface is unlocked. 863 1.1 mycroft * No need to check the extended BIOS flags as some of the 864 1.1 mycroft * extensions that cause us problems are not flagged in that byte. 865 1.1 mycroft */ 866 1.1 mycroft if (!strncmp(sc->sc_model, "1542C", 5)) { 867 1.1 mycroft struct aha_extbios extbios; 868 1.1 mycroft struct aha_unlock unlock; 869 1.1 mycroft 870 1.59 tsutsui printf("%s: unlocking mailbox interface\n", 871 1.59 tsutsui device_xname(sc->sc_dev)); 872 1.1 mycroft extbios.cmd.opcode = AHA_EXT_BIOS; 873 1.1 mycroft aha_cmd(iot, ioh, sc, 874 1.1 mycroft sizeof(extbios.cmd), (u_char *)&extbios.cmd, 875 1.1 mycroft sizeof(extbios.reply), (u_char *)&extbios.reply); 876 1.1 mycroft 877 1.1 mycroft #ifdef AHADEBUG 878 1.1 mycroft printf("%s: flags=%02x, mailboxlock=%02x\n", 879 1.59 tsutsui device_xname(sc->sc_dev), 880 1.1 mycroft extbios.reply.flags, extbios.reply.mailboxlock); 881 1.1 mycroft #endif /* AHADEBUG */ 882 1.1 mycroft 883 1.1 mycroft unlock.cmd.opcode = AHA_MBX_ENABLE; 884 1.1 mycroft unlock.cmd.junk = 0; 885 1.1 mycroft unlock.cmd.magic = extbios.reply.mailboxlock; 886 1.1 mycroft aha_cmd(iot, ioh, sc, 887 1.1 mycroft sizeof(unlock.cmd), (u_char *)&unlock.cmd, 888 1.1 mycroft 0, (u_char *)0); 889 1.1 mycroft } 890 1.1 mycroft 891 1.1 mycroft #if 0 892 1.1 mycroft /* 893 1.40 wiz * Change the bus on/off times to not clash with other DMA users. 894 1.1 mycroft */ 895 1.1 mycroft aha_cmd(iot, ioh, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7); 896 1.1 mycroft aha_cmd(iot, ioh, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4); 897 1.1 mycroft #endif 898 1.1 mycroft 899 1.1 mycroft /* Inquire Installed Devices (to force synchronous negotiation). */ 900 1.1 mycroft devices.cmd.opcode = AHA_INQUIRE_DEVICES; 901 1.1 mycroft aha_cmd(iot, ioh, sc, 902 1.1 mycroft sizeof(devices.cmd), (u_char *)&devices.cmd, 903 1.1 mycroft sizeof(devices.reply), (u_char *)&devices.reply); 904 1.1 mycroft 905 1.6 hannken /* Count installed units */ 906 1.6 hannken initial_ccbs = 0; 907 1.6 hannken for (i = 0; i < 8; i++) { 908 1.6 hannken for (j = 0; j < 8; j++) { 909 1.6 hannken if (((devices.reply.lun_map[i] >> j) & 1) == 1) 910 1.6 hannken initial_ccbs += 1; 911 1.6 hannken } 912 1.6 hannken } 913 1.31 bouyer initial_ccbs *= 2; 914 1.15 thorpej if (initial_ccbs > AHA_CCB_MAX) 915 1.15 thorpej initial_ccbs = AHA_CCB_MAX; 916 1.16 thorpej if (initial_ccbs == 0) /* yes, this can happen */ 917 1.31 bouyer initial_ccbs = 2; 918 1.6 hannken 919 1.1 mycroft /* Obtain setup information from. */ 920 1.1 mycroft setup.cmd.opcode = AHA_INQUIRE_SETUP; 921 1.1 mycroft setup.cmd.len = sizeof(setup.reply); 922 1.1 mycroft aha_cmd(iot, ioh, sc, 923 1.1 mycroft sizeof(setup.cmd), (u_char *)&setup.cmd, 924 1.1 mycroft sizeof(setup.reply), (u_char *)&setup.reply); 925 1.1 mycroft 926 1.1 mycroft printf("%s: %s, %s\n", 927 1.59 tsutsui device_xname(sc->sc_dev), 928 1.1 mycroft setup.reply.sync_neg ? "sync" : "async", 929 1.1 mycroft setup.reply.parity ? "parity" : "no parity"); 930 1.1 mycroft 931 1.1 mycroft for (i = 0; i < 8; i++) { 932 1.1 mycroft if (!setup.reply.sync[i].valid || 933 1.62 msaitoh (!setup.reply.sync[i].offset 934 1.62 msaitoh && !setup.reply.sync[i].period)) 935 1.1 mycroft continue; 936 1.1 mycroft printf("%s targ %d: sync, offset %d, period %dnsec\n", 937 1.62 msaitoh device_xname(sc->sc_dev), i, setup.reply.sync[i].offset, 938 1.62 msaitoh setup.reply.sync[i].period * 50 + 200); 939 1.1 mycroft } 940 1.1 mycroft 941 1.1 mycroft /* 942 1.15 thorpej * Allocate the mailbox and control blocks. 943 1.5 thorpej */ 944 1.15 thorpej if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct aha_control), 945 1.29 thorpej PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { 946 1.59 tsutsui aprint_error_dev(sc->sc_dev, 947 1.59 tsutsui "unable to allocate control structures, " 948 1.56 cegger "error = %d\n", error); 949 1.15 thorpej return (error); 950 1.15 thorpej } 951 1.15 thorpej if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, 952 1.53 christos sizeof(struct aha_control), (void **)&sc->sc_control, 953 1.15 thorpej BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { 954 1.59 tsutsui aprint_error_dev(sc->sc_dev, 955 1.59 tsutsui "unable to map control structures, error = %d\n", error); 956 1.15 thorpej return (error); 957 1.15 thorpej } 958 1.5 thorpej 959 1.5 thorpej /* 960 1.15 thorpej * Create and load the DMA map used for the mailbox and 961 1.15 thorpej * control blocks. 962 1.5 thorpej */ 963 1.15 thorpej if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct aha_control), 964 1.15 thorpej 1, sizeof(struct aha_control), 0, BUS_DMA_NOWAIT, 965 1.15 thorpej &sc->sc_dmamap_control)) != 0) { 966 1.59 tsutsui aprint_error_dev(sc->sc_dev, 967 1.63 msaitoh "unable to create control DMA map, error = %d\n", error); 968 1.15 thorpej return (error); 969 1.15 thorpej } 970 1.15 thorpej if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_control, 971 1.15 thorpej sc->sc_control, sizeof(struct aha_control), NULL, 972 1.15 thorpej BUS_DMA_NOWAIT)) != 0) { 973 1.59 tsutsui aprint_error_dev(sc->sc_dev, 974 1.63 msaitoh "unable to load control DMA map, error = %d\n", error); 975 1.15 thorpej return (error); 976 1.15 thorpej } 977 1.5 thorpej 978 1.5 thorpej /* 979 1.15 thorpej * Initialize the control blocks. 980 1.5 thorpej */ 981 1.15 thorpej i = aha_create_ccbs(sc, sc->sc_control->ac_ccbs, initial_ccbs); 982 1.15 thorpej if (i == 0) { 983 1.59 tsutsui aprint_error_dev(sc->sc_dev, 984 1.59 tsutsui "unable to create control blocks\n"); 985 1.15 thorpej return (ENOMEM); 986 1.15 thorpej } else if (i != initial_ccbs) { 987 1.15 thorpej printf("%s: WARNING: only %d of %d control blocks created\n", 988 1.59 tsutsui device_xname(sc->sc_dev), i, initial_ccbs); 989 1.15 thorpej } 990 1.5 thorpej 991 1.31 bouyer sc->sc_adapter.adapt_openings = i; 992 1.31 bouyer sc->sc_adapter.adapt_max_periph = sc->sc_adapter.adapt_openings; 993 1.31 bouyer 994 1.5 thorpej /* 995 1.1 mycroft * Set up initial mail box for round-robin operation. 996 1.1 mycroft */ 997 1.1 mycroft for (i = 0; i < AHA_MBX_SIZE; i++) { 998 1.1 mycroft wmbx->mbo[i].cmd = AHA_MBO_FREE; 999 1.15 thorpej bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control, 1000 1.15 thorpej AHA_MBO_OFF(&wmbx->mbo[i]), sizeof(struct aha_mbx_out), 1001 1.15 thorpej BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 1002 1.1 mycroft wmbx->mbi[i].stat = AHA_MBI_FREE; 1003 1.15 thorpej bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control, 1004 1.15 thorpej AHA_MBI_OFF(&wmbx->mbi[i]), sizeof(struct aha_mbx_in), 1005 1.15 thorpej BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 1006 1.1 mycroft } 1007 1.1 mycroft wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0]; 1008 1.1 mycroft wmbx->tmbi = &wmbx->mbi[0]; 1009 1.1 mycroft sc->sc_mbofull = 0; 1010 1.1 mycroft 1011 1.1 mycroft /* Initialize mail box. */ 1012 1.1 mycroft mailbox.cmd.opcode = AHA_MBX_INIT; 1013 1.1 mycroft mailbox.cmd.nmbx = AHA_MBX_SIZE; 1014 1.15 thorpej ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr + 1015 1.15 thorpej offsetof(struct aha_control, ac_mbx), mailbox.cmd.addr); 1016 1.1 mycroft aha_cmd(iot, ioh, sc, 1017 1.1 mycroft sizeof(mailbox.cmd), (u_char *)&mailbox.cmd, 1018 1.1 mycroft 0, (u_char *)0); 1019 1.15 thorpej return (0); 1020 1.1 mycroft } 1021 1.1 mycroft 1022 1.44 thorpej static void 1023 1.44 thorpej aha_inquire_setup_information(struct aha_softc *sc) 1024 1.1 mycroft { 1025 1.1 mycroft bus_space_tag_t iot = sc->sc_iot; 1026 1.1 mycroft bus_space_handle_t ioh = sc->sc_ioh; 1027 1.1 mycroft struct aha_revision revision; 1028 1.1 mycroft u_char sts; 1029 1.1 mycroft int i; 1030 1.1 mycroft char *p; 1031 1.1 mycroft 1032 1.1 mycroft strcpy(sc->sc_model, "unknown"); 1033 1.1 mycroft 1034 1.1 mycroft /* 1035 1.1 mycroft * Assume we have a board at this stage, do an adapter inquire 1036 1.1 mycroft * to find out what type of controller it is. If the command 1037 1.1 mycroft * fails, we assume it's either a crusty board or an old 1542 1038 1.1 mycroft * clone, and skip the board-specific stuff. 1039 1.1 mycroft */ 1040 1.1 mycroft revision.cmd.opcode = AHA_INQUIRE_REVISION; 1041 1.1 mycroft if (aha_cmd(iot, ioh, sc, 1042 1.1 mycroft sizeof(revision.cmd), (u_char *)&revision.cmd, 1043 1.1 mycroft sizeof(revision.reply), (u_char *)&revision.reply)) { 1044 1.1 mycroft /* 1045 1.1 mycroft * aha_cmd() already started the reset. It's not clear we 1046 1.1 mycroft * even need to bother here. 1047 1.1 mycroft */ 1048 1.1 mycroft for (i = AHA_RESET_TIMEOUT; i; i--) { 1049 1.1 mycroft sts = bus_space_read_1(iot, ioh, AHA_STAT_PORT); 1050 1.1 mycroft if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT)) 1051 1.1 mycroft break; 1052 1.1 mycroft delay(1000); 1053 1.1 mycroft } 1054 1.1 mycroft if (!i) { 1055 1.1 mycroft #ifdef AHADEBUG 1056 1.1 mycroft printf("aha_init: soft reset failed\n"); 1057 1.1 mycroft #endif /* AHADEBUG */ 1058 1.1 mycroft return; 1059 1.1 mycroft } 1060 1.1 mycroft #ifdef AHADEBUG 1061 1.1 mycroft printf("aha_init: inquire command failed\n"); 1062 1.1 mycroft #endif /* AHADEBUG */ 1063 1.1 mycroft goto noinquire; 1064 1.1 mycroft } 1065 1.1 mycroft 1066 1.1 mycroft #ifdef AHADEBUG 1067 1.1 mycroft printf("%s: inquire %x, %x, %x, %x\n", 1068 1.59 tsutsui device_xname(sc->sc_dev), 1069 1.1 mycroft revision.reply.boardid, revision.reply.spec_opts, 1070 1.1 mycroft revision.reply.revision_1, revision.reply.revision_2); 1071 1.1 mycroft #endif /* AHADEBUG */ 1072 1.1 mycroft 1073 1.1 mycroft switch (revision.reply.boardid) { 1074 1.23 mjl case BOARD_1540_16HEAD_BIOS: 1075 1.23 mjl case BOARD_1540_64HEAD_BIOS: 1076 1.23 mjl case BOARD_1540: 1077 1.1 mycroft strcpy(sc->sc_model, "1540"); 1078 1.1 mycroft break; 1079 1.23 mjl case BOARD_1542: 1080 1.1 mycroft strcpy(sc->sc_model, "1540A/1542A/1542B"); 1081 1.1 mycroft break; 1082 1.23 mjl case BOARD_1640: 1083 1.1 mycroft strcpy(sc->sc_model, "1640"); 1084 1.1 mycroft break; 1085 1.23 mjl case BOARD_1740: 1086 1.23 mjl strcpy(sc->sc_model, "1740"); 1087 1.23 mjl break; 1088 1.23 mjl case BOARD_1542C: 1089 1.1 mycroft strcpy(sc->sc_model, "1542C"); 1090 1.1 mycroft break; 1091 1.23 mjl case BOARD_1542CF: 1092 1.1 mycroft strcpy(sc->sc_model, "1542CF"); 1093 1.1 mycroft break; 1094 1.23 mjl case BOARD_1542CP: 1095 1.1 mycroft strcpy(sc->sc_model, "1542CP"); 1096 1.1 mycroft break; 1097 1.1 mycroft } 1098 1.1 mycroft 1099 1.1 mycroft p = sc->sc_firmware; 1100 1.1 mycroft *p++ = revision.reply.revision_1; 1101 1.1 mycroft *p++ = '.'; 1102 1.1 mycroft *p++ = revision.reply.revision_2; 1103 1.1 mycroft *p = '\0'; 1104 1.1 mycroft 1105 1.1 mycroft noinquire: 1106 1.2 sommerfe printf("%s: model AHA-%s, firmware %s\n", 1107 1.59 tsutsui device_xname(sc->sc_dev), 1108 1.2 sommerfe sc->sc_model, sc->sc_firmware); 1109 1.1 mycroft } 1110 1.1 mycroft 1111 1.44 thorpej static void 1112 1.44 thorpej ahaminphys(struct buf *bp) 1113 1.1 mycroft { 1114 1.1 mycroft 1115 1.5 thorpej if (bp->b_bcount > AHA_MAXXFER) 1116 1.5 thorpej bp->b_bcount = AHA_MAXXFER; 1117 1.1 mycroft minphys(bp); 1118 1.1 mycroft } 1119 1.1 mycroft 1120 1.1 mycroft /* 1121 1.1 mycroft * start a scsi operation given the command and the data address. Also needs 1122 1.1 mycroft * the unit, target and lu. 1123 1.1 mycroft */ 1124 1.31 bouyer 1125 1.44 thorpej static void 1126 1.44 thorpej aha_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, 1127 1.44 thorpej void *arg) 1128 1.31 bouyer { 1129 1.7 bouyer struct scsipi_xfer *xs; 1130 1.31 bouyer struct scsipi_periph *periph; 1131 1.59 tsutsui struct aha_softc *sc = device_private(chan->chan_adapter->adapt_dev); 1132 1.5 thorpej bus_dma_tag_t dmat = sc->sc_dmat; 1133 1.1 mycroft struct aha_ccb *ccb; 1134 1.5 thorpej int error, seg, flags, s; 1135 1.10 thorpej 1136 1.10 thorpej 1137 1.31 bouyer switch (req) { 1138 1.31 bouyer case ADAPTER_REQ_RUN_XFER: 1139 1.31 bouyer xs = arg; 1140 1.31 bouyer periph = xs->xs_periph; 1141 1.31 bouyer flags = xs->xs_control; 1142 1.31 bouyer 1143 1.31 bouyer SC_DEBUG(periph, SCSIPI_DB2, ("aha_scsipi_request\n")); 1144 1.31 bouyer 1145 1.31 bouyer /* Get a CCB to use. */ 1146 1.31 bouyer ccb = aha_get_ccb(sc); 1147 1.31 bouyer #ifdef DIAGNOSTIC 1148 1.10 thorpej /* 1149 1.31 bouyer * This should never happen as we track the resources 1150 1.31 bouyer * in the mid-layer. 1151 1.10 thorpej */ 1152 1.31 bouyer if (ccb == NULL) { 1153 1.31 bouyer scsipi_printaddr(periph); 1154 1.31 bouyer printf("unable to allocate ccb\n"); 1155 1.31 bouyer panic("aha_scsipi_request"); 1156 1.10 thorpej } 1157 1.31 bouyer #endif 1158 1.31 bouyer 1159 1.31 bouyer ccb->xs = xs; 1160 1.31 bouyer ccb->timeout = xs->timeout; 1161 1.10 thorpej 1162 1.10 thorpej /* 1163 1.31 bouyer * Put all the arguments for the xfer in the ccb 1164 1.10 thorpej */ 1165 1.31 bouyer if (flags & XS_CTL_RESET) { 1166 1.31 bouyer ccb->opcode = AHA_RESET_CCB; 1167 1.31 bouyer ccb->scsi_cmd_length = 0; 1168 1.31 bouyer } else { 1169 1.31 bouyer /* can't use S/G if zero length */ 1170 1.45 thorpej if (xs->cmdlen > sizeof(ccb->scsi_cmd)) { 1171 1.45 thorpej printf("%s: cmdlen %d too large for CCB\n", 1172 1.59 tsutsui device_xname(sc->sc_dev), xs->cmdlen); 1173 1.45 thorpej xs->error = XS_DRIVER_STUFFUP; 1174 1.45 thorpej goto out_bad; 1175 1.45 thorpej } 1176 1.31 bouyer ccb->opcode = (xs->datalen ? AHA_INIT_SCAT_GATH_CCB 1177 1.31 bouyer : AHA_INITIATOR_CCB); 1178 1.33 thorpej memcpy(&ccb->scsi_cmd, xs->cmd, 1179 1.31 bouyer ccb->scsi_cmd_length = xs->cmdlen); 1180 1.10 thorpej } 1181 1.10 thorpej 1182 1.31 bouyer if (xs->datalen) { 1183 1.31 bouyer /* 1184 1.31 bouyer * Map the DMA transfer. 1185 1.31 bouyer */ 1186 1.31 bouyer #ifdef TFS 1187 1.31 bouyer if (flags & XS_CTL_DATA_UIO) { 1188 1.31 bouyer error = bus_dmamap_load_uio(dmat, 1189 1.31 bouyer ccb->dmamap_xfer, (struct uio *)xs->data, 1190 1.31 bouyer ((flags & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT : 1191 1.35 thorpej BUS_DMA_WAITOK) | BUS_DMA_STREAMING | 1192 1.35 thorpej ((flags & XS_CTL_DATA_IN) ? BUS_DMA_READ : 1193 1.35 thorpej BUS_DMA_WRITE)); 1194 1.31 bouyer } else 1195 1.31 bouyer #endif 1196 1.31 bouyer { 1197 1.31 bouyer error = bus_dmamap_load(dmat, 1198 1.31 bouyer ccb->dmamap_xfer, xs->data, xs->datalen, 1199 1.31 bouyer NULL, 1200 1.31 bouyer ((flags & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT : 1201 1.35 thorpej BUS_DMA_WAITOK) | BUS_DMA_STREAMING | 1202 1.35 thorpej ((flags & XS_CTL_DATA_IN) ? BUS_DMA_READ : 1203 1.35 thorpej BUS_DMA_WRITE)); 1204 1.31 bouyer } 1205 1.31 bouyer 1206 1.31 bouyer switch (error) { 1207 1.31 bouyer case 0: 1208 1.31 bouyer break; 1209 1.10 thorpej 1210 1.31 bouyer case ENOMEM: 1211 1.31 bouyer case EAGAIN: 1212 1.31 bouyer xs->error = XS_RESOURCE_SHORTAGE; 1213 1.31 bouyer goto out_bad; 1214 1.10 thorpej 1215 1.31 bouyer default: 1216 1.31 bouyer xs->error = XS_DRIVER_STUFFUP; 1217 1.31 bouyer if (error == EFBIG) { 1218 1.31 bouyer printf("%s: aha_scsi_cmd, more than %d" 1219 1.40 wiz " DMA segments\n", 1220 1.59 tsutsui device_xname(sc->sc_dev), AHA_NSEG); 1221 1.31 bouyer } else { 1222 1.59 tsutsui aprint_error_dev(sc->sc_dev, 1223 1.59 tsutsui "error %d loading DMA map\n", 1224 1.56 cegger error); 1225 1.31 bouyer } 1226 1.31 bouyer out_bad: 1227 1.31 bouyer aha_free_ccb(sc, ccb); 1228 1.31 bouyer scsipi_done(xs); 1229 1.31 bouyer return; 1230 1.31 bouyer } 1231 1.1 mycroft 1232 1.31 bouyer bus_dmamap_sync(dmat, ccb->dmamap_xfer, 0, 1233 1.31 bouyer ccb->dmamap_xfer->dm_mapsize, 1234 1.31 bouyer (flags & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD : 1235 1.31 bouyer BUS_DMASYNC_PREWRITE); 1236 1.1 mycroft 1237 1.31 bouyer /* 1238 1.31 bouyer * Load the hardware scatter/gather map with the 1239 1.31 bouyer * contents of the DMA map. 1240 1.31 bouyer */ 1241 1.31 bouyer for (seg = 0; seg < ccb->dmamap_xfer->dm_nsegs; seg++) { 1242 1.31 bouyer ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_addr, 1243 1.31 bouyer ccb->scat_gath[seg].seg_addr); 1244 1.31 bouyer ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_len, 1245 1.31 bouyer ccb->scat_gath[seg].seg_len); 1246 1.1 mycroft } 1247 1.31 bouyer 1248 1.31 bouyer ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr + 1249 1.31 bouyer AHA_CCB_OFF(ccb) + 1250 1.31 bouyer offsetof(struct aha_ccb, scat_gath), 1251 1.31 bouyer ccb->data_addr); 1252 1.31 bouyer ltophys(ccb->dmamap_xfer->dm_nsegs * 1253 1.31 bouyer sizeof(struct aha_scat_gath), ccb->data_length); 1254 1.31 bouyer } else { 1255 1.31 bouyer /* 1256 1.31 bouyer * No data xfer, use non S/G values. 1257 1.31 bouyer */ 1258 1.31 bouyer ltophys(0, ccb->data_addr); 1259 1.31 bouyer ltophys(0, ccb->data_length); 1260 1.1 mycroft } 1261 1.5 thorpej 1262 1.31 bouyer ccb->data_out = 0; 1263 1.31 bouyer ccb->data_in = 0; 1264 1.31 bouyer ccb->target = periph->periph_target; 1265 1.31 bouyer ccb->lun = periph->periph_lun; 1266 1.31 bouyer ccb->req_sense_length = sizeof(ccb->scsi_sense); 1267 1.31 bouyer ccb->host_stat = 0x00; 1268 1.31 bouyer ccb->target_stat = 0x00; 1269 1.31 bouyer ccb->link_id = 0; 1270 1.31 bouyer ltophys(0, ccb->link_addr); 1271 1.5 thorpej 1272 1.31 bouyer bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control, 1273 1.31 bouyer AHA_CCB_OFF(ccb), sizeof(struct aha_ccb), 1274 1.31 bouyer BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 1275 1.5 thorpej 1276 1.31 bouyer s = splbio(); 1277 1.31 bouyer aha_queue_ccb(sc, ccb); 1278 1.31 bouyer splx(s); 1279 1.1 mycroft 1280 1.31 bouyer SC_DEBUG(periph, SCSIPI_DB3, ("cmd_sent\n")); 1281 1.31 bouyer if ((flags & XS_CTL_POLL) == 0) 1282 1.31 bouyer return; 1283 1.15 thorpej 1284 1.31 bouyer /* Not allowed to use interrupts, poll for completion. */ 1285 1.31 bouyer if (aha_poll(sc, xs, ccb->timeout)) { 1286 1.31 bouyer aha_timeout(ccb); 1287 1.31 bouyer if (aha_poll(sc, xs, ccb->timeout)) 1288 1.31 bouyer aha_timeout(ccb); 1289 1.31 bouyer } 1290 1.31 bouyer return; 1291 1.1 mycroft 1292 1.31 bouyer case ADAPTER_REQ_GROW_RESOURCES: 1293 1.31 bouyer /* XXX Not supported. */ 1294 1.31 bouyer return; 1295 1.1 mycroft 1296 1.31 bouyer case ADAPTER_REQ_SET_XFER_MODE: 1297 1.31 bouyer /* 1298 1.31 bouyer * Can't really do this on the Adaptec; it has 1299 1.31 bouyer * its own config mechanism, but we do know how 1300 1.31 bouyer * to query what the firmware negotiated. 1301 1.31 bouyer */ 1302 1.31 bouyer /* XXX XXX XXX */ 1303 1.31 bouyer return; 1304 1.1 mycroft } 1305 1.1 mycroft } 1306 1.1 mycroft 1307 1.1 mycroft /* 1308 1.1 mycroft * Poll a particular unit, looking for a particular xs 1309 1.1 mycroft */ 1310 1.44 thorpej static int 1311 1.44 thorpej aha_poll(struct aha_softc *sc, struct scsipi_xfer *xs, int count) 1312 1.1 mycroft { 1313 1.1 mycroft bus_space_tag_t iot = sc->sc_iot; 1314 1.1 mycroft bus_space_handle_t ioh = sc->sc_ioh; 1315 1.1 mycroft 1316 1.1 mycroft /* timeouts are in msec, so we loop in 1000 usec cycles */ 1317 1.1 mycroft while (count) { 1318 1.1 mycroft /* 1319 1.1 mycroft * If we had interrupts enabled, would we 1320 1.1 mycroft * have got an interrupt? 1321 1.1 mycroft */ 1322 1.62 msaitoh if (bus_space_read_1(iot, ioh, AHA_INTR_PORT) 1323 1.62 msaitoh & AHA_INTR_ANYINTR) 1324 1.1 mycroft aha_intr(sc); 1325 1.24 thorpej if (xs->xs_status & XS_STS_DONE) 1326 1.1 mycroft return (0); 1327 1.1 mycroft delay(1000); /* only happens in boot so ok */ 1328 1.1 mycroft count--; 1329 1.1 mycroft } 1330 1.1 mycroft return (1); 1331 1.1 mycroft } 1332 1.1 mycroft 1333 1.44 thorpej static void 1334 1.44 thorpej aha_timeout(void *arg) 1335 1.1 mycroft { 1336 1.1 mycroft struct aha_ccb *ccb = arg; 1337 1.7 bouyer struct scsipi_xfer *xs = ccb->xs; 1338 1.31 bouyer struct scsipi_periph *periph = xs->xs_periph; 1339 1.31 bouyer struct aha_softc *sc = 1340 1.59 tsutsui device_private(periph->periph_channel->chan_adapter->adapt_dev); 1341 1.1 mycroft int s; 1342 1.1 mycroft 1343 1.31 bouyer scsipi_printaddr(periph); 1344 1.1 mycroft printf("timed out"); 1345 1.1 mycroft 1346 1.1 mycroft s = splbio(); 1347 1.1 mycroft 1348 1.1 mycroft #ifdef AHADIAG 1349 1.1 mycroft /* 1350 1.1 mycroft * If The ccb's mbx is not free, then the board has gone south? 1351 1.1 mycroft */ 1352 1.1 mycroft aha_collect_mbo(sc); 1353 1.1 mycroft if (ccb->flags & CCB_SENDING) { 1354 1.59 tsutsui aprint_error_dev(sc->sc_dev, "not taking commands!\n"); 1355 1.1 mycroft Debugger(); 1356 1.1 mycroft } 1357 1.1 mycroft #endif 1358 1.1 mycroft 1359 1.1 mycroft /* 1360 1.1 mycroft * If it has been through before, then 1361 1.1 mycroft * a previous abort has failed, don't 1362 1.1 mycroft * try abort again 1363 1.1 mycroft */ 1364 1.1 mycroft if (ccb->flags & CCB_ABORT) { 1365 1.1 mycroft /* abort timed out */ 1366 1.1 mycroft printf(" AGAIN\n"); 1367 1.1 mycroft /* XXX Must reset! */ 1368 1.1 mycroft } else { 1369 1.1 mycroft /* abort the operation that has timed out */ 1370 1.1 mycroft printf("\n"); 1371 1.1 mycroft ccb->xs->error = XS_TIMEOUT; 1372 1.1 mycroft ccb->timeout = AHA_ABORT_TIMEOUT; 1373 1.1 mycroft ccb->flags |= CCB_ABORT; 1374 1.1 mycroft aha_queue_ccb(sc, ccb); 1375 1.1 mycroft } 1376 1.1 mycroft 1377 1.1 mycroft splx(s); 1378 1.1 mycroft } 1379