Annotation of sys/dev/ic/aic79xx.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: aic79xx.c,v 1.39 2007/05/09 19:24:56 miod Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2004 Milos Urbanek, Kenneth R. Westerback & Marco Peereboom
! 5: * All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: *
! 16: * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
! 17: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 19: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
! 20: * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 26: * SUCH DAMAGE.
! 27: *
! 28: */
! 29:
! 30: /*
! 31: * Core routines and tables shareable across OS platforms.
! 32: *
! 33: * Copyright (c) 1994-2002, 2004 Justin T. Gibbs.
! 34: * Copyright (c) 2000-2003 Adaptec Inc.
! 35: * All rights reserved.
! 36: *
! 37: * Redistribution and use in source and binary forms, with or without
! 38: * modification, are permitted provided that the following conditions
! 39: * are met:
! 40: * 1. Redistributions of source code must retain the above copyright
! 41: * notice, this list of conditions, and the following disclaimer,
! 42: * without modification.
! 43: * 2. Redistributions in binary form must reproduce at minimum a disclaimer
! 44: * substantially similar to the "NO WARRANTY" disclaimer below
! 45: * ("Disclaimer") and any redistribution must be conditioned upon
! 46: * including a substantially similar Disclaimer requirement for further
! 47: * binary redistribution.
! 48: * 3. Neither the names of the above-listed copyright holders nor the names
! 49: * of any contributors may be used to endorse or promote products derived
! 50: * from this software without specific prior written permission.
! 51: *
! 52: * Alternatively, this software may be distributed under the terms of the
! 53: * GNU General Public License ("GPL") version 2 as published by the Free
! 54: * Software Foundation.
! 55: *
! 56: * NO WARRANTY
! 57: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
! 58: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
! 59: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
! 60: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
! 61: * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 62: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 63: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 64: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 65: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
! 66: * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 67: * POSSIBILITY OF SUCH DAMAGES.
! 68: *
! 69: * Id: //depot/aic7xxx/aic7xxx/aic79xx.c#246
! 70: *
! 71: * FreeBSD: src/sys/dev/aic7xxx/aic79xx.c,v 1.33 2004/11/18 20:22:30 gibbs Exp
! 72: */
! 73:
! 74: #include <sys/cdefs.h>
! 75:
! 76: #include <dev/ic/aic79xx_openbsd.h>
! 77: #include <dev/ic/aic79xx_inline.h>
! 78: #include <dev/ic/aic79xx.h>
! 79:
! 80: #include <dev/microcode/aic7xxx/aicasm.h>
! 81: #include <dev/microcode/aic7xxx/aicasm_insformat.h>
! 82:
! 83: /******************************** Globals *************************************/
! 84: struct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq);
! 85: uint32_t ahd_attach_to_HostRAID_controllers = 1;
! 86:
! 87: /***************************** Lookup Tables **********************************/
! 88: char *ahd_chip_names[] =
! 89: {
! 90: "NONE",
! 91: "aic7901",
! 92: "aic7902",
! 93: "aic7901A"
! 94: };
! 95: static const u_int num_chip_names = NUM_ELEMENTS(ahd_chip_names);
! 96:
! 97: /*
! 98: * Hardware error codes.
! 99: */
! 100: struct ahd_hard_error_entry {
! 101: uint8_t errno;
! 102: char *errmesg;
! 103: };
! 104:
! 105: static struct ahd_hard_error_entry ahd_hard_errors[] = {
! 106: { DSCTMOUT, "Discard Timer has timed out" },
! 107: { ILLOPCODE, "Illegal Opcode in sequencer program" },
! 108: { SQPARERR, "Sequencer Parity Error" },
! 109: { DPARERR, "Data-path Parity Error" },
! 110: { MPARERR, "Scratch or SCB Memory Parity Error" },
! 111: { CIOPARERR, "CIOBUS Parity Error" },
! 112: };
! 113: static const u_int num_errors = NUM_ELEMENTS(ahd_hard_errors);
! 114:
! 115: static struct ahd_phase_table_entry ahd_phase_table[] =
! 116: {
! 117: { P_DATAOUT, MSG_NOOP, "in Data-out phase" },
! 118: { P_DATAIN, MSG_INITIATOR_DET_ERR, "in Data-in phase" },
! 119: { P_DATAOUT_DT, MSG_NOOP, "in DT Data-out phase" },
! 120: { P_DATAIN_DT, MSG_INITIATOR_DET_ERR, "in DT Data-in phase" },
! 121: { P_COMMAND, MSG_NOOP, "in Command phase" },
! 122: { P_MESGOUT, MSG_NOOP, "in Message-out phase" },
! 123: { P_STATUS, MSG_INITIATOR_DET_ERR, "in Status phase" },
! 124: { P_MESGIN, MSG_PARITY_ERROR, "in Message-in phase" },
! 125: { P_BUSFREE, MSG_NOOP, "while idle" },
! 126: { 0, MSG_NOOP, "in unknown phase" }
! 127: };
! 128:
! 129: /*
! 130: * In most cases we only wish to itterate over real phases, so
! 131: * exclude the last element from the count.
! 132: */
! 133: static const u_int num_phases = NUM_ELEMENTS(ahd_phase_table) - 1;
! 134:
! 135: /* Our Sequencer Program */
! 136: #include <dev/microcode/aic7xxx/aic79xx_seq.h>
! 137:
! 138: /**************************** Function Declarations ***************************/
! 139: void ahd_handle_transmission_error(struct ahd_softc *ahd);
! 140: void ahd_handle_lqiphase_error(struct ahd_softc *ahd,
! 141: u_int lqistat1);
! 142: int ahd_handle_pkt_busfree(struct ahd_softc *ahd,
! 143: u_int busfreetime);
! 144: int ahd_handle_nonpkt_busfree(struct ahd_softc *ahd);
! 145: void ahd_handle_proto_violation(struct ahd_softc *ahd);
! 146: void ahd_force_renegotiation(struct ahd_softc *ahd,
! 147: struct ahd_devinfo *devinfo);
! 148:
! 149: struct ahd_tmode_tstate*
! 150: ahd_alloc_tstate(struct ahd_softc *ahd,
! 151: u_int scsi_id, char channel);
! 152: #ifdef AHD_TARGET_MODE
! 153: void ahd_free_tstate(struct ahd_softc *ahd,
! 154: u_int scsi_id, char channel, int force);
! 155: #endif
! 156: void ahd_devlimited_syncrate(struct ahd_softc *ahd,
! 157: struct ahd_initiator_tinfo *,
! 158: u_int *period,
! 159: u_int *ppr_options,
! 160: role_t role);
! 161: void ahd_update_neg_table(struct ahd_softc *ahd,
! 162: struct ahd_devinfo *devinfo,
! 163: struct ahd_transinfo *tinfo);
! 164: void ahd_update_pending_scbs(struct ahd_softc *ahd);
! 165: void ahd_fetch_devinfo(struct ahd_softc *ahd,
! 166: struct ahd_devinfo *devinfo);
! 167: void ahd_scb_devinfo(struct ahd_softc *ahd,
! 168: struct ahd_devinfo *devinfo,
! 169: struct scb *scb);
! 170: void ahd_setup_initiator_msgout(struct ahd_softc *ahd,
! 171: struct ahd_devinfo *devinfo,
! 172: struct scb *scb);
! 173: void ahd_build_transfer_msg(struct ahd_softc *ahd,
! 174: struct ahd_devinfo *devinfo);
! 175: void ahd_construct_sdtr(struct ahd_softc *ahd,
! 176: struct ahd_devinfo *devinfo,
! 177: u_int period, u_int offset);
! 178: void ahd_construct_wdtr(struct ahd_softc *ahd,
! 179: struct ahd_devinfo *devinfo,
! 180: u_int bus_width);
! 181: void ahd_construct_ppr(struct ahd_softc *ahd,
! 182: struct ahd_devinfo *devinfo,
! 183: u_int period, u_int offset,
! 184: u_int bus_width, u_int ppr_options);
! 185: void ahd_clear_msg_state(struct ahd_softc *ahd);
! 186: void ahd_handle_message_phase(struct ahd_softc *ahd);
! 187: typedef enum {
! 188: AHDMSG_1B,
! 189: AHDMSG_2B,
! 190: AHDMSG_EXT
! 191: } ahd_msgtype;
! 192: int ahd_sent_msg(struct ahd_softc *ahd, ahd_msgtype type,
! 193: u_int msgval, int full);
! 194: int ahd_parse_msg(struct ahd_softc *ahd,
! 195: struct ahd_devinfo *devinfo);
! 196: int ahd_handle_msg_reject(struct ahd_softc *ahd,
! 197: struct ahd_devinfo *devinfo);
! 198: void ahd_handle_ign_wide_residue(struct ahd_softc *ahd,
! 199: struct ahd_devinfo *devinfo);
! 200: void ahd_reinitialize_dataptrs(struct ahd_softc *ahd);
! 201: void ahd_handle_devreset(struct ahd_softc *ahd,
! 202: struct ahd_devinfo *devinfo,
! 203: u_int lun, cam_status status,
! 204: char *message, int verbose_level);
! 205: #if AHD_TARGET_MODE
! 206: void ahd_setup_target_msgin(struct ahd_softc *ahd,
! 207: struct ahd_devinfo *devinfo,
! 208: struct scb *scb);
! 209: #endif
! 210:
! 211: u_int ahd_sglist_size(struct ahd_softc *ahd);
! 212: u_int ahd_sglist_allocsize(struct ahd_softc *ahd);
! 213: void ahd_initialize_hscbs(struct ahd_softc *ahd);
! 214: int ahd_init_scbdata(struct ahd_softc *ahd);
! 215: struct scb * ahd_find_scb_by_tag(struct ahd_softc *, u_int);
! 216: void ahd_fini_scbdata(struct ahd_softc *ahd);
! 217: void ahd_setup_iocell_workaround(struct ahd_softc *ahd);
! 218: void ahd_iocell_first_selection(struct ahd_softc *ahd);
! 219: void ahd_add_col_list(struct ahd_softc *ahd,
! 220: struct scb *scb, u_int col_idx);
! 221: void ahd_rem_col_list(struct ahd_softc *ahd,
! 222: struct scb *scb);
! 223: void ahd_chip_init(struct ahd_softc *ahd);
! 224: void ahd_qinfifo_requeue(struct ahd_softc *ahd,
! 225: struct scb *prev_scb,
! 226: struct scb *scb);
! 227: int ahd_qinfifo_count(struct ahd_softc *ahd);
! 228: int ahd_search_scb_list(struct ahd_softc *ahd, int target,
! 229: char channel, int lun, u_int tag,
! 230: role_t role, uint32_t status,
! 231: ahd_search_action action,
! 232: u_int *list_head, u_int *list_tail,
! 233: u_int tid);
! 234: void ahd_stitch_tid_list(struct ahd_softc *ahd,
! 235: u_int tid_prev, u_int tid_cur,
! 236: u_int tid_next);
! 237: void ahd_add_scb_to_free_list(struct ahd_softc *ahd,
! 238: u_int scbid);
! 239: u_int ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid,
! 240: u_int prev, u_int next, u_int tid);
! 241: void ahd_reset_current_bus(struct ahd_softc *ahd);
! 242: ahd_callback_t ahd_reset_poll;
! 243: ahd_callback_t ahd_stat_timer;
! 244: #ifdef AHD_DUMP_SEQ
! 245: void ahd_dumpseq(struct ahd_softc *ahd);
! 246: #endif
! 247: void ahd_loadseq(struct ahd_softc *ahd);
! 248: int ahd_check_patch(struct ahd_softc *ahd,
! 249: const struct patch **start_patch,
! 250: u_int start_instr, u_int *skip_addr);
! 251: u_int ahd_resolve_seqaddr(struct ahd_softc *ahd,
! 252: u_int address);
! 253: void ahd_download_instr(struct ahd_softc *ahd,
! 254: u_int instrptr, uint8_t *dconsts);
! 255: int ahd_probe_stack_size(struct ahd_softc *ahd);
! 256: int ahd_scb_active_in_fifo(struct ahd_softc *ahd,
! 257: struct scb *scb);
! 258: void ahd_run_data_fifo(struct ahd_softc *ahd,
! 259: struct scb *scb);
! 260:
! 261: #ifdef AHD_TARGET_MODE
! 262: void ahd_queue_lstate_event(struct ahd_softc *ahd,
! 263: struct ahd_tmode_lstate *lstate,
! 264: u_int initiator_id,
! 265: u_int event_type,
! 266: u_int event_arg);
! 267: void ahd_update_scsiid(struct ahd_softc *ahd,
! 268: u_int targid_mask);
! 269: int ahd_handle_target_cmd(struct ahd_softc *ahd,
! 270: struct target_cmd *cmd);
! 271: #endif
! 272:
! 273: /************************** Added for porting to NetBSD ***********************/
! 274: int ahd_createdmamem(struct ahd_softc *, size_t, struct map_node *,
! 275: const char *);
! 276:
! 277: void ahd_freedmamem(struct ahd_softc *, struct map_node *);
! 278:
! 279: /******************************** Private Inlines *****************************/
! 280: __inline void ahd_assert_atn(struct ahd_softc *ahd);
! 281: int ahd_currently_packetized(struct ahd_softc *ahd);
! 282: int ahd_set_active_fifo(struct ahd_softc *ahd);
! 283:
! 284: __inline void
! 285: ahd_assert_atn(struct ahd_softc *ahd)
! 286: {
! 287: ahd_outb(ahd, SCSISIGO, ATNO);
! 288: }
! 289:
! 290: /*
! 291: * Determine if the current connection has a packetized
! 292: * agreement. This does not necessarily mean that we
! 293: * are currently in a packetized transfer. We could
! 294: * just as easily be sending or receiving a message.
! 295: */
! 296: int
! 297: ahd_currently_packetized(struct ahd_softc *ahd)
! 298: {
! 299: ahd_mode_state saved_modes;
! 300: int packetized;
! 301:
! 302: saved_modes = ahd_save_modes(ahd);
! 303: if ((ahd->bugs & AHD_PKTIZED_STATUS_BUG) != 0) {
! 304: /*
! 305: * The packetized bit refers to the last
! 306: * connection, not the current one. Check
! 307: * for non-zero LQISTATE instead.
! 308: */
! 309: ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
! 310: packetized = ahd_inb(ahd, LQISTATE) != 0;
! 311: } else {
! 312: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 313: packetized = ahd_inb(ahd, LQISTAT2) & PACKETIZED;
! 314: }
! 315: ahd_restore_modes(ahd, saved_modes);
! 316: return (packetized);
! 317: }
! 318:
! 319: int
! 320: ahd_set_active_fifo(struct ahd_softc *ahd)
! 321: {
! 322: u_int active_fifo;
! 323:
! 324: AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
! 325: active_fifo = ahd_inb(ahd, DFFSTAT) & CURRFIFO;
! 326: switch (active_fifo) {
! 327: case 0:
! 328: case 1:
! 329: ahd_set_modes(ahd, active_fifo, active_fifo);
! 330: return (1);
! 331: default:
! 332: return (0);
! 333: }
! 334: }
! 335:
! 336: /************************* Sequencer Execution Control ************************/
! 337: /*
! 338: * Restart the sequencer program from address zero
! 339: */
! 340: void
! 341: ahd_restart(struct ahd_softc *ahd)
! 342: {
! 343:
! 344: ahd_pause(ahd);
! 345:
! 346: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 347:
! 348: /* No more pending messages */
! 349: ahd_clear_msg_state(ahd);
! 350: ahd_outb(ahd, SCSISIGO, 0); /* De-assert BSY */
! 351: ahd_outb(ahd, MSG_OUT, MSG_NOOP); /* No message to send */
! 352: ahd_outb(ahd, SXFRCTL1, ahd_inb(ahd, SXFRCTL1) & ~BITBUCKET);
! 353: ahd_outb(ahd, SEQINTCTL, 0);
! 354: ahd_outb(ahd, LASTPHASE, P_BUSFREE);
! 355: ahd_outb(ahd, SEQ_FLAGS, 0);
! 356: ahd_outb(ahd, SAVED_SCSIID, 0xFF);
! 357: ahd_outb(ahd, SAVED_LUN, 0xFF);
! 358:
! 359: /*
! 360: * Ensure that the sequencer's idea of TQINPOS
! 361: * matches our own. The sequencer increments TQINPOS
! 362: * only after it sees a DMA complete and a reset could
! 363: * occur before the increment leaving the kernel to believe
! 364: * the command arrived but the sequencer to not.
! 365: */
! 366: ahd_outb(ahd, TQINPOS, ahd->tqinfifonext);
! 367:
! 368: /* Always allow reselection */
! 369: ahd_outb(ahd, SCSISEQ1,
! 370: ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP));
! 371: ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
! 372:
! 373: /*
! 374: * Clear any pending sequencer interrupt. It is no
! 375: * longer relevant since we're resetting the Program
! 376: * Counter.
! 377: */
! 378: ahd_outb(ahd, CLRINT, CLRSEQINT);
! 379:
! 380: ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);
! 381: ahd_unpause(ahd);
! 382: }
! 383:
! 384: void
! 385: ahd_clear_fifo(struct ahd_softc *ahd, u_int fifo)
! 386: {
! 387: ahd_mode_state saved_modes;
! 388:
! 389: #ifdef AHD_DEBUG
! 390: if ((ahd_debug & AHD_SHOW_FIFOS) != 0)
! 391: printf("%s: Clearing FIFO %d\n", ahd_name(ahd), fifo);
! 392: #endif
! 393: saved_modes = ahd_save_modes(ahd);
! 394: ahd_set_modes(ahd, fifo, fifo);
! 395: ahd_outb(ahd, DFFSXFRCTL, RSTCHN|CLRSHCNT);
! 396: if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
! 397: ahd_outb(ahd, CCSGCTL, CCSGRESET);
! 398: ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
! 399: ahd_outb(ahd, SG_STATE, 0);
! 400: ahd_restore_modes(ahd, saved_modes);
! 401: }
! 402:
! 403: /************************* Input/Output Queues ********************************/
! 404: /*
! 405: * Flush and completed commands that are sitting in the command
! 406: * complete queues down on the chip but have yet to be dma'ed back up.
! 407: */
! 408: void
! 409: ahd_flush_qoutfifo(struct ahd_softc *ahd)
! 410: {
! 411: struct scb *scb;
! 412: ahd_mode_state saved_modes;
! 413: u_int saved_scbptr;
! 414: u_int ccscbctl;
! 415: u_int scbid;
! 416: u_int next_scbid;
! 417:
! 418: saved_modes = ahd_save_modes(ahd);
! 419:
! 420: /*
! 421: * Flush the good status FIFO for completed packetized commands.
! 422: */
! 423: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 424: saved_scbptr = ahd_get_scbptr(ahd);
! 425: while ((ahd_inb(ahd, LQISTAT2) & LQIGSAVAIL) != 0) {
! 426: u_int fifo_mode;
! 427: u_int i;
! 428:
! 429: scbid = ahd_inw(ahd, GSFIFO);
! 430: scb = ahd_lookup_scb(ahd, scbid);
! 431: if (scb == NULL) {
! 432: printf("%s: Warning - GSFIFO SCB %d invalid\n",
! 433: ahd_name(ahd), scbid);
! 434: continue;
! 435: }
! 436: /*
! 437: * Determine if this transaction is still active in
! 438: * any FIFO. If it is, we must flush that FIFO to
! 439: * the host before completing the command.
! 440: */
! 441: fifo_mode = 0;
! 442: rescan_fifos:
! 443: for (i = 0; i < 2; i++) {
! 444: /* Toggle to the other mode. */
! 445: fifo_mode ^= 1;
! 446: ahd_set_modes(ahd, fifo_mode, fifo_mode);
! 447:
! 448: if (ahd_scb_active_in_fifo(ahd, scb) == 0)
! 449: continue;
! 450:
! 451: ahd_run_data_fifo(ahd, scb);
! 452:
! 453: /*
! 454: * Running this FIFO may cause a CFG4DATA for
! 455: * this same transaction to assert in the other
! 456: * FIFO or a new snapshot SAVEPTRS interrupt
! 457: * in this FIFO. Even running a FIFO may not
! 458: * clear the transaction if we are still waiting
! 459: * for data to drain to the host. We must loop
! 460: * until the transaction is not active in either
! 461: * FIFO just to be sure. Reset our loop counter
! 462: * so we will visit both FIFOs again before
! 463: * declaring this transaction finished. We
! 464: * also delay a bit so that status has a chance
! 465: * to change before we look at this FIFO again.
! 466: */
! 467: aic_delay(200);
! 468: goto rescan_fifos;
! 469: }
! 470: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 471: ahd_set_scbptr(ahd, scbid);
! 472: if ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_LIST_NULL) == 0
! 473: && ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_FULL_RESID) != 0
! 474: || (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR)
! 475: & SG_LIST_NULL) != 0)) {
! 476: u_int comp_head;
! 477:
! 478: /*
! 479: * The transfer completed with a residual.
! 480: * Place this SCB on the complete DMA list
! 481: * so that we update our in-core copy of the
! 482: * SCB before completing the command.
! 483: */
! 484: ahd_outb(ahd, SCB_SCSI_STATUS, 0);
! 485: ahd_outb(ahd, SCB_SGPTR,
! 486: ahd_inb_scbram(ahd, SCB_SGPTR)
! 487: | SG_STATUS_VALID);
! 488: ahd_outw(ahd, SCB_TAG, scbid);
! 489: ahd_outw(ahd, SCB_NEXT_COMPLETE, SCB_LIST_NULL);
! 490: comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
! 491: if (SCBID_IS_NULL(comp_head)) {
! 492: ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, scbid);
! 493: ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);
! 494: } else {
! 495: u_int tail;
! 496:
! 497: tail = ahd_inw(ahd, COMPLETE_DMA_SCB_TAIL);
! 498: ahd_set_scbptr(ahd, tail);
! 499: ahd_outw(ahd, SCB_NEXT_COMPLETE, scbid);
! 500: ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);
! 501: ahd_set_scbptr(ahd, scbid);
! 502: }
! 503: } else
! 504: ahd_complete_scb(ahd, scb);
! 505: }
! 506: ahd_set_scbptr(ahd, saved_scbptr);
! 507:
! 508: /*
! 509: * Setup for command channel portion of flush.
! 510: */
! 511: ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
! 512:
! 513: /*
! 514: * Wait for any inprogress DMA to complete and clear DMA state
! 515: * if this if for an SCB in the qinfifo.
! 516: */
! 517: while (((ccscbctl = ahd_inb(ahd, CCSCBCTL)) & (CCARREN|CCSCBEN)) != 0) {
! 518:
! 519: if ((ccscbctl & (CCSCBDIR|CCARREN)) == (CCSCBDIR|CCARREN)) {
! 520: if ((ccscbctl & ARRDONE) != 0)
! 521: break;
! 522: } else if ((ccscbctl & CCSCBDONE) != 0)
! 523: break;
! 524: aic_delay(200);
! 525: }
! 526: /*
! 527: * We leave the sequencer to cleanup in the case of DMA's to
! 528: * update the qoutfifo. In all other cases (DMA's to the
! 529: * chip or a push of an SCB from the COMPLETE_DMA_SCB list),
! 530: * we disable the DMA engine so that the sequencer will not
! 531: * attempt to handle the DMA completion.
! 532: */
! 533: if ((ccscbctl & CCSCBDIR) != 0 || (ccscbctl & ARRDONE) != 0)
! 534: ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN));
! 535:
! 536: /*
! 537: * Complete any SCBs that just finished
! 538: * being DMA'ed into the qoutfifo.
! 539: */
! 540: ahd_run_qoutfifo(ahd);
! 541:
! 542: saved_scbptr = ahd_get_scbptr(ahd);
! 543: /*
! 544: * Manually update/complete any completed SCBs that are waiting to be
! 545: * DMA'ed back up to the host.
! 546: */
! 547: scbid = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
! 548: while (!SCBID_IS_NULL(scbid)) {
! 549: uint8_t *hscb_ptr;
! 550: u_int i;
! 551:
! 552: ahd_set_scbptr(ahd, scbid);
! 553: next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
! 554: scb = ahd_lookup_scb(ahd, scbid);
! 555: if (scb == NULL) {
! 556: printf("%s: Warning - DMA-up and complete "
! 557: "SCB %d invalid\n", ahd_name(ahd), scbid);
! 558: continue;
! 559: }
! 560: hscb_ptr = (uint8_t *)scb->hscb;
! 561: for (i = 0; i < sizeof(struct hardware_scb); i++)
! 562: *hscb_ptr++ = ahd_inb_scbram(ahd, SCB_BASE + i);
! 563:
! 564: ahd_complete_scb(ahd, scb);
! 565: scbid = next_scbid;
! 566: }
! 567: ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);
! 568: ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);
! 569:
! 570: scbid = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);
! 571: while (!SCBID_IS_NULL(scbid)) {
! 572:
! 573: ahd_set_scbptr(ahd, scbid);
! 574: next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
! 575: scb = ahd_lookup_scb(ahd, scbid);
! 576: if (scb == NULL) {
! 577: printf("%s: Warning - Complete Qfrz SCB %d invalid\n",
! 578: ahd_name(ahd), scbid);
! 579: continue;
! 580: }
! 581:
! 582: ahd_complete_scb(ahd, scb);
! 583: scbid = next_scbid;
! 584: }
! 585: ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);
! 586:
! 587: scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD);
! 588: while (!SCBID_IS_NULL(scbid)) {
! 589:
! 590: ahd_set_scbptr(ahd, scbid);
! 591: next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
! 592: scb = ahd_lookup_scb(ahd, scbid);
! 593: if (scb == NULL) {
! 594: printf("%s: Warning - Complete SCB %d invalid\n",
! 595: ahd_name(ahd), scbid);
! 596: continue;
! 597: }
! 598:
! 599: ahd_complete_scb(ahd, scb);
! 600: scbid = next_scbid;
! 601: }
! 602: ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);
! 603:
! 604: /*
! 605: * Restore state.
! 606: */
! 607: ahd_set_scbptr(ahd, saved_scbptr);
! 608: ahd_restore_modes(ahd, saved_modes);
! 609: ahd->flags |= AHD_UPDATE_PEND_CMDS;
! 610: }
! 611:
! 612: /*
! 613: * Determine if an SCB for a packetized transaction
! 614: * is active in a FIFO.
! 615: */
! 616: int
! 617: ahd_scb_active_in_fifo(struct ahd_softc *ahd, struct scb *scb)
! 618: {
! 619:
! 620: /*
! 621: * The FIFO is only active for our transaction if
! 622: * the SCBPTR matches the SCB's ID and the firmware
! 623: * has installed a handler for the FIFO or we have
! 624: * a pending SAVEPTRS or CFG4DATA interrupt.
! 625: */
! 626: if (ahd_get_scbptr(ahd) != SCB_GET_TAG(scb)
! 627: || ((ahd_inb(ahd, LONGJMP_ADDR+1) & INVALID_ADDR) != 0
! 628: && (ahd_inb(ahd, SEQINTSRC) & (CFG4DATA|SAVEPTRS)) == 0))
! 629: return (0);
! 630:
! 631: return (1);
! 632: }
! 633:
! 634: /*
! 635: * Run a data fifo to completion for a transaction we know
! 636: * has completed across the SCSI bus (good status has been
! 637: * received). We are already set to the correct FIFO mode
! 638: * on entry to this routine.
! 639: *
! 640: * This function attempts to operate exactly as the firmware
! 641: * would when running this FIFO. Care must be taken to update
! 642: * this routine any time the firmware's FIFO algorithm is
! 643: * changed.
! 644: */
! 645: void
! 646: ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
! 647: {
! 648: u_int seqintsrc;
! 649:
! 650: seqintsrc = ahd_inb(ahd, SEQINTSRC);
! 651: if ((seqintsrc & CFG4DATA) != 0) {
! 652: uint32_t datacnt;
! 653: uint32_t sgptr;
! 654:
! 655: /*
! 656: * Clear full residual flag.
! 657: */
! 658: sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;
! 659: ahd_outb(ahd, SCB_SGPTR, sgptr);
! 660:
! 661: /*
! 662: * Load datacnt and address.
! 663: */
! 664: datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);
! 665: if ((datacnt & AHD_DMA_LAST_SEG) != 0) {
! 666: sgptr |= LAST_SEG;
! 667: ahd_outb(ahd, SG_STATE, 0);
! 668: } else
! 669: ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
! 670: ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));
! 671: ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);
! 672: ahd_outb(ahd, SG_CACHE_PRE, sgptr);
! 673: ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
! 674:
! 675: /*
! 676: * Initialize Residual Fields.
! 677: */
! 678: ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);
! 679: ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);
! 680:
! 681: /*
! 682: * Mark the SCB as having a FIFO in use.
! 683: */
! 684: ahd_outb(ahd, SCB_FIFO_USE_COUNT,
! 685: ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);
! 686:
! 687: /*
! 688: * Install a "fake" handler for this FIFO.
! 689: */
! 690: ahd_outw(ahd, LONGJMP_ADDR, 0);
! 691:
! 692: /*
! 693: * Notify the hardware that we have satisfied
! 694: * this sequencer interrupt.
! 695: */
! 696: ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);
! 697: } else if ((seqintsrc & SAVEPTRS) != 0) {
! 698: uint32_t sgptr;
! 699: uint32_t resid;
! 700:
! 701: if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {
! 702: /*
! 703: * Snapshot Save Pointers. All that
! 704: * is necessary to clear the snapshot
! 705: * is a CLRCHN.
! 706: */
! 707: goto clrchn;
! 708: }
! 709:
! 710: /*
! 711: * Disable S/G fetch so the DMA engine
! 712: * is available to future users.
! 713: */
! 714: if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
! 715: ahd_outb(ahd, CCSGCTL, 0);
! 716: ahd_outb(ahd, SG_STATE, 0);
! 717:
! 718: /*
! 719: * Flush the data FIFO. Strickly only
! 720: * necessary for Rev A parts.
! 721: */
! 722: ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);
! 723:
! 724: /*
! 725: * Calculate residual.
! 726: */
! 727: sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
! 728: resid = ahd_inl(ahd, SHCNT);
! 729: resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;
! 730: ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);
! 731: if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {
! 732: /*
! 733: * Must back up to the correct S/G element.
! 734: * Typically this just means resetting our
! 735: * low byte to the offset in the SG_CACHE,
! 736: * but if we wrapped, we have to correct
! 737: * the other bytes of the sgptr too.
! 738: */
! 739: if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0
! 740: && (sgptr & 0x80) == 0)
! 741: sgptr -= 0x100;
! 742: sgptr &= ~0xFF;
! 743: sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)
! 744: & SG_ADDR_MASK;
! 745: ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
! 746: ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);
! 747: } else if ((resid & AHD_SG_LEN_MASK) == 0) {
! 748: ahd_outb(ahd, SCB_RESIDUAL_SGPTR,
! 749: sgptr | SG_LIST_NULL);
! 750: }
! 751: /*
! 752: * Save Pointers.
! 753: */
! 754: ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));
! 755: ahd_outl(ahd, SCB_DATACNT, resid);
! 756: ahd_outl(ahd, SCB_SGPTR, sgptr);
! 757: ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);
! 758: ahd_outb(ahd, SEQIMODE,
! 759: ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);
! 760: /*
! 761: * If the data is to the SCSI bus, we are
! 762: * done, otherwise wait for FIFOEMP.
! 763: */
! 764: if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)
! 765: goto clrchn;
! 766: } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {
! 767: uint32_t sgptr;
! 768: uint64_t data_addr;
! 769: uint32_t data_len;
! 770: u_int dfcntrl;
! 771:
! 772: /*
! 773: * Disable S/G fetch so the DMA engine
! 774: * is available to future users. We won't
! 775: * be using the DMA engine to load segments.
! 776: */
! 777: if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) {
! 778: ahd_outb(ahd, CCSGCTL, 0);
! 779: ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
! 780: }
! 781:
! 782: /*
! 783: * Wait for the DMA engine to notice that the
! 784: * host transfer is enabled and that there is
! 785: * space in the S/G FIFO for new segments before
! 786: * loading more segments.
! 787: */
! 788: if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) != 0
! 789: && (ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) {
! 790:
! 791: /*
! 792: * Determine the offset of the next S/G
! 793: * element to load.
! 794: */
! 795: sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
! 796: sgptr &= SG_PTR_MASK;
! 797: if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
! 798: struct ahd_dma64_seg *sg;
! 799:
! 800: sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
! 801: data_addr = sg->addr;
! 802: data_len = sg->len;
! 803: sgptr += sizeof(*sg);
! 804: } else {
! 805: struct ahd_dma_seg *sg;
! 806:
! 807: sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
! 808: data_addr = sg->len & AHD_SG_HIGH_ADDR_MASK;
! 809: data_addr <<= 8;
! 810: data_addr |= sg->addr;
! 811: data_len = sg->len;
! 812: sgptr += sizeof(*sg);
! 813: }
! 814:
! 815: /*
! 816: * Update residual information.
! 817: */
! 818: ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, data_len >> 24);
! 819: ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
! 820:
! 821: /*
! 822: * Load the S/G.
! 823: */
! 824: if (data_len & AHD_DMA_LAST_SEG) {
! 825: sgptr |= LAST_SEG;
! 826: ahd_outb(ahd, SG_STATE, 0);
! 827: }
! 828: ahd_outq(ahd, HADDR, data_addr);
! 829: ahd_outl(ahd, HCNT, data_len & AHD_SG_LEN_MASK);
! 830: ahd_outb(ahd, SG_CACHE_PRE, sgptr & 0xFF);
! 831:
! 832: /*
! 833: * Advertise the segment to the hardware.
! 834: */
! 835: dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN;
! 836: if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) {
! 837: /*
! 838: * Use SCSIENWRDIS so that SCSIEN
! 839: * is never modified by this
! 840: * operation.
! 841: */
! 842: dfcntrl |= SCSIENWRDIS;
! 843: }
! 844: ahd_outb(ahd, DFCNTRL, dfcntrl);
! 845: }
! 846: } else if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG_DONE) != 0) {
! 847:
! 848: /*
! 849: * Transfer completed to the end of SG list
! 850: * and has flushed to the host.
! 851: */
! 852: ahd_outb(ahd, SCB_SGPTR,
! 853: ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);
! 854: goto clrchn;
! 855: } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {
! 856: clrchn:
! 857: /*
! 858: * Clear any handler for this FIFO, decrement
! 859: * the FIFO use count for the SCB, and release
! 860: * the FIFO.
! 861: */
! 862: ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
! 863: ahd_outb(ahd, SCB_FIFO_USE_COUNT,
! 864: ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);
! 865: ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
! 866: }
! 867: }
! 868:
! 869: /*
! 870: * Look for entries in the QoutFIFO that have completed.
! 871: * The valid_tag completion field indicates the validity
! 872: * of the entry - the valid value toggles each time through
! 873: * the queue. We use the sg_status field in the completion
! 874: * entry to avoid referencing the hscb if the completion
! 875: * occurred with no errors and no residual. sg_status is
! 876: * a copy of the first byte (little endian) of the sgptr
! 877: * hscb field.
! 878: */
! 879: void
! 880: ahd_run_qoutfifo(struct ahd_softc *ahd)
! 881: {
! 882: struct ahd_completion *completion;
! 883: struct scb *scb;
! 884: u_int scb_index;
! 885:
! 886: if ((ahd->flags & AHD_RUNNING_QOUTFIFO) != 0)
! 887: panic("ahd_run_qoutfifo recursion");
! 888: ahd->flags |= AHD_RUNNING_QOUTFIFO;
! 889: ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD);
! 890: for (;;) {
! 891: completion = &ahd->qoutfifo[ahd->qoutfifonext];
! 892:
! 893: if (completion->valid_tag != ahd->qoutfifonext_valid_tag)
! 894: break;
! 895:
! 896: scb_index = aic_le16toh(completion->tag);
! 897: scb = ahd_lookup_scb(ahd, scb_index);
! 898: if (scb == NULL) {
! 899: printf("%s: WARNING no command for scb %d "
! 900: "(cmdcmplt)\nQOUTPOS = %d\n",
! 901: ahd_name(ahd), scb_index,
! 902: ahd->qoutfifonext);
! 903: ahd_dump_card_state(ahd);
! 904: } else if ((completion->sg_status & SG_STATUS_VALID) != 0) {
! 905: ahd_handle_scb_status(ahd, scb);
! 906: } else {
! 907: ahd_done(ahd, scb);
! 908: }
! 909:
! 910: ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1);
! 911: if (ahd->qoutfifonext == 0)
! 912: ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID;
! 913: }
! 914: ahd->flags &= ~AHD_RUNNING_QOUTFIFO;
! 915: }
! 916:
! 917: /************************* Interrupt Handling *********************************/
! 918: void
! 919: ahd_handle_hwerrint(struct ahd_softc *ahd)
! 920: {
! 921: /*
! 922: * Some catastrophic hardware error has occurred.
! 923: * Print it for the user and disable the controller.
! 924: */
! 925: int i;
! 926: int error;
! 927:
! 928: error = ahd_inb(ahd, ERROR);
! 929: for (i = 0; i < num_errors; i++) {
! 930: if ((error & ahd_hard_errors[i].errno) != 0)
! 931: printf("%s: hwerrint, %s\n",
! 932: ahd_name(ahd), ahd_hard_errors[i].errmesg);
! 933: }
! 934:
! 935: ahd_dump_card_state(ahd);
! 936: panic("BRKADRINT");
! 937:
! 938: /* Tell everyone that this HBA is no longer available */
! 939: ahd_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,
! 940: CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_UNKNOWN,
! 941: CAM_NO_HBA);
! 942:
! 943: /* Tell the system that this controller has gone away. */
! 944: ahd_free(ahd);
! 945: }
! 946:
! 947: void
! 948: ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
! 949: {
! 950: u_int seqintcode;
! 951:
! 952: /*
! 953: * Save the sequencer interrupt code and clear the SEQINT
! 954: * bit. We will unpause the sequencer, if appropriate,
! 955: * after servicing the request.
! 956: */
! 957: seqintcode = ahd_inb(ahd, SEQINTCODE);
! 958: ahd_outb(ahd, CLRINT, CLRSEQINT);
! 959: if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {
! 960: /*
! 961: * Unpause the sequencer and let it clear
! 962: * SEQINT by writing NO_SEQINT to it. This
! 963: * will cause the sequencer to be paused again,
! 964: * which is the expected state of this routine.
! 965: */
! 966: ahd_unpause(ahd);
! 967: while (!ahd_is_paused(ahd))
! 968: ;
! 969: ahd_outb(ahd, CLRINT, CLRSEQINT);
! 970: }
! 971: ahd_update_modes(ahd);
! 972: #ifdef AHD_DEBUG
! 973: if ((ahd_debug & AHD_SHOW_MISC) != 0)
! 974: printf("%s: Handle Seqint Called for code %d\n",
! 975: ahd_name(ahd), seqintcode);
! 976: #endif
! 977: switch (seqintcode) {
! 978: case ENTERING_NONPACK:
! 979: {
! 980: struct scb *scb;
! 981: u_int scbid;
! 982:
! 983: AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
! 984: ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
! 985: scbid = ahd_get_scbptr(ahd);
! 986: scb = ahd_lookup_scb(ahd, scbid);
! 987: if (scb == NULL) {
! 988: /*
! 989: * Somehow need to know if this
! 990: * is from a selection or reselection.
! 991: * From that, we can determine target
! 992: * ID so we at least have an I_T nexus.
! 993: */
! 994: } else {
! 995: ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid);
! 996: ahd_outb(ahd, SAVED_LUN, scb->hscb->lun);
! 997: ahd_outb(ahd, SEQ_FLAGS, 0x0);
! 998: }
! 999: if ((ahd_inb(ahd, LQISTAT2) & LQIPHASE_OUTPKT) != 0
! 1000: && (ahd_inb(ahd, SCSISIGO) & ATNO) != 0) {
! 1001: /*
! 1002: * Phase change after read stream with
! 1003: * CRC error with P0 asserted on last
! 1004: * packet.
! 1005: */
! 1006: #ifdef AHD_DEBUG
! 1007: if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
! 1008: printf("%s: Assuming LQIPHASE_NLQ with "
! 1009: "P0 assertion\n", ahd_name(ahd));
! 1010: #endif
! 1011: }
! 1012: #ifdef AHD_DEBUG
! 1013: if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
! 1014: printf("%s: Entering NONPACK\n", ahd_name(ahd));
! 1015: #endif
! 1016: break;
! 1017: }
! 1018: case INVALID_SEQINT:
! 1019: printf("%s: Invalid Sequencer interrupt occurred.\n",
! 1020: ahd_name(ahd));
! 1021: ahd_dump_card_state(ahd);
! 1022: ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
! 1023: break;
! 1024: case STATUS_OVERRUN:
! 1025: {
! 1026: struct scb *scb;
! 1027: u_int scbid;
! 1028:
! 1029: scbid = ahd_get_scbptr(ahd);
! 1030: scb = ahd_lookup_scb(ahd, scbid);
! 1031: if (scb != NULL)
! 1032: ahd_print_path(ahd, scb);
! 1033: else
! 1034: printf("%s: ", ahd_name(ahd));
! 1035: printf("SCB %d Packetized Status Overrun", scbid);
! 1036: ahd_dump_card_state(ahd);
! 1037: ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
! 1038: break;
! 1039: }
! 1040: case CFG4ISTAT_INTR:
! 1041: {
! 1042: struct scb *scb;
! 1043: u_int scbid;
! 1044:
! 1045: scbid = ahd_get_scbptr(ahd);
! 1046: scb = ahd_lookup_scb(ahd, scbid);
! 1047: if (scb == NULL) {
! 1048: ahd_dump_card_state(ahd);
! 1049: printf("CFG4ISTAT: Free SCB %d referenced", scbid);
! 1050: panic("For safety");
! 1051: }
! 1052: ahd_outq(ahd, HADDR, scb->sense_busaddr);
! 1053: ahd_outw(ahd, HCNT, AHD_SENSE_BUFSIZE);
! 1054: ahd_outb(ahd, HCNT + 2, 0);
! 1055: ahd_outb(ahd, SG_CACHE_PRE, SG_LAST_SEG);
! 1056: ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
! 1057: break;
! 1058: }
! 1059: case ILLEGAL_PHASE:
! 1060: {
! 1061: u_int bus_phase;
! 1062:
! 1063: bus_phase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;
! 1064: printf("%s: ILLEGAL_PHASE 0x%x\n",
! 1065: ahd_name(ahd), bus_phase);
! 1066:
! 1067: switch (bus_phase) {
! 1068: case P_DATAOUT:
! 1069: case P_DATAIN:
! 1070: case P_DATAOUT_DT:
! 1071: case P_DATAIN_DT:
! 1072: case P_MESGOUT:
! 1073: case P_STATUS:
! 1074: case P_MESGIN:
! 1075: ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
! 1076: printf("%s: Issued Bus Reset.\n", ahd_name(ahd));
! 1077: break;
! 1078: case P_COMMAND:
! 1079: {
! 1080: struct ahd_devinfo devinfo;
! 1081: struct scb *scb;
! 1082: struct ahd_initiator_tinfo *targ_info;
! 1083: struct ahd_tmode_tstate *tstate;
! 1084: struct ahd_transinfo *tinfo;
! 1085: u_int scbid;
! 1086:
! 1087: /*
! 1088: * If a target takes us into the command phase
! 1089: * assume that it has been externally reset and
! 1090: * has thus lost our previous packetized negotiation
! 1091: * agreement. Since we have not sent an identify
! 1092: * message and may not have fully qualified the
! 1093: * connection, we change our command to TUR, assert
! 1094: * ATN and ABORT the task when we go to message in
! 1095: * phase. The OSM will see the REQUEUE_REQUEST
! 1096: * status and retry the command.
! 1097: */
! 1098: scbid = ahd_get_scbptr(ahd);
! 1099: scb = ahd_lookup_scb(ahd, scbid);
! 1100: if (scb == NULL) {
! 1101: printf("Invalid phase with no valid SCB. "
! 1102: "Resetting bus.\n");
! 1103: ahd_reset_channel(ahd, 'A',
! 1104: /*Initiate Reset*/TRUE);
! 1105: break;
! 1106: }
! 1107: ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb),
! 1108: SCB_GET_TARGET(ahd, scb),
! 1109: SCB_GET_LUN(scb),
! 1110: SCB_GET_CHANNEL(ahd, scb),
! 1111: ROLE_INITIATOR);
! 1112: targ_info = ahd_fetch_transinfo(ahd,
! 1113: devinfo.channel,
! 1114: devinfo.our_scsiid,
! 1115: devinfo.target,
! 1116: &tstate);
! 1117: tinfo = &targ_info->curr;
! 1118: ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
! 1119: AHD_TRANS_ACTIVE, /*paused*/TRUE);
! 1120: ahd_set_syncrate(ahd, &devinfo, /*period*/0,
! 1121: /*offset*/0, /*ppr_options*/0,
! 1122: AHD_TRANS_ACTIVE, /*paused*/TRUE);
! 1123: ahd_outb(ahd, SCB_CDB_STORE, 0);
! 1124: ahd_outb(ahd, SCB_CDB_STORE+1, 0);
! 1125: ahd_outb(ahd, SCB_CDB_STORE+2, 0);
! 1126: ahd_outb(ahd, SCB_CDB_STORE+3, 0);
! 1127: ahd_outb(ahd, SCB_CDB_STORE+4, 0);
! 1128: ahd_outb(ahd, SCB_CDB_STORE+5, 0);
! 1129: ahd_outb(ahd, SCB_CDB_LEN, 6);
! 1130: scb->hscb->control &= ~(TAG_ENB|SCB_TAG_TYPE);
! 1131: scb->hscb->control |= MK_MESSAGE;
! 1132: ahd_outb(ahd, SCB_CONTROL, scb->hscb->control);
! 1133: ahd_outb(ahd, MSG_OUT, HOST_MSG);
! 1134: ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid);
! 1135: /*
! 1136: * The lun is 0, regardless of the SCB's lun
! 1137: * as we have not sent an identify message.
! 1138: */
! 1139: ahd_outb(ahd, SAVED_LUN, 0);
! 1140: ahd_outb(ahd, SEQ_FLAGS, 0);
! 1141: ahd_assert_atn(ahd);
! 1142: scb->flags &= ~SCB_PACKETIZED;
! 1143: scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT;
! 1144: ahd_freeze_devq(ahd, scb);
! 1145: aic_set_transaction_status(scb, CAM_REQUEUE_REQ);
! 1146: aic_freeze_scb(scb);
! 1147:
! 1148: /*
! 1149: * Allow the sequencer to continue with
! 1150: * non-pack processing.
! 1151: */
! 1152: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 1153: ahd_outb(ahd, CLRLQOINT1, CLRLQOPHACHGINPKT);
! 1154: if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {
! 1155: ahd_outb(ahd, CLRLQOINT1, 0);
! 1156: }
! 1157: #ifdef AHD_DEBUG
! 1158: if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
! 1159: ahd_print_path(ahd, scb);
! 1160: printf("Unexpected command phase from "
! 1161: "packetized target\n");
! 1162: }
! 1163: #endif
! 1164: break;
! 1165: }
! 1166: }
! 1167: break;
! 1168: }
! 1169: case CFG4OVERRUN:
! 1170: {
! 1171: struct scb *scb;
! 1172: u_int scb_index;
! 1173:
! 1174: #ifdef AHD_DEBUG
! 1175: if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
! 1176: printf("%s: CFG4OVERRUN mode = %x\n", ahd_name(ahd),
! 1177: ahd_inb(ahd, MODE_PTR));
! 1178: }
! 1179: #endif
! 1180: scb_index = ahd_get_scbptr(ahd);
! 1181: scb = ahd_lookup_scb(ahd, scb_index);
! 1182: if (scb == NULL) {
! 1183: /*
! 1184: * Attempt to transfer to an SCB that is
! 1185: * not outstanding.
! 1186: */
! 1187: ahd_assert_atn(ahd);
! 1188: ahd_outb(ahd, MSG_OUT, HOST_MSG);
! 1189: ahd->msgout_buf[0] = MSG_ABORT_TASK;
! 1190: ahd->msgout_len = 1;
! 1191: ahd->msgout_index = 0;
! 1192: ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
! 1193: /*
! 1194: * Clear status received flag to prevent any
! 1195: * attempt to complete this bogus SCB.
! 1196: */
! 1197: ahd_outb(ahd, SCB_CONTROL,
! 1198: ahd_inb_scbram(ahd, SCB_CONTROL)
! 1199: & ~STATUS_RCVD);
! 1200: }
! 1201: break;
! 1202: }
! 1203: case DUMP_CARD_STATE:
! 1204: {
! 1205: ahd_dump_card_state(ahd);
! 1206: break;
! 1207: }
! 1208: case PDATA_REINIT:
! 1209: {
! 1210: #ifdef AHD_DEBUG
! 1211: if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
! 1212: printf("%s: PDATA_REINIT - DFCNTRL = 0x%x "
! 1213: "SG_CACHE_SHADOW = 0x%x\n",
! 1214: ahd_name(ahd), ahd_inb(ahd, DFCNTRL),
! 1215: ahd_inb(ahd, SG_CACHE_SHADOW));
! 1216: }
! 1217: #endif
! 1218: ahd_reinitialize_dataptrs(ahd);
! 1219: break;
! 1220: }
! 1221: case HOST_MSG_LOOP:
! 1222: {
! 1223: struct ahd_devinfo devinfo;
! 1224:
! 1225: /*
! 1226: * The sequencer has encountered a message phase
! 1227: * that requires host assistance for completion.
! 1228: * While handling the message phase(s), we will be
! 1229: * notified by the sequencer after each byte is
! 1230: * transfered so we can track bus phase changes.
! 1231: *
! 1232: * If this is the first time we've seen a HOST_MSG_LOOP
! 1233: * interrupt, initialize the state of the host message
! 1234: * loop.
! 1235: */
! 1236: ahd_fetch_devinfo(ahd, &devinfo);
! 1237: if (ahd->msg_type == MSG_TYPE_NONE) {
! 1238: struct scb *scb;
! 1239: u_int scb_index;
! 1240: u_int bus_phase;
! 1241:
! 1242: bus_phase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;
! 1243: if (bus_phase != P_MESGIN
! 1244: && bus_phase != P_MESGOUT) {
! 1245: printf("ahd_intr: HOST_MSG_LOOP bad "
! 1246: "phase 0x%x\n", bus_phase);
! 1247: /*
! 1248: * Probably transitioned to bus free before
! 1249: * we got here. Just punt the message.
! 1250: */
! 1251: ahd_dump_card_state(ahd);
! 1252: ahd_clear_intstat(ahd);
! 1253: ahd_restart(ahd);
! 1254: return;
! 1255: }
! 1256:
! 1257: scb_index = ahd_get_scbptr(ahd);
! 1258: scb = ahd_lookup_scb(ahd, scb_index);
! 1259: if (devinfo.role == ROLE_INITIATOR) {
! 1260: if (bus_phase == P_MESGOUT)
! 1261: ahd_setup_initiator_msgout(ahd,
! 1262: &devinfo,
! 1263: scb);
! 1264: else {
! 1265: ahd->msg_type =
! 1266: MSG_TYPE_INITIATOR_MSGIN;
! 1267: ahd->msgin_index = 0;
! 1268: }
! 1269: }
! 1270: #if AHD_TARGET_MODE
! 1271: else {
! 1272: if (bus_phase == P_MESGOUT) {
! 1273: ahd->msg_type =
! 1274: MSG_TYPE_TARGET_MSGOUT;
! 1275: ahd->msgin_index = 0;
! 1276: }
! 1277: else
! 1278: ahd_setup_target_msgin(ahd,
! 1279: &devinfo,
! 1280: scb);
! 1281: }
! 1282: #endif
! 1283: }
! 1284:
! 1285: ahd_handle_message_phase(ahd);
! 1286: break;
! 1287: }
! 1288: case NO_MATCH:
! 1289: {
! 1290: /* Ensure we don't leave the selection hardware on */
! 1291: AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
! 1292: ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
! 1293:
! 1294: printf("%s:%c:%d: no active SCB for reconnecting "
! 1295: "target - issuing BUS DEVICE RESET\n",
! 1296: ahd_name(ahd), 'A', ahd_inb(ahd, SELID) >> 4);
! 1297: printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, "
! 1298: "REG0 == 0x%x ACCUM = 0x%x\n",
! 1299: ahd_inb(ahd, SAVED_SCSIID), ahd_inb(ahd, SAVED_LUN),
! 1300: ahd_inw(ahd, REG0), ahd_inb(ahd, ACCUM));
! 1301: printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, "
! 1302: "SINDEX == 0x%x\n",
! 1303: ahd_inb(ahd, SEQ_FLAGS), ahd_get_scbptr(ahd),
! 1304: ahd_find_busy_tcl(ahd,
! 1305: BUILD_TCL(ahd_inb(ahd, SAVED_SCSIID),
! 1306: ahd_inb(ahd, SAVED_LUN))),
! 1307: ahd_inw(ahd, SINDEX));
! 1308: printf("SELID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, "
! 1309: "SCB_CONTROL == 0x%x\n",
! 1310: ahd_inb(ahd, SELID), ahd_inb_scbram(ahd, SCB_SCSIID),
! 1311: ahd_inb_scbram(ahd, SCB_LUN),
! 1312: ahd_inb_scbram(ahd, SCB_CONTROL));
! 1313: printf("SCSIBUS[0] == 0x%x, SCSISIGI == 0x%x\n",
! 1314: ahd_inb(ahd, SCSIBUS), ahd_inb(ahd, SCSISIGI));
! 1315: printf("SXFRCTL0 == 0x%x\n", ahd_inb(ahd, SXFRCTL0));
! 1316: printf("SEQCTL0 == 0x%x\n", ahd_inb(ahd, SEQCTL0));
! 1317: ahd_dump_card_state(ahd);
! 1318: ahd->msgout_buf[0] = MSG_BUS_DEV_RESET;
! 1319: ahd->msgout_len = 1;
! 1320: ahd->msgout_index = 0;
! 1321: ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
! 1322: ahd_outb(ahd, MSG_OUT, HOST_MSG);
! 1323: ahd_assert_atn(ahd);
! 1324: break;
! 1325: }
! 1326: case PROTO_VIOLATION:
! 1327: {
! 1328: ahd_handle_proto_violation(ahd);
! 1329: break;
! 1330: }
! 1331: case IGN_WIDE_RES:
! 1332: {
! 1333: struct ahd_devinfo devinfo;
! 1334:
! 1335: ahd_fetch_devinfo(ahd, &devinfo);
! 1336: ahd_handle_ign_wide_residue(ahd, &devinfo);
! 1337: break;
! 1338: }
! 1339: case BAD_PHASE:
! 1340: {
! 1341: u_int lastphase;
! 1342:
! 1343: lastphase = ahd_inb(ahd, LASTPHASE);
! 1344: printf("%s:%c:%d: unknown scsi bus phase %x, "
! 1345: "lastphase = 0x%x. Attempting to continue\n",
! 1346: ahd_name(ahd), 'A',
! 1347: SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)),
! 1348: lastphase, ahd_inb(ahd, SCSISIGI));
! 1349: break;
! 1350: }
! 1351: case MISSED_BUSFREE:
! 1352: {
! 1353: u_int lastphase;
! 1354:
! 1355: lastphase = ahd_inb(ahd, LASTPHASE);
! 1356: printf("%s:%c:%d: Missed busfree. "
! 1357: "Lastphase = 0x%x, Curphase = 0x%x\n",
! 1358: ahd_name(ahd), 'A',
! 1359: SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)),
! 1360: lastphase, ahd_inb(ahd, SCSISIGI));
! 1361: ahd_restart(ahd);
! 1362: return;
! 1363: }
! 1364: case DATA_OVERRUN:
! 1365: {
! 1366: /*
! 1367: * When the sequencer detects an overrun, it
! 1368: * places the controller in "BITBUCKET" mode
! 1369: * and allows the target to complete its transfer.
! 1370: * Unfortunately, none of the counters get updated
! 1371: * when the controller is in this mode, so we have
! 1372: * no way of knowing how large the overrun was.
! 1373: */
! 1374: struct scb *scb;
! 1375: u_int scbindex;
! 1376: #ifdef AHD_DEBUG
! 1377: u_int lastphase;
! 1378: #endif
! 1379:
! 1380: scbindex = ahd_get_scbptr(ahd);
! 1381: scb = ahd_lookup_scb(ahd, scbindex);
! 1382: #ifdef AHD_DEBUG
! 1383: lastphase = ahd_inb(ahd, LASTPHASE);
! 1384: if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
! 1385: ahd_print_path(ahd, scb);
! 1386: printf("data overrun detected %s. Tag == 0x%x.\n",
! 1387: ahd_lookup_phase_entry(lastphase)->phasemsg,
! 1388: SCB_GET_TAG(scb));
! 1389: ahd_print_path(ahd, scb);
! 1390: printf("%s seen Data Phase. Length = %ld. "
! 1391: "NumSGs = %d.\n",
! 1392: ahd_inb(ahd, SEQ_FLAGS) & DPHASE
! 1393: ? "Have" : "Haven't",
! 1394: aic_get_transfer_length(scb), scb->sg_count);
! 1395: ahd_dump_sglist(scb);
! 1396: }
! 1397: #endif
! 1398:
! 1399: /*
! 1400: * Set this and it will take effect when the
! 1401: * target does a command complete.
! 1402: */
! 1403: ahd_freeze_devq(ahd, scb);
! 1404: aic_set_transaction_status(scb, CAM_DATA_RUN_ERR);
! 1405: aic_freeze_scb(scb);
! 1406: break;
! 1407: }
! 1408: case MKMSG_FAILED:
! 1409: {
! 1410: struct ahd_devinfo devinfo;
! 1411: struct scb *scb;
! 1412: u_int scbid;
! 1413:
! 1414: ahd_fetch_devinfo(ahd, &devinfo);
! 1415: printf("%s:%c:%d:%d: Attempt to issue message failed\n",
! 1416: ahd_name(ahd), devinfo.channel, devinfo.target,
! 1417: devinfo.lun);
! 1418: scbid = ahd_get_scbptr(ahd);
! 1419: scb = ahd_lookup_scb(ahd, scbid);
! 1420: if (scb != NULL)
! 1421: /*
! 1422: * Ensure that we didn't put a second instance of this
! 1423: * SCB into the QINFIFO.
! 1424: */
! 1425: ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),
! 1426: SCB_GET_CHANNEL(ahd, scb),
! 1427: SCB_GET_LUN(scb), SCB_GET_TAG(scb),
! 1428: ROLE_INITIATOR, /*status*/0,
! 1429: SEARCH_REMOVE);
! 1430: ahd_outb(ahd, SCB_CONTROL,
! 1431: ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE);
! 1432: break;
! 1433: }
! 1434: case TASKMGMT_FUNC_COMPLETE:
! 1435: {
! 1436: u_int scbid;
! 1437: struct scb *scb;
! 1438:
! 1439: scbid = ahd_get_scbptr(ahd);
! 1440: scb = ahd_lookup_scb(ahd, scbid);
! 1441: if (scb != NULL) {
! 1442: u_int lun;
! 1443: u_int tag;
! 1444: cam_status error;
! 1445:
! 1446: ahd_print_path(ahd, scb);
! 1447: printf("Task Management Func 0x%x Complete\n",
! 1448: scb->hscb->task_management);
! 1449: lun = CAM_LUN_WILDCARD;
! 1450: tag = SCB_LIST_NULL;
! 1451:
! 1452: switch (scb->hscb->task_management) {
! 1453: case SIU_TASKMGMT_ABORT_TASK:
! 1454: tag = SCB_GET_TAG(scb);
! 1455: case SIU_TASKMGMT_ABORT_TASK_SET:
! 1456: case SIU_TASKMGMT_CLEAR_TASK_SET:
! 1457: lun = scb->hscb->lun;
! 1458: error = CAM_REQ_ABORTED;
! 1459: ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),
! 1460: 'A', lun, tag, ROLE_INITIATOR,
! 1461: error);
! 1462: break;
! 1463: case SIU_TASKMGMT_LUN_RESET:
! 1464: lun = scb->hscb->lun;
! 1465: case SIU_TASKMGMT_TARGET_RESET:
! 1466: {
! 1467: struct ahd_devinfo devinfo;
! 1468:
! 1469: ahd_scb_devinfo(ahd, &devinfo, scb);
! 1470: error = CAM_BDR_SENT;
! 1471: ahd_handle_devreset(ahd, &devinfo, lun,
! 1472: CAM_BDR_SENT,
! 1473: lun != CAM_LUN_WILDCARD
! 1474: ? "Lun Reset"
! 1475: : "Target Reset",
! 1476: /*verbose_level*/0);
! 1477: break;
! 1478: }
! 1479: default:
! 1480: panic("Unexpected TaskMgmt Func");
! 1481: break;
! 1482: }
! 1483: }
! 1484: break;
! 1485: }
! 1486: case TASKMGMT_CMD_CMPLT_OKAY:
! 1487: {
! 1488: u_int scbid;
! 1489: struct scb *scb;
! 1490:
! 1491: /*
! 1492: * An ABORT TASK TMF failed to be delivered before
! 1493: * the targeted command completed normally.
! 1494: */
! 1495: scbid = ahd_get_scbptr(ahd);
! 1496: scb = ahd_lookup_scb(ahd, scbid);
! 1497: if (scb != NULL) {
! 1498: /*
! 1499: * Remove the second instance of this SCB from
! 1500: * the QINFIFO if it is still there.
! 1501: */
! 1502: ahd_print_path(ahd, scb);
! 1503: printf("SCB completes before TMF\n");
! 1504: /*
! 1505: * Handle losing the race. Wait until any
! 1506: * current selection completes. We will then
! 1507: * set the TMF back to zero in this SCB so that
! 1508: * the sequencer doesn't bother to issue another
! 1509: * sequencer interrupt for its completion.
! 1510: */
! 1511: while ((ahd_inb(ahd, SCSISEQ0) & ENSELO) != 0
! 1512: && (ahd_inb(ahd, SSTAT0) & SELDO) == 0
! 1513: && (ahd_inb(ahd, SSTAT1) & SELTO) == 0)
! 1514: ;
! 1515: ahd_outb(ahd, SCB_TASK_MANAGEMENT, 0);
! 1516: ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),
! 1517: SCB_GET_CHANNEL(ahd, scb),
! 1518: SCB_GET_LUN(scb), SCB_GET_TAG(scb),
! 1519: ROLE_INITIATOR, /*status*/0,
! 1520: SEARCH_REMOVE);
! 1521: }
! 1522: break;
! 1523: }
! 1524: case TRACEPOINT0:
! 1525: case TRACEPOINT1:
! 1526: case TRACEPOINT2:
! 1527: case TRACEPOINT3:
! 1528: printf("%s: Tracepoint %d\n", ahd_name(ahd),
! 1529: seqintcode - TRACEPOINT0);
! 1530: break;
! 1531: case NO_SEQINT:
! 1532: break;
! 1533: case SAW_HWERR:
! 1534: ahd_handle_hwerrint(ahd);
! 1535: break;
! 1536: default:
! 1537: printf("%s: Unexpected SEQINTCODE %d\n", ahd_name(ahd),
! 1538: seqintcode);
! 1539: break;
! 1540: }
! 1541: /*
! 1542: * The sequencer is paused immediately on
! 1543: * a SEQINT, so we should restart it when
! 1544: * we're done.
! 1545: */
! 1546: ahd_unpause(ahd);
! 1547: }
! 1548:
! 1549: void
! 1550: ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
! 1551: {
! 1552: struct scb *scb;
! 1553: u_int status0;
! 1554: u_int status3;
! 1555: u_int status;
! 1556: u_int lqistat1;
! 1557: u_int lqostat0;
! 1558: u_int scbid;
! 1559: u_int busfreetime;
! 1560:
! 1561: ahd_update_modes(ahd);
! 1562: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 1563:
! 1564: status3 = ahd_inb(ahd, SSTAT3) & (NTRAMPERR|OSRAMPERR);
! 1565: status0 = ahd_inb(ahd, SSTAT0) & (IOERR|OVERRUN|SELDI|SELDO);
! 1566: status = ahd_inb(ahd, SSTAT1) & (SELTO|SCSIRSTI|BUSFREE|SCSIPERR);
! 1567: lqistat1 = ahd_inb(ahd, LQISTAT1);
! 1568: lqostat0 = ahd_inb(ahd, LQOSTAT0);
! 1569: busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME;
! 1570: if ((status0 & (SELDI|SELDO)) != 0) {
! 1571: u_int simode0;
! 1572:
! 1573: ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
! 1574: simode0 = ahd_inb(ahd, SIMODE0);
! 1575: status0 &= simode0 & (IOERR|OVERRUN|SELDI|SELDO);
! 1576: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 1577: }
! 1578: scbid = ahd_get_scbptr(ahd);
! 1579: scb = ahd_lookup_scb(ahd, scbid);
! 1580: if (scb != NULL
! 1581: && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)
! 1582: scb = NULL;
! 1583:
! 1584: if ((status0 & IOERR) != 0) {
! 1585: u_int now_lvd;
! 1586:
! 1587: now_lvd = ahd_inb(ahd, SBLKCTL) & ENAB40;
! 1588: printf("%s: Transceiver State Has Changed to %s mode\n",
! 1589: ahd_name(ahd), now_lvd ? "LVD" : "SE");
! 1590: ahd_outb(ahd, CLRSINT0, CLRIOERR);
! 1591: /*
! 1592: * A change in I/O mode is equivalent to a bus reset.
! 1593: */
! 1594: ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
! 1595: ahd_pause(ahd);
! 1596: ahd_setup_iocell_workaround(ahd);
! 1597: ahd_unpause(ahd);
! 1598: } else if ((status0 & OVERRUN) != 0) {
! 1599:
! 1600: printf("%s: SCSI offset overrun detected. Resetting bus.\n",
! 1601: ahd_name(ahd));
! 1602: ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
! 1603: } else if ((status & SCSIRSTI) != 0) {
! 1604:
! 1605: printf("%s: Someone reset channel A\n", ahd_name(ahd));
! 1606: ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE);
! 1607: } else if ((status & SCSIPERR) != 0) {
! 1608:
! 1609: /* Make sure the sequencer is in a safe location. */
! 1610: ahd_clear_critical_section(ahd);
! 1611:
! 1612: ahd_handle_transmission_error(ahd);
! 1613: } else if (lqostat0 != 0) {
! 1614:
! 1615: printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0);
! 1616: ahd_outb(ahd, CLRLQOINT0, lqostat0);
! 1617: if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)
! 1618: ahd_outb(ahd, CLRLQOINT1, 0);
! 1619: } else if ((status & SELTO) != 0) {
! 1620: u_int scbid;
! 1621:
! 1622: /* Stop the selection */
! 1623: ahd_outb(ahd, SCSISEQ0, 0);
! 1624:
! 1625: /* Make sure the sequencer is in a safe location. */
! 1626: ahd_clear_critical_section(ahd);
! 1627:
! 1628: /* No more pending messages */
! 1629: ahd_clear_msg_state(ahd);
! 1630:
! 1631: /* Clear interrupt state */
! 1632: ahd_outb(ahd, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR);
! 1633:
! 1634: /*
! 1635: * Although the driver does not care about the
! 1636: * 'Selection in Progress' status bit, the busy
! 1637: * LED does. SELINGO is only cleared by a sucessfull
! 1638: * selection, so we must manually clear it to insure
! 1639: * the LED turns off just incase no future successful
! 1640: * selections occur (e.g. no devices on the bus).
! 1641: */
! 1642: ahd_outb(ahd, CLRSINT0, CLRSELINGO);
! 1643:
! 1644: scbid = ahd_inw(ahd, WAITING_TID_HEAD);
! 1645: scb = ahd_lookup_scb(ahd, scbid);
! 1646: if (scb == NULL) {
! 1647: printf("%s: ahd_intr - referenced scb not "
! 1648: "valid during SELTO scb(0x%x)\n",
! 1649: ahd_name(ahd), scbid);
! 1650: ahd_dump_card_state(ahd);
! 1651: } else {
! 1652: struct ahd_devinfo devinfo;
! 1653: #ifdef AHD_DEBUG
! 1654: if ((ahd_debug & AHD_SHOW_SELTO) != 0) {
! 1655: ahd_print_path(ahd, scb);
! 1656: printf("Saw Selection Timeout for SCB 0x%x\n",
! 1657: scbid);
! 1658: }
! 1659: #endif
! 1660: ahd_scb_devinfo(ahd, &devinfo, scb);
! 1661: aic_set_transaction_status(scb, CAM_SEL_TIMEOUT);
! 1662: ahd_freeze_devq(ahd, scb);
! 1663:
! 1664: /*
! 1665: * Cancel any pending transactions on the device
! 1666: * now that it seems to be missing. This will
! 1667: * also revert us to async/narrow transfers until
! 1668: * we can renegotiate with the device.
! 1669: */
! 1670: ahd_handle_devreset(ahd, &devinfo,
! 1671: CAM_LUN_WILDCARD,
! 1672: CAM_SEL_TIMEOUT,
! 1673: "Selection Timeout",
! 1674: /*verbose_level*/1);
! 1675: }
! 1676: ahd_outb(ahd, CLRINT, CLRSCSIINT);
! 1677: ahd_iocell_first_selection(ahd);
! 1678: ahd_unpause(ahd);
! 1679: } else if ((status0 & (SELDI|SELDO)) != 0) {
! 1680:
! 1681: ahd_iocell_first_selection(ahd);
! 1682: ahd_unpause(ahd);
! 1683: } else if (status3 != 0) {
! 1684: printf("%s: SCSI Cell parity error SSTAT3 == 0x%x\n",
! 1685: ahd_name(ahd), status3);
! 1686: ahd_outb(ahd, CLRSINT3, status3);
! 1687: } else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) {
! 1688:
! 1689: /* Make sure the sequencer is in a safe location. */
! 1690: ahd_clear_critical_section(ahd);
! 1691:
! 1692: ahd_handle_lqiphase_error(ahd, lqistat1);
! 1693: } else if ((lqistat1 & LQICRCI_NLQ) != 0) {
! 1694: /*
! 1695: * This status can be delayed during some
! 1696: * streaming operations. The SCSIPHASE
! 1697: * handler has already dealt with this case
! 1698: * so just clear the error.
! 1699: */
! 1700: ahd_outb(ahd, CLRLQIINT1, CLRLQICRCI_NLQ);
! 1701: } else if ((status & BUSFREE) != 0
! 1702: || (lqistat1 & LQOBUSFREE) != 0) {
! 1703: u_int lqostat1;
! 1704: int restart;
! 1705: int clear_fifo;
! 1706: int packetized;
! 1707: u_int mode;
! 1708:
! 1709: /*
! 1710: * Clear our selection hardware as soon as possible.
! 1711: * We may have an entry in the waiting Q for this target,
! 1712: * that is affected by this busfree and we don't want to
! 1713: * go about selecting the target while we handle the event.
! 1714: */
! 1715: ahd_outb(ahd, SCSISEQ0, 0);
! 1716:
! 1717: /* Make sure the sequencer is in a safe location. */
! 1718: ahd_clear_critical_section(ahd);
! 1719:
! 1720: /*
! 1721: * Determine what we were up to at the time of
! 1722: * the busfree.
! 1723: */
! 1724: mode = AHD_MODE_SCSI;
! 1725: busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME;
! 1726: lqostat1 = ahd_inb(ahd, LQOSTAT1);
! 1727: switch (busfreetime) {
! 1728: case BUSFREE_DFF0:
! 1729: case BUSFREE_DFF1:
! 1730: {
! 1731: u_int scbid;
! 1732: struct scb *scb;
! 1733:
! 1734: mode = busfreetime == BUSFREE_DFF0
! 1735: ? AHD_MODE_DFF0 : AHD_MODE_DFF1;
! 1736: ahd_set_modes(ahd, mode, mode);
! 1737: scbid = ahd_get_scbptr(ahd);
! 1738: scb = ahd_lookup_scb(ahd, scbid);
! 1739: if (scb == NULL) {
! 1740: printf("%s: Invalid SCB %d in DFF%d "
! 1741: "during unexpected busfree\n",
! 1742: ahd_name(ahd), scbid, mode);
! 1743: packetized = 0;
! 1744: } else
! 1745: packetized = (scb->flags & SCB_PACKETIZED) != 0;
! 1746: clear_fifo = 1;
! 1747: break;
! 1748: }
! 1749: case BUSFREE_LQO:
! 1750: clear_fifo = 0;
! 1751: packetized = 1;
! 1752: break;
! 1753: default:
! 1754: clear_fifo = 0;
! 1755: packetized = (lqostat1 & LQOBUSFREE) != 0;
! 1756: if (!packetized
! 1757: && ahd_inb(ahd, LASTPHASE) == P_BUSFREE
! 1758: && (ahd_inb(ahd, SSTAT0) & SELDI) == 0
! 1759: && ((ahd_inb(ahd, SSTAT0) & SELDO) == 0
! 1760: || (ahd_inb(ahd, SCSISEQ0) & ENSELO) == 0))
! 1761: /*
! 1762: * Assume packetized if we are not
! 1763: * on the bus in a non-packetized
! 1764: * capacity and any pending selection
! 1765: * was a packetized selection.
! 1766: */
! 1767: packetized = 1;
! 1768: break;
! 1769: }
! 1770:
! 1771: #ifdef AHD_DEBUG
! 1772: if ((ahd_debug & AHD_SHOW_MISC) != 0)
! 1773: printf("Saw Busfree. Busfreetime = 0x%x.\n",
! 1774: busfreetime);
! 1775: #endif
! 1776: /*
! 1777: * Busfrees that occur in non-packetized phases are
! 1778: * handled by the nonpkt_busfree handler.
! 1779: */
! 1780: if (packetized && ahd_inb(ahd, LASTPHASE) == P_BUSFREE) {
! 1781: restart = ahd_handle_pkt_busfree(ahd, busfreetime);
! 1782: } else {
! 1783: packetized = 0;
! 1784: restart = ahd_handle_nonpkt_busfree(ahd);
! 1785: }
! 1786: /*
! 1787: * Clear the busfree interrupt status. The setting of
! 1788: * the interrupt is a pulse, so in a perfect world, we
! 1789: * would not need to muck with the ENBUSFREE logic. This
! 1790: * would ensure that if the bus moves on to another
! 1791: * connection, busfree protection is still in force. If
! 1792: * BUSFREEREV is broken, however, we must manually clear
! 1793: * the ENBUSFREE if the busfree occurred during a non-pack
! 1794: * connection so that we don't get false positives during
! 1795: * future, packetized, connections.
! 1796: */
! 1797: ahd_outb(ahd, CLRSINT1, CLRBUSFREE);
! 1798: if (packetized == 0
! 1799: && (ahd->bugs & AHD_BUSFREEREV_BUG) != 0)
! 1800: ahd_outb(ahd, SIMODE1,
! 1801: ahd_inb(ahd, SIMODE1) & ~ENBUSFREE);
! 1802:
! 1803: if (clear_fifo)
! 1804: ahd_clear_fifo(ahd, mode);
! 1805:
! 1806: ahd_clear_msg_state(ahd);
! 1807: ahd_outb(ahd, CLRINT, CLRSCSIINT);
! 1808: if (restart) {
! 1809: ahd_restart(ahd);
! 1810: } else {
! 1811: ahd_unpause(ahd);
! 1812: }
! 1813: } else {
! 1814: printf("%s: Missing case in ahd_handle_scsiint. status = %x\n",
! 1815: ahd_name(ahd), status);
! 1816: ahd_dump_card_state(ahd);
! 1817: ahd_clear_intstat(ahd);
! 1818: ahd_unpause(ahd);
! 1819: }
! 1820: }
! 1821:
! 1822: void
! 1823: ahd_handle_transmission_error(struct ahd_softc *ahd)
! 1824: {
! 1825: struct scb *scb;
! 1826: u_int scbid;
! 1827: u_int lqistat1;
! 1828: u_int lqistat2;
! 1829: u_int msg_out;
! 1830: u_int curphase;
! 1831: u_int lastphase;
! 1832: u_int perrdiag;
! 1833: u_int cur_col;
! 1834: int silent;
! 1835:
! 1836: scb = NULL;
! 1837: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 1838: lqistat1 = ahd_inb(ahd, LQISTAT1) & ~(LQIPHASE_LQ|LQIPHASE_NLQ);
! 1839: lqistat2 = ahd_inb(ahd, LQISTAT2);
! 1840: if ((lqistat1 & (LQICRCI_NLQ|LQICRCI_LQ)) == 0
! 1841: && (ahd->bugs & AHD_NLQICRC_DELAYED_BUG) != 0) {
! 1842: u_int lqistate;
! 1843:
! 1844: ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
! 1845: lqistate = ahd_inb(ahd, LQISTATE);
! 1846: if ((lqistate >= 0x1E && lqistate <= 0x24)
! 1847: || (lqistate == 0x29)) {
! 1848: #ifdef AHD_DEBUG
! 1849: if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
! 1850: printf("%s: NLQCRC found via LQISTATE\n",
! 1851: ahd_name(ahd));
! 1852: }
! 1853: #endif
! 1854: lqistat1 |= LQICRCI_NLQ;
! 1855: }
! 1856: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 1857: }
! 1858:
! 1859: ahd_outb(ahd, CLRLQIINT1, lqistat1);
! 1860: lastphase = ahd_inb(ahd, LASTPHASE);
! 1861: curphase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;
! 1862: perrdiag = ahd_inb(ahd, PERRDIAG);
! 1863: msg_out = MSG_INITIATOR_DET_ERR;
! 1864: ahd_outb(ahd, CLRSINT1, CLRSCSIPERR);
! 1865:
! 1866: /*
! 1867: * Try to find the SCB associated with this error.
! 1868: */
! 1869: silent = FALSE;
! 1870: if (lqistat1 == 0
! 1871: || (lqistat1 & LQICRCI_NLQ) != 0) {
! 1872: if ((lqistat1 & (LQICRCI_NLQ|LQIOVERI_NLQ)) != 0)
! 1873: ahd_set_active_fifo(ahd);
! 1874: scbid = ahd_get_scbptr(ahd);
! 1875: scb = ahd_lookup_scb(ahd, scbid);
! 1876: if (scb != NULL && SCB_IS_SILENT(scb))
! 1877: silent = TRUE;
! 1878: }
! 1879:
! 1880: cur_col = 0;
! 1881: if (silent == FALSE) {
! 1882: printf("%s: Transmission error detected\n", ahd_name(ahd));
! 1883: ahd_lqistat1_print(lqistat1, &cur_col, 50);
! 1884: ahd_lastphase_print(lastphase, &cur_col, 50);
! 1885: ahd_scsisigi_print(curphase, &cur_col, 50);
! 1886: ahd_perrdiag_print(perrdiag, &cur_col, 50);
! 1887: printf("\n");
! 1888: ahd_dump_card_state(ahd);
! 1889: }
! 1890:
! 1891: if ((lqistat1 & (LQIOVERI_LQ|LQIOVERI_NLQ)) != 0) {
! 1892: if (silent == FALSE) {
! 1893: printf("%s: Gross protocol error during incoming "
! 1894: "packet. lqistat1 == 0x%x. Resetting bus.\n",
! 1895: ahd_name(ahd), lqistat1);
! 1896: }
! 1897: ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
! 1898: return;
! 1899: } else if ((lqistat1 & LQICRCI_LQ) != 0) {
! 1900: /*
! 1901: * A CRC error has been detected on an incoming LQ.
! 1902: * The bus is currently hung on the last ACK.
! 1903: * Hit LQIRETRY to release the last ack, and
! 1904: * wait for the sequencer to determine that ATNO
! 1905: * is asserted while in message out to take us
! 1906: * to our host message loop. No NONPACKREQ or
! 1907: * LQIPHASE type errors will occur in this
! 1908: * scenario. After this first LQIRETRY, the LQI
! 1909: * manager will be in ISELO where it will
! 1910: * happily sit until another packet phase begins.
! 1911: * Unexpected bus free detection is enabled
! 1912: * through any phases that occur after we release
! 1913: * this last ack until the LQI manager sees a
! 1914: * packet phase. This implies we may have to
! 1915: * ignore a perfectly valid "unexpected busfree"
! 1916: * after our "initiator detected error" message is
! 1917: * sent. A busfree is the expected response after
! 1918: * we tell the target that its L_Q was corrupted.
! 1919: * (SPI4R09 10.7.3.3.3)
! 1920: */
! 1921: ahd_outb(ahd, LQCTL2, LQIRETRY);
! 1922: printf("LQIRetry for LQICRCI_LQ to release ACK\n");
! 1923: } else if ((lqistat1 & LQICRCI_NLQ) != 0) {
! 1924: /*
! 1925: * We detected a CRC error in a NON-LQ packet.
! 1926: * The hardware has varying behavior in this situation
! 1927: * depending on whether this packet was part of a
! 1928: * stream or not.
! 1929: *
! 1930: * PKT by PKT mode:
! 1931: * The hardware has already acked the complete packet.
! 1932: * If the target honors our outstanding ATN condition,
! 1933: * we should be (or soon will be) in MSGOUT phase.
! 1934: * This will trigger the LQIPHASE_LQ status bit as the
! 1935: * hardware was expecting another LQ. Unexpected
! 1936: * busfree detection is enabled. Once LQIPHASE_LQ is
! 1937: * true (first entry into host message loop is much
! 1938: * the same), we must clear LQIPHASE_LQ and hit
! 1939: * LQIRETRY so the hardware is ready to handle
! 1940: * a future LQ. NONPACKREQ will not be asserted again
! 1941: * once we hit LQIRETRY until another packet is
! 1942: * processed. The target may either go busfree
! 1943: * or start another packet in response to our message.
! 1944: *
! 1945: * Read Streaming P0 asserted:
! 1946: * If we raise ATN and the target completes the entire
! 1947: * stream (P0 asserted during the last packet), the
! 1948: * hardware will ack all data and return to the ISTART
! 1949: * state. When the target reponds to our ATN condition,
! 1950: * LQIPHASE_LQ will be asserted. We should respond to
! 1951: * this with an LQIRETRY to prepare for any future
! 1952: * packets. NONPACKREQ will not be asserted again
! 1953: * once we hit LQIRETRY until another packet is
! 1954: * processed. The target may either go busfree or
! 1955: * start another packet in response to our message.
! 1956: * Busfree detection is enabled.
! 1957: *
! 1958: * Read Streaming P0 not asserted:
! 1959: * If we raise ATN and the target transitions to
! 1960: * MSGOUT in or after a packet where P0 is not
! 1961: * asserted, the hardware will assert LQIPHASE_NLQ.
! 1962: * We should respond to the LQIPHASE_NLQ with an
! 1963: * LQIRETRY. Should the target stay in a non-pkt
! 1964: * phase after we send our message, the hardware
! 1965: * will assert LQIPHASE_LQ. Recovery is then just as
! 1966: * listed above for the read streaming with P0 asserted.
! 1967: * Busfree detection is enabled.
! 1968: */
! 1969: if (silent == FALSE)
! 1970: printf("LQICRC_NLQ\n");
! 1971: if (scb == NULL) {
! 1972: printf("%s: No SCB valid for LQICRC_NLQ. "
! 1973: "Resetting bus\n", ahd_name(ahd));
! 1974: ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
! 1975: return;
! 1976: }
! 1977: } else if ((lqistat1 & LQIBADLQI) != 0) {
! 1978: printf("Need to handle BADLQI!\n");
! 1979: ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
! 1980: return;
! 1981: } else if ((perrdiag & (PARITYERR|PREVPHASE)) == PARITYERR) {
! 1982: if ((curphase & ~P_DATAIN_DT) != 0) {
! 1983: /* Ack the byte. So we can continue. */
! 1984: if (silent == FALSE)
! 1985: printf("Acking %s to clear perror\n",
! 1986: ahd_lookup_phase_entry(curphase)->phasemsg);
! 1987: ahd_inb(ahd, SCSIDAT);
! 1988: }
! 1989:
! 1990: if (curphase == P_MESGIN)
! 1991: msg_out = MSG_PARITY_ERROR;
! 1992: }
! 1993:
! 1994: /*
! 1995: * We've set the hardware to assert ATN if we
! 1996: * get a parity error on "in" phases, so all we
! 1997: * need to do is stuff the message buffer with
! 1998: * the appropriate message. "In" phases have set
! 1999: * mesg_out to something other than MSG_NOP.
! 2000: */
! 2001: ahd->send_msg_perror = msg_out;
! 2002: if (scb != NULL && msg_out == MSG_INITIATOR_DET_ERR)
! 2003: scb->flags |= SCB_TRANSMISSION_ERROR;
! 2004: ahd_outb(ahd, MSG_OUT, HOST_MSG);
! 2005: ahd_outb(ahd, CLRINT, CLRSCSIINT);
! 2006: ahd_unpause(ahd);
! 2007: }
! 2008:
! 2009: void
! 2010: ahd_handle_lqiphase_error(struct ahd_softc *ahd, u_int lqistat1)
! 2011: {
! 2012: /*
! 2013: * Clear the sources of the interrupts.
! 2014: */
! 2015: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 2016: ahd_outb(ahd, CLRLQIINT1, lqistat1);
! 2017:
! 2018: /*
! 2019: * If the "illegal" phase changes were in response
! 2020: * to our ATN to flag a CRC error, AND we ended up
! 2021: * on packet boundaries, clear the error, restart the
! 2022: * LQI manager as appropriate, and go on our merry
! 2023: * way toward sending the message. Otherwise, reset
! 2024: * the bus to clear the error.
! 2025: */
! 2026: ahd_set_active_fifo(ahd);
! 2027: if ((ahd_inb(ahd, SCSISIGO) & ATNO) != 0
! 2028: && (ahd_inb(ahd, MDFFSTAT) & DLZERO) != 0) {
! 2029: if ((lqistat1 & LQIPHASE_LQ) != 0) {
! 2030: printf("LQIRETRY for LQIPHASE_LQ\n");
! 2031: ahd_outb(ahd, LQCTL2, LQIRETRY);
! 2032: } else if ((lqistat1 & LQIPHASE_NLQ) != 0) {
! 2033: printf("LQIRETRY for LQIPHASE_NLQ\n");
! 2034: ahd_outb(ahd, LQCTL2, LQIRETRY);
! 2035: } else
! 2036: panic("ahd_handle_lqiphase_error: No phase errors");
! 2037: ahd_dump_card_state(ahd);
! 2038: ahd_outb(ahd, CLRINT, CLRSCSIINT);
! 2039: ahd_unpause(ahd);
! 2040: } else {
! 2041: printf("Reseting Channel for LQI Phase error\n");
! 2042: ahd_dump_card_state(ahd);
! 2043: ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
! 2044: }
! 2045: }
! 2046:
! 2047: /*
! 2048: * Packetized unexpected or expected busfree.
! 2049: * Entered in mode based on busfreetime.
! 2050: */
! 2051: int
! 2052: ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
! 2053: {
! 2054: u_int lqostat1;
! 2055:
! 2056: AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
! 2057: ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
! 2058: lqostat1 = ahd_inb(ahd, LQOSTAT1);
! 2059: if ((lqostat1 & LQOBUSFREE) != 0) {
! 2060: struct scb *scb;
! 2061: u_int scbid;
! 2062: u_int saved_scbptr;
! 2063: u_int waiting_h;
! 2064: u_int waiting_t;
! 2065: u_int next;
! 2066:
! 2067: /*
! 2068: * The LQO manager detected an unexpected busfree
! 2069: * either:
! 2070: *
! 2071: * 1) During an outgoing LQ.
! 2072: * 2) After an outgoing LQ but before the first
! 2073: * REQ of the command packet.
! 2074: * 3) During an outgoing command packet.
! 2075: *
! 2076: * In all cases, CURRSCB is pointing to the
! 2077: * SCB that encountered the failure. Clean
! 2078: * up the queue, clear SELDO and LQOBUSFREE,
! 2079: * and allow the sequencer to restart the select
! 2080: * out at its lesure.
! 2081: */
! 2082: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 2083: scbid = ahd_inw(ahd, CURRSCB);
! 2084: scb = ahd_lookup_scb(ahd, scbid);
! 2085: if (scb == NULL)
! 2086: panic("SCB not valid during LQOBUSFREE");
! 2087: /*
! 2088: * Clear the status.
! 2089: */
! 2090: ahd_outb(ahd, CLRLQOINT1, CLRLQOBUSFREE);
! 2091: if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)
! 2092: ahd_outb(ahd, CLRLQOINT1, 0);
! 2093: ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
! 2094: ahd_flush_device_writes(ahd);
! 2095: ahd_outb(ahd, CLRSINT0, CLRSELDO);
! 2096:
! 2097: /*
! 2098: * Return the LQO manager to its idle loop. It will
! 2099: * not do this automatically if the busfree occurs
! 2100: * after the first REQ of either the LQ or command
! 2101: * packet or between the LQ and command packet.
! 2102: */
! 2103: ahd_outb(ahd, LQCTL2, ahd_inb(ahd, LQCTL2) | LQOTOIDLE);
! 2104:
! 2105: /*
! 2106: * Update the waiting for selection queue so
! 2107: * we restart on the correct SCB.
! 2108: */
! 2109: waiting_h = ahd_inw(ahd, WAITING_TID_HEAD);
! 2110: saved_scbptr = ahd_get_scbptr(ahd);
! 2111: if (waiting_h != scbid) {
! 2112:
! 2113: ahd_outw(ahd, WAITING_TID_HEAD, scbid);
! 2114: waiting_t = ahd_inw(ahd, WAITING_TID_TAIL);
! 2115: if (waiting_t == waiting_h) {
! 2116: ahd_outw(ahd, WAITING_TID_TAIL, scbid);
! 2117: next = SCB_LIST_NULL;
! 2118: } else {
! 2119: ahd_set_scbptr(ahd, waiting_h);
! 2120: next = ahd_inw_scbram(ahd, SCB_NEXT2);
! 2121: }
! 2122: ahd_set_scbptr(ahd, scbid);
! 2123: ahd_outw(ahd, SCB_NEXT2, next);
! 2124: }
! 2125: ahd_set_scbptr(ahd, saved_scbptr);
! 2126: if (scb->crc_retry_count < AHD_MAX_LQ_CRC_ERRORS) {
! 2127: if (SCB_IS_SILENT(scb) == FALSE) {
! 2128: ahd_print_path(ahd, scb);
! 2129: printf("Probable outgoing LQ CRC error. "
! 2130: "Retrying command\n");
! 2131: }
! 2132: scb->crc_retry_count++;
! 2133: } else {
! 2134: aic_set_transaction_status(scb, CAM_UNCOR_PARITY);
! 2135: aic_freeze_scb(scb);
! 2136: ahd_freeze_devq(ahd, scb);
! 2137: }
! 2138: /* Return unpausing the sequencer. */
! 2139: return (0);
! 2140: } else if ((ahd_inb(ahd, PERRDIAG) & PARITYERR) != 0) {
! 2141: /*
! 2142: * Ignore what are really parity errors that
! 2143: * occur on the last REQ of a free running
! 2144: * clock prior to going busfree. Some drives
! 2145: * do not properly active negate just before
! 2146: * going busfree resulting in a parity glitch.
! 2147: */
! 2148: ahd_outb(ahd, CLRSINT1, CLRSCSIPERR|CLRBUSFREE);
! 2149: #ifdef AHD_DEBUG
! 2150: if ((ahd_debug & AHD_SHOW_MASKED_ERRORS) != 0)
! 2151: printf("%s: Parity on last REQ detected "
! 2152: "during busfree phase.\n",
! 2153: ahd_name(ahd));
! 2154: #endif
! 2155: /* Return unpausing the sequencer. */
! 2156: return (0);
! 2157: }
! 2158: if (ahd->src_mode != AHD_MODE_SCSI) {
! 2159: u_int scbid;
! 2160: struct scb *scb;
! 2161:
! 2162: scbid = ahd_get_scbptr(ahd);
! 2163: scb = ahd_lookup_scb(ahd, scbid);
! 2164: ahd_print_path(ahd, scb);
! 2165: printf("Unexpected PKT busfree condition\n");
! 2166: ahd_dump_card_state(ahd);
! 2167: ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb), 'A',
! 2168: SCB_GET_LUN(scb), SCB_GET_TAG(scb),
! 2169: ROLE_INITIATOR, CAM_UNEXP_BUSFREE);
! 2170:
! 2171: /* Return restarting the sequencer. */
! 2172: return (1);
! 2173: }
! 2174: printf("%s: Unexpected PKT busfree condition\n", ahd_name(ahd));
! 2175: ahd_dump_card_state(ahd);
! 2176: /* Restart the sequencer. */
! 2177: return (1);
! 2178: }
! 2179:
! 2180: /*
! 2181: * Non-packetized unexpected or expected busfree.
! 2182: */
! 2183: int
! 2184: ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
! 2185: {
! 2186: struct ahd_devinfo devinfo;
! 2187: struct scb *scb;
! 2188: u_int lastphase;
! 2189: u_int saved_scsiid;
! 2190: u_int saved_lun;
! 2191: u_int target;
! 2192: u_int initiator_role_id;
! 2193: u_int scbid;
! 2194: u_int ppr_busfree;
! 2195: int printerror;
! 2196:
! 2197: /*
! 2198: * Look at what phase we were last in. If its message out,
! 2199: * chances are pretty good that the busfree was in response
! 2200: * to one of our abort requests.
! 2201: */
! 2202: lastphase = ahd_inb(ahd, LASTPHASE);
! 2203: saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
! 2204: saved_lun = ahd_inb(ahd, SAVED_LUN);
! 2205: target = SCSIID_TARGET(ahd, saved_scsiid);
! 2206: initiator_role_id = SCSIID_OUR_ID(saved_scsiid);
! 2207: ahd_compile_devinfo(&devinfo, initiator_role_id,
! 2208: target, saved_lun, 'A', ROLE_INITIATOR);
! 2209: printerror = 1;
! 2210:
! 2211: scbid = ahd_get_scbptr(ahd);
! 2212: scb = ahd_lookup_scb(ahd, scbid);
! 2213: if (scb != NULL
! 2214: && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)
! 2215: scb = NULL;
! 2216:
! 2217: ppr_busfree = (ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0;
! 2218: if (lastphase == P_MESGOUT) {
! 2219: u_int tag;
! 2220:
! 2221: tag = SCB_LIST_NULL;
! 2222: if (ahd_sent_msg(ahd, AHDMSG_1B, MSG_ABORT_TAG, TRUE)
! 2223: || ahd_sent_msg(ahd, AHDMSG_1B, MSG_ABORT, TRUE)) {
! 2224: int found;
! 2225: int sent_msg;
! 2226:
! 2227: if (scb == NULL) {
! 2228: ahd_print_devinfo(ahd, &devinfo);
! 2229: printf("Abort for unidentified "
! 2230: "connection completed.\n");
! 2231: /* restart the sequencer. */
! 2232: return (1);
! 2233: }
! 2234: sent_msg = ahd->msgout_buf[ahd->msgout_index - 1];
! 2235: ahd_print_path(ahd, scb);
! 2236: printf("SCB %d - Abort%s Completed.\n",
! 2237: SCB_GET_TAG(scb),
! 2238: sent_msg == MSG_ABORT_TAG ? "" : " Tag");
! 2239:
! 2240: if (sent_msg == MSG_ABORT_TAG)
! 2241: tag = SCB_GET_TAG(scb);
! 2242:
! 2243: if ((scb->flags & SCB_CMDPHASE_ABORT) != 0) {
! 2244: /*
! 2245: * This abort is in response to an
! 2246: * unexpected switch to command phase
! 2247: * for a packetized connection. Since
! 2248: * the identify message was never sent,
! 2249: * "saved lun" is 0. We really want to
! 2250: * abort only the SCB that encountered
! 2251: * this error, which could have a different
! 2252: * lun. The SCB will be retried so the OS
! 2253: * will see the UA after renegotiating to
! 2254: * packetized.
! 2255: */
! 2256: tag = SCB_GET_TAG(scb);
! 2257: saved_lun = scb->hscb->lun;
! 2258: }
! 2259: found = ahd_abort_scbs(ahd, target, 'A', saved_lun,
! 2260: tag, ROLE_INITIATOR,
! 2261: CAM_REQ_ABORTED);
! 2262: printf("found == 0x%x\n", found);
! 2263: printerror = 0;
! 2264: } else if (ahd_sent_msg(ahd, AHDMSG_1B,
! 2265: MSG_BUS_DEV_RESET, TRUE)) {
! 2266: #ifdef __FreeBSD__
! 2267: /*
! 2268: * Don't mark the user's request for this BDR
! 2269: * as completing with CAM_BDR_SENT. CAM3
! 2270: * specifies CAM_REQ_CMP.
! 2271: */
! 2272: if (scb != NULL
! 2273: && scb->io_ctx->ccb_h.func_code== XPT_RESET_DEV
! 2274: && ahd_match_scb(ahd, scb, target, 'A',
! 2275: CAM_LUN_WILDCARD, SCB_LIST_NULL,
! 2276: ROLE_INITIATOR))
! 2277: aic_set_transaction_status(scb, CAM_REQ_CMP);
! 2278: #endif
! 2279: ahd_handle_devreset(ahd, &devinfo, CAM_LUN_WILDCARD,
! 2280: CAM_BDR_SENT, "Bus Device Reset",
! 2281: /*verbose_level*/0);
! 2282: printerror = 0;
! 2283: } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, FALSE)
! 2284: && ppr_busfree == 0) {
! 2285: struct ahd_initiator_tinfo *tinfo;
! 2286: struct ahd_tmode_tstate *tstate;
! 2287:
! 2288: /*
! 2289: * PPR Rejected.
! 2290: *
! 2291: * If the previous negotiation was packetized,
! 2292: * this could be because the device has been
! 2293: * reset without our knowledge. Force our
! 2294: * current negotiation to async and retry the
! 2295: * negotiation. Otherwise retry the command
! 2296: * with non-ppr negotiation.
! 2297: */
! 2298: #ifdef AHD_DEBUG
! 2299: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
! 2300: printf("PPR negotiation rejected busfree.\n");
! 2301: #endif
! 2302: tinfo = ahd_fetch_transinfo(ahd, devinfo.channel,
! 2303: devinfo.our_scsiid,
! 2304: devinfo.target, &tstate);
! 2305: if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)!=0) {
! 2306: ahd_set_width(ahd, &devinfo,
! 2307: MSG_EXT_WDTR_BUS_8_BIT,
! 2308: AHD_TRANS_CUR,
! 2309: /*paused*/TRUE);
! 2310: ahd_set_syncrate(ahd, &devinfo,
! 2311: /*period*/0, /*offset*/0,
! 2312: /*ppr_options*/0,
! 2313: AHD_TRANS_CUR,
! 2314: /*paused*/TRUE);
! 2315: /*
! 2316: * The expect PPR busfree handler below
! 2317: * will effect the retry and necessary
! 2318: * abort.
! 2319: */
! 2320: } else {
! 2321: tinfo->curr.transport_version = 2;
! 2322: tinfo->goal.transport_version = 2;
! 2323: tinfo->goal.ppr_options = 0;
! 2324: /*
! 2325: * Remove any SCBs in the waiting for selection
! 2326: * queue that may also be for this target so
! 2327: * that command ordering is preserved.
! 2328: */
! 2329: ahd_freeze_devq(ahd, scb);
! 2330: ahd_qinfifo_requeue_tail(ahd, scb);
! 2331: printerror = 0;
! 2332: }
! 2333: } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, FALSE)
! 2334: && ppr_busfree == 0) {
! 2335: /*
! 2336: * Negotiation Rejected. Go-narrow and
! 2337: * retry command.
! 2338: */
! 2339: #ifdef AHD_DEBUG
! 2340: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
! 2341: printf("WDTR negotiation rejected busfree.\n");
! 2342: #endif
! 2343: ahd_set_width(ahd, &devinfo,
! 2344: MSG_EXT_WDTR_BUS_8_BIT,
! 2345: AHD_TRANS_CUR|AHD_TRANS_GOAL,
! 2346: /*paused*/TRUE);
! 2347: /*
! 2348: * Remove any SCBs in the waiting for selection
! 2349: * queue that may also be for this target so that
! 2350: * command ordering is preserved.
! 2351: */
! 2352: ahd_freeze_devq(ahd, scb);
! 2353: ahd_qinfifo_requeue_tail(ahd, scb);
! 2354: printerror = 0;
! 2355: } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, FALSE)
! 2356: && ppr_busfree == 0) {
! 2357: /*
! 2358: * Negotiation Rejected. Go-async and
! 2359: * retry command.
! 2360: */
! 2361: #ifdef AHD_DEBUG
! 2362: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
! 2363: printf("SDTR negotiation rejected busfree.\n");
! 2364: #endif
! 2365: ahd_set_syncrate(ahd, &devinfo,
! 2366: /*period*/0, /*offset*/0,
! 2367: /*ppr_options*/0,
! 2368: AHD_TRANS_CUR|AHD_TRANS_GOAL,
! 2369: /*paused*/TRUE);
! 2370: /*
! 2371: * Remove any SCBs in the waiting for selection
! 2372: * queue that may also be for this target so that
! 2373: * command ordering is preserved.
! 2374: */
! 2375: ahd_freeze_devq(ahd, scb);
! 2376: ahd_qinfifo_requeue_tail(ahd, scb);
! 2377: printerror = 0;
! 2378: } else if ((ahd->msg_flags & MSG_FLAG_EXPECT_IDE_BUSFREE) != 0
! 2379: && ahd_sent_msg(ahd, AHDMSG_1B,
! 2380: MSG_INITIATOR_DET_ERR, TRUE)) {
! 2381:
! 2382: #ifdef AHD_DEBUG
! 2383: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
! 2384: printf("Expected IDE Busfree\n");
! 2385: #endif
! 2386: printerror = 0;
! 2387: } else if ((ahd->msg_flags & MSG_FLAG_EXPECT_QASREJ_BUSFREE)
! 2388: && ahd_sent_msg(ahd, AHDMSG_1B,
! 2389: MSG_MESSAGE_REJECT, TRUE)) {
! 2390:
! 2391: #ifdef AHD_DEBUG
! 2392: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
! 2393: printf("Expected QAS Reject Busfree\n");
! 2394: #endif
! 2395: printerror = 0;
! 2396: }
! 2397: }
! 2398:
! 2399: /*
! 2400: * The busfree required flag is honored at the end of
! 2401: * the message phases. We check it last in case we
! 2402: * had to send some other message that caused a busfree.
! 2403: */
! 2404: if (printerror != 0
! 2405: && (lastphase == P_MESGIN || lastphase == P_MESGOUT)
! 2406: && ((ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0)) {
! 2407:
! 2408: ahd_freeze_devq(ahd, scb);
! 2409: aic_set_transaction_status(scb, CAM_REQUEUE_REQ);
! 2410: aic_freeze_scb(scb);
! 2411: if ((ahd->msg_flags & MSG_FLAG_IU_REQ_CHANGED) != 0) {
! 2412: ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),
! 2413: SCB_GET_CHANNEL(ahd, scb),
! 2414: SCB_GET_LUN(scb), SCB_LIST_NULL,
! 2415: ROLE_INITIATOR, CAM_REQ_ABORTED);
! 2416: } else {
! 2417: #ifdef AHD_DEBUG
! 2418: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
! 2419: printf("PPR Negotiation Busfree.\n");
! 2420: #endif
! 2421: ahd_done(ahd, scb);
! 2422: }
! 2423: printerror = 0;
! 2424: }
! 2425: if (printerror != 0) {
! 2426: int aborted;
! 2427:
! 2428: aborted = 0;
! 2429: if (scb != NULL) {
! 2430: u_int tag;
! 2431:
! 2432: if ((scb->hscb->control & TAG_ENB) != 0)
! 2433: tag = SCB_GET_TAG(scb);
! 2434: else
! 2435: tag = SCB_LIST_NULL;
! 2436: ahd_print_path(ahd, scb);
! 2437: aborted = ahd_abort_scbs(ahd, target, 'A',
! 2438: SCB_GET_LUN(scb), tag,
! 2439: ROLE_INITIATOR,
! 2440: CAM_UNEXP_BUSFREE);
! 2441: } else {
! 2442: /*
! 2443: * We had not fully identified this connection,
! 2444: * so we cannot abort anything.
! 2445: */
! 2446: printf("%s: ", ahd_name(ahd));
! 2447: }
! 2448: printf("Unexpected busfree %s, %d SCBs aborted, "
! 2449: "PRGMCNT == 0x%x\n",
! 2450: ahd_lookup_phase_entry(lastphase)->phasemsg,
! 2451: aborted,
! 2452: ahd_inw(ahd, PRGMCNT));
! 2453: ahd_dump_card_state(ahd);
! 2454: if (lastphase != P_BUSFREE)
! 2455: ahd_force_renegotiation(ahd, &devinfo);
! 2456: }
! 2457: /* Always restart the sequencer. */
! 2458: return (1);
! 2459: }
! 2460:
! 2461: void
! 2462: ahd_handle_proto_violation(struct ahd_softc *ahd)
! 2463: {
! 2464: struct ahd_devinfo devinfo;
! 2465: struct scb *scb;
! 2466: u_int scbid;
! 2467: u_int seq_flags;
! 2468: u_int curphase;
! 2469: u_int lastphase;
! 2470: int found;
! 2471:
! 2472: ahd_fetch_devinfo(ahd, &devinfo);
! 2473: scbid = ahd_get_scbptr(ahd);
! 2474: scb = ahd_lookup_scb(ahd, scbid);
! 2475: seq_flags = ahd_inb(ahd, SEQ_FLAGS);
! 2476: curphase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;
! 2477: lastphase = ahd_inb(ahd, LASTPHASE);
! 2478: if ((seq_flags & NOT_IDENTIFIED) != 0) {
! 2479:
! 2480: /*
! 2481: * The reconnecting target either did not send an
! 2482: * identify message, or did, but we didn't find an SCB
! 2483: * to match.
! 2484: */
! 2485: ahd_print_devinfo(ahd, &devinfo);
! 2486: printf("Target did not send an IDENTIFY message. "
! 2487: "LASTPHASE = 0x%x.\n", lastphase);
! 2488: scb = NULL;
! 2489: } else if (scb == NULL) {
! 2490: /*
! 2491: * We don't seem to have an SCB active for this
! 2492: * transaction. Print an error and reset the bus.
! 2493: */
! 2494: ahd_print_devinfo(ahd, &devinfo);
! 2495: printf("No SCB found during protocol violation\n");
! 2496: goto proto_violation_reset;
! 2497: } else {
! 2498: aic_set_transaction_status(scb, CAM_SEQUENCE_FAIL);
! 2499: if ((seq_flags & NO_CDB_SENT) != 0) {
! 2500: ahd_print_path(ahd, scb);
! 2501: printf("No or incomplete CDB sent to device.\n");
! 2502: } else if ((ahd_inb_scbram(ahd, SCB_CONTROL)
! 2503: & STATUS_RCVD) == 0) {
! 2504: /*
! 2505: * The target never bothered to provide status to
! 2506: * us prior to completing the command. Since we don't
! 2507: * know the disposition of this command, we must attempt
! 2508: * to abort it. Assert ATN and prepare to send an abort
! 2509: * message.
! 2510: */
! 2511: ahd_print_path(ahd, scb);
! 2512: printf("Completed command without status.\n");
! 2513: } else {
! 2514: ahd_print_path(ahd, scb);
! 2515: printf("Unknown protocol violation.\n");
! 2516: ahd_dump_card_state(ahd);
! 2517: }
! 2518: }
! 2519: if ((lastphase & ~P_DATAIN_DT) == 0
! 2520: || lastphase == P_COMMAND) {
! 2521: proto_violation_reset:
! 2522: /*
! 2523: * Target either went directly to data
! 2524: * phase or didn't respond to our ATN.
! 2525: * The only safe thing to do is to blow
! 2526: * it away with a bus reset.
! 2527: */
! 2528: found = ahd_reset_channel(ahd, 'A', TRUE);
! 2529: printf("%s: Issued Channel %c Bus Reset. "
! 2530: "%d SCBs aborted\n", ahd_name(ahd), 'A', found);
! 2531: } else {
! 2532: /*
! 2533: * Leave the selection hardware off in case
! 2534: * this abort attempt will affect yet to
! 2535: * be sent commands.
! 2536: */
! 2537: ahd_outb(ahd, SCSISEQ0,
! 2538: ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
! 2539: ahd_assert_atn(ahd);
! 2540: ahd_outb(ahd, MSG_OUT, HOST_MSG);
! 2541: if (scb == NULL) {
! 2542: ahd_print_devinfo(ahd, &devinfo);
! 2543: ahd->msgout_buf[0] = MSG_ABORT_TASK;
! 2544: ahd->msgout_len = 1;
! 2545: ahd->msgout_index = 0;
! 2546: ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
! 2547: } else {
! 2548: ahd_print_path(ahd, scb);
! 2549: scb->flags |= SCB_ABORT;
! 2550: }
! 2551: printf("Protocol violation %s. Attempting to abort.\n",
! 2552: ahd_lookup_phase_entry(curphase)->phasemsg);
! 2553: }
! 2554: }
! 2555:
! 2556: /*
! 2557: * Force renegotiation to occur the next time we initiate
! 2558: * a command to the current device.
! 2559: */
! 2560: void
! 2561: ahd_force_renegotiation(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
! 2562: {
! 2563: struct ahd_initiator_tinfo *targ_info;
! 2564: struct ahd_tmode_tstate *tstate;
! 2565:
! 2566: #ifdef AHD_DEBUG
! 2567: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
! 2568: ahd_print_devinfo(ahd, devinfo);
! 2569: printf("Forcing renegotiation\n");
! 2570: }
! 2571: #endif
! 2572: targ_info = ahd_fetch_transinfo(ahd,
! 2573: devinfo->channel,
! 2574: devinfo->our_scsiid,
! 2575: devinfo->target,
! 2576: &tstate);
! 2577: ahd_update_neg_request(ahd, devinfo, tstate,
! 2578: targ_info, AHD_NEG_IF_NON_ASYNC);
! 2579: }
! 2580:
! 2581: #define AHD_MAX_STEPS 2000
! 2582: void
! 2583: ahd_clear_critical_section(struct ahd_softc *ahd)
! 2584: {
! 2585: ahd_mode_state saved_modes;
! 2586: int stepping;
! 2587: int steps;
! 2588: int first_instr;
! 2589: u_int simode0;
! 2590: u_int simode1;
! 2591: u_int simode3;
! 2592: u_int lqimode0;
! 2593: u_int lqimode1;
! 2594: u_int lqomode0;
! 2595: u_int lqomode1;
! 2596:
! 2597: if (ahd->num_critical_sections == 0)
! 2598: return;
! 2599:
! 2600: stepping = FALSE;
! 2601: steps = 0;
! 2602: first_instr = 0;
! 2603: simode0 = 0;
! 2604: simode1 = 0;
! 2605: simode3 = 0;
! 2606: lqimode0 = 0;
! 2607: lqimode1 = 0;
! 2608: lqomode0 = 0;
! 2609: lqomode1 = 0;
! 2610: saved_modes = ahd_save_modes(ahd);
! 2611: for (;;) {
! 2612: struct cs *cs;
! 2613: u_int seqaddr;
! 2614: u_int i;
! 2615:
! 2616: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 2617: seqaddr = ahd_inw(ahd, CURADDR);
! 2618:
! 2619: cs = ahd->critical_sections;
! 2620: for (i = 0; i < ahd->num_critical_sections; i++, cs++) {
! 2621:
! 2622: if (cs->begin < seqaddr && cs->end >= seqaddr)
! 2623: break;
! 2624: }
! 2625:
! 2626: if (i == ahd->num_critical_sections)
! 2627: break;
! 2628:
! 2629: if (steps > AHD_MAX_STEPS) {
! 2630: printf("%s: Infinite loop in critical section\n"
! 2631: "%s: First Instruction 0x%x now 0x%x\n",
! 2632: ahd_name(ahd), ahd_name(ahd), first_instr,
! 2633: seqaddr);
! 2634: ahd_dump_card_state(ahd);
! 2635: panic("critical section loop");
! 2636: }
! 2637:
! 2638: steps++;
! 2639: #ifdef AHD_DEBUG
! 2640: if ((ahd_debug & AHD_SHOW_MISC) != 0)
! 2641: printf("%s: Single stepping at 0x%x\n", ahd_name(ahd),
! 2642: seqaddr);
! 2643: #endif
! 2644: if (stepping == FALSE) {
! 2645:
! 2646: first_instr = seqaddr;
! 2647: ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
! 2648: simode0 = ahd_inb(ahd, SIMODE0);
! 2649: simode3 = ahd_inb(ahd, SIMODE3);
! 2650: lqimode0 = ahd_inb(ahd, LQIMODE0);
! 2651: lqimode1 = ahd_inb(ahd, LQIMODE1);
! 2652: lqomode0 = ahd_inb(ahd, LQOMODE0);
! 2653: lqomode1 = ahd_inb(ahd, LQOMODE1);
! 2654: ahd_outb(ahd, SIMODE0, 0);
! 2655: ahd_outb(ahd, SIMODE3, 0);
! 2656: ahd_outb(ahd, LQIMODE0, 0);
! 2657: ahd_outb(ahd, LQIMODE1, 0);
! 2658: ahd_outb(ahd, LQOMODE0, 0);
! 2659: ahd_outb(ahd, LQOMODE1, 0);
! 2660: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 2661: simode1 = ahd_inb(ahd, SIMODE1);
! 2662: /*
! 2663: * We don't clear ENBUSFREE. Unfortunately
! 2664: * we cannot re-enable busfree detection within
! 2665: * the current connection, so we must leave it
! 2666: * on while single stepping.
! 2667: */
! 2668: ahd_outb(ahd, SIMODE1, simode1 & ENBUSFREE);
! 2669: ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) | STEP);
! 2670: stepping = TRUE;
! 2671: }
! 2672: ahd_outb(ahd, CLRSINT1, CLRBUSFREE);
! 2673: ahd_outb(ahd, CLRINT, CLRSCSIINT);
! 2674: ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
! 2675: ahd_outb(ahd, HCNTRL, ahd->unpause);
! 2676: while (!ahd_is_paused(ahd))
! 2677: aic_delay(200);
! 2678: ahd_update_modes(ahd);
! 2679: }
! 2680: if (stepping) {
! 2681: ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
! 2682: ahd_outb(ahd, SIMODE0, simode0);
! 2683: ahd_outb(ahd, SIMODE3, simode3);
! 2684: ahd_outb(ahd, LQIMODE0, lqimode0);
! 2685: ahd_outb(ahd, LQIMODE1, lqimode1);
! 2686: ahd_outb(ahd, LQOMODE0, lqomode0);
! 2687: ahd_outb(ahd, LQOMODE1, lqomode1);
! 2688: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 2689: ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) & ~STEP);
! 2690: ahd_outb(ahd, SIMODE1, simode1);
! 2691: /*
! 2692: * SCSIINT seems to glitch occassionally when
! 2693: * the interrupt masks are restored. Clear SCSIINT
! 2694: * one more time so that only persistent errors
! 2695: * are seen as a real interrupt.
! 2696: */
! 2697: ahd_outb(ahd, CLRINT, CLRSCSIINT);
! 2698: }
! 2699: ahd_restore_modes(ahd, saved_modes);
! 2700: }
! 2701:
! 2702: /*
! 2703: * Clear any pending interrupt status.
! 2704: */
! 2705: void
! 2706: ahd_clear_intstat(struct ahd_softc *ahd)
! 2707: {
! 2708: AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
! 2709: ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
! 2710: /* Clear any interrupt conditions this may have caused */
! 2711: ahd_outb(ahd, CLRLQIINT0, CLRLQIATNQAS|CLRLQICRCT1|CLRLQICRCT2
! 2712: |CLRLQIBADLQT|CLRLQIATNLQ|CLRLQIATNCMD);
! 2713: ahd_outb(ahd, CLRLQIINT1, CLRLQIPHASE_LQ|CLRLQIPHASE_NLQ|CLRLIQABORT
! 2714: |CLRLQICRCI_LQ|CLRLQICRCI_NLQ|CLRLQIBADLQI
! 2715: |CLRLQIOVERI_LQ|CLRLQIOVERI_NLQ|CLRNONPACKREQ);
! 2716: ahd_outb(ahd, CLRLQOINT0, CLRLQOTARGSCBPERR|CLRLQOSTOPT2|CLRLQOATNLQ
! 2717: |CLRLQOATNPKT|CLRLQOTCRC);
! 2718: ahd_outb(ahd, CLRLQOINT1, CLRLQOINITSCBPERR|CLRLQOSTOPI2|CLRLQOBADQAS
! 2719: |CLRLQOBUSFREE|CLRLQOPHACHGINPKT);
! 2720: if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {
! 2721: ahd_outb(ahd, CLRLQOINT0, 0);
! 2722: ahd_outb(ahd, CLRLQOINT1, 0);
! 2723: }
! 2724: ahd_outb(ahd, CLRSINT3, CLRNTRAMPERR|CLROSRAMPERR);
! 2725: ahd_outb(ahd, CLRSINT1, CLRSELTIMEO|CLRATNO|CLRSCSIRSTI
! 2726: |CLRBUSFREE|CLRSCSIPERR|CLRREQINIT);
! 2727: ahd_outb(ahd, CLRSINT0, CLRSELDO|CLRSELDI|CLRSELINGO
! 2728: |CLRIOERR|CLROVERRUN);
! 2729: ahd_outb(ahd, CLRINT, CLRSCSIINT);
! 2730: }
! 2731:
! 2732: /**************************** Debugging Routines ******************************/
! 2733: #ifdef AHD_DEBUG
! 2734: uint32_t ahd_debug = AHD_DEBUG_OPTS;
! 2735: #endif
! 2736: void
! 2737: ahd_print_scb(struct scb *scb)
! 2738: {
! 2739: struct hardware_scb *hscb;
! 2740: int i;
! 2741:
! 2742: hscb = scb->hscb;
! 2743: printf("scb:%p control:0x%x scsiid:0x%x lun:%d cdb_len:%d\n",
! 2744: (void *)scb,
! 2745: hscb->control,
! 2746: hscb->scsiid,
! 2747: hscb->lun,
! 2748: hscb->cdb_len);
! 2749: printf("Shared Data: ");
! 2750: for (i = 0; i < sizeof(hscb->shared_data.idata.cdb); i++)
! 2751: printf("%#02x", hscb->shared_data.idata.cdb[i]);
! 2752: printf(" dataptr:%#x%x datacnt:%#x sgptr:%#x tag:%#x\n",
! 2753: (uint32_t)((aic_le64toh(hscb->dataptr) >> 32) & 0xFFFFFFFF),
! 2754: (uint32_t)(aic_le64toh(hscb->dataptr) & 0xFFFFFFFF),
! 2755: aic_le32toh(hscb->datacnt),
! 2756: aic_le32toh(hscb->sgptr),
! 2757: SCB_GET_TAG(scb));
! 2758: ahd_dump_sglist(scb);
! 2759: }
! 2760:
! 2761: void
! 2762: ahd_dump_sglist(struct scb *scb)
! 2763: {
! 2764: int i;
! 2765:
! 2766: if (scb->sg_count > 0) {
! 2767: if ((scb->ahd_softc->flags & AHD_64BIT_ADDRESSING) != 0) {
! 2768: struct ahd_dma64_seg *sg_list;
! 2769:
! 2770: sg_list = (struct ahd_dma64_seg*)scb->sg_list;
! 2771: for (i = 0; i < scb->sg_count; i++) {
! 2772: uint64_t addr;
! 2773: uint32_t len;
! 2774:
! 2775: addr = aic_le64toh(sg_list[i].addr);
! 2776: len = aic_le32toh(sg_list[i].len);
! 2777: printf("sg[%d] - Addr 0x%x%x : Length %d%s\n",
! 2778: i,
! 2779: (uint32_t)((addr >> 32) & 0xFFFFFFFF),
! 2780: (uint32_t)(addr & 0xFFFFFFFF),
! 2781: sg_list[i].len & AHD_SG_LEN_MASK,
! 2782: (sg_list[i].len & AHD_DMA_LAST_SEG)
! 2783: ? " Last" : "");
! 2784: }
! 2785: } else {
! 2786: struct ahd_dma_seg *sg_list;
! 2787:
! 2788: sg_list = (struct ahd_dma_seg*)scb->sg_list;
! 2789: for (i = 0; i < scb->sg_count; i++) {
! 2790: uint32_t len;
! 2791:
! 2792: len = aic_le32toh(sg_list[i].len);
! 2793: printf("sg[%d] - Addr 0x%x%x : Length %d%s\n",
! 2794: i,
! 2795: (len & AHD_SG_HIGH_ADDR_MASK) >> 24,
! 2796: aic_le32toh(sg_list[i].addr),
! 2797: len & AHD_SG_LEN_MASK,
! 2798: len & AHD_DMA_LAST_SEG ? " Last" : "");
! 2799: }
! 2800: }
! 2801: }
! 2802: }
! 2803:
! 2804: /************************* Transfer Negotiation *******************************/
! 2805: /*
! 2806: * Allocate per target mode instance (ID we respond to as a target)
! 2807: * transfer negotiation data structures.
! 2808: */
! 2809: struct ahd_tmode_tstate *
! 2810: ahd_alloc_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel)
! 2811: {
! 2812: struct ahd_tmode_tstate *master_tstate;
! 2813: struct ahd_tmode_tstate *tstate;
! 2814: int i;
! 2815:
! 2816: master_tstate = ahd->enabled_targets[ahd->our_id];
! 2817: if (ahd->enabled_targets[scsi_id] != NULL
! 2818: && ahd->enabled_targets[scsi_id] != master_tstate)
! 2819: panic("%s: ahd_alloc_tstate - Target already allocated",
! 2820: ahd_name(ahd));
! 2821: tstate = malloc(sizeof(*tstate), M_DEVBUF, M_NOWAIT);
! 2822: if (tstate == NULL)
! 2823: return (NULL);
! 2824:
! 2825: /*
! 2826: * If we have allocated a master tstate, copy user settings from
! 2827: * the master tstate (taken from SRAM or the EEPROM) for this
! 2828: * channel, but reset our current and goal settings to async/narrow
! 2829: * until an initiator talks to us.
! 2830: */
! 2831: if (master_tstate != NULL) {
! 2832: memcpy(tstate, master_tstate, sizeof(*tstate));
! 2833: memset(tstate->enabled_luns, 0, sizeof(tstate->enabled_luns));
! 2834: for (i = 0; i < 16; i++) {
! 2835: memset(&tstate->transinfo[i].curr, 0,
! 2836: sizeof(tstate->transinfo[i].curr));
! 2837: memset(&tstate->transinfo[i].goal, 0,
! 2838: sizeof(tstate->transinfo[i].goal));
! 2839: }
! 2840: } else
! 2841: memset(tstate, 0, sizeof(*tstate));
! 2842: ahd->enabled_targets[scsi_id] = tstate;
! 2843: return (tstate);
! 2844: }
! 2845:
! 2846: #ifdef AHD_TARGET_MODE
! 2847: /*
! 2848: * Free per target mode instance (ID we respond to as a target)
! 2849: * transfer negotiation data structures.
! 2850: */
! 2851: void
! 2852: ahd_free_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel, int force)
! 2853: {
! 2854: struct ahd_tmode_tstate *tstate;
! 2855:
! 2856: /*
! 2857: * Don't clean up our "master" tstate.
! 2858: * It has our default user settings.
! 2859: */
! 2860: if (scsi_id == ahd->our_id
! 2861: && force == FALSE)
! 2862: return;
! 2863:
! 2864: tstate = ahd->enabled_targets[scsi_id];
! 2865: if (tstate != NULL)
! 2866: free(tstate, M_DEVBUF);
! 2867: ahd->enabled_targets[scsi_id] = NULL;
! 2868: }
! 2869: #endif
! 2870:
! 2871: /*
! 2872: * Called when we have an active connection to a target on the bus,
! 2873: * this function finds the nearest period to the input period limited
! 2874: * by the capabilities of the bus connectivity of and sync settings for
! 2875: * the target.
! 2876: */
! 2877: void
! 2878: ahd_devlimited_syncrate(struct ahd_softc *ahd,
! 2879: struct ahd_initiator_tinfo *tinfo,
! 2880: u_int *period, u_int *ppr_options, role_t role)
! 2881: {
! 2882: struct ahd_transinfo *transinfo;
! 2883: u_int maxsync;
! 2884:
! 2885: if ((ahd_inb(ahd, SBLKCTL) & ENAB40) != 0
! 2886: && (ahd_inb(ahd, SSTAT2) & EXP_ACTIVE) == 0) {
! 2887: maxsync = AHD_SYNCRATE_PACED;
! 2888: } else {
! 2889: maxsync = AHD_SYNCRATE_ULTRA;
! 2890: /* Can't do DT related options on an SE bus */
! 2891: *ppr_options &= MSG_EXT_PPR_QAS_REQ;
! 2892: }
! 2893: /*
! 2894: * Never allow a value higher than our current goal
! 2895: * period otherwise we may allow a target initiated
! 2896: * negotiation to go above the limit as set by the
! 2897: * user. In the case of an initiator initiated
! 2898: * sync negotiation, we limit based on the user
! 2899: * setting. This allows the system to still accept
! 2900: * incoming negotiations even if target initiated
! 2901: * negotiation is not performed.
! 2902: */
! 2903: if (role == ROLE_TARGET)
! 2904: transinfo = &tinfo->user;
! 2905: else
! 2906: transinfo = &tinfo->goal;
! 2907: *ppr_options &= (transinfo->ppr_options|MSG_EXT_PPR_PCOMP_EN);
! 2908: if (transinfo->width == MSG_EXT_WDTR_BUS_8_BIT) {
! 2909: maxsync = MAX(maxsync, AHD_SYNCRATE_ULTRA2);
! 2910: *ppr_options &= ~MSG_EXT_PPR_DT_REQ;
! 2911: }
! 2912: if (transinfo->period == 0) {
! 2913: *period = 0;
! 2914: *ppr_options = 0;
! 2915: } else {
! 2916: *period = MAX(*period, transinfo->period);
! 2917: ahd_find_syncrate(ahd, period, ppr_options, maxsync);
! 2918: }
! 2919: }
! 2920:
! 2921: /*
! 2922: * Look up the valid period to SCSIRATE conversion in our table.
! 2923: * Return the period and offset that should be sent to the target
! 2924: * if this was the beginning of an SDTR.
! 2925: */
! 2926: void
! 2927: ahd_find_syncrate(struct ahd_softc *ahd, u_int *period,
! 2928: u_int *ppr_options, u_int maxsync)
! 2929: {
! 2930: if (*period < maxsync)
! 2931: *period = maxsync;
! 2932:
! 2933: if ((*ppr_options & MSG_EXT_PPR_DT_REQ) != 0
! 2934: && *period > AHD_SYNCRATE_MIN_DT)
! 2935: *ppr_options &= ~MSG_EXT_PPR_DT_REQ;
! 2936:
! 2937: if (*period > AHD_SYNCRATE_MIN)
! 2938: *period = 0;
! 2939:
! 2940: /* Honor PPR option conformance rules. */
! 2941: if (*period > AHD_SYNCRATE_PACED)
! 2942: *ppr_options &= ~MSG_EXT_PPR_RTI;
! 2943:
! 2944: if ((*ppr_options & MSG_EXT_PPR_IU_REQ) == 0)
! 2945: *ppr_options &= (MSG_EXT_PPR_DT_REQ|MSG_EXT_PPR_QAS_REQ);
! 2946:
! 2947: if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0)
! 2948: *ppr_options &= MSG_EXT_PPR_QAS_REQ;
! 2949:
! 2950: /* Skip all PACED only entries if IU is not available */
! 2951: if ((*ppr_options & MSG_EXT_PPR_IU_REQ) == 0
! 2952: && *period < AHD_SYNCRATE_DT)
! 2953: *period = AHD_SYNCRATE_DT;
! 2954:
! 2955: /* Skip all DT only entries if DT is not available */
! 2956: if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0
! 2957: && *period < AHD_SYNCRATE_ULTRA2)
! 2958: *period = AHD_SYNCRATE_ULTRA2;
! 2959: }
! 2960:
! 2961: /*
! 2962: * Truncate the given synchronous offset to a value the
! 2963: * current adapter type and syncrate are capable of.
! 2964: */
! 2965: void
! 2966: ahd_validate_offset(struct ahd_softc *ahd,
! 2967: struct ahd_initiator_tinfo *tinfo,
! 2968: u_int period, u_int *offset, int wide,
! 2969: role_t role)
! 2970: {
! 2971: u_int maxoffset;
! 2972:
! 2973: /* Limit offset to what we can do */
! 2974: if (period == 0)
! 2975: maxoffset = 0;
! 2976: else if (period <= AHD_SYNCRATE_PACED) {
! 2977: if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0)
! 2978: maxoffset = MAX_OFFSET_PACED_BUG;
! 2979: else
! 2980: maxoffset = MAX_OFFSET_PACED;
! 2981: } else
! 2982: maxoffset = MAX_OFFSET_NON_PACED;
! 2983: *offset = MIN(*offset, maxoffset);
! 2984: if (tinfo != NULL) {
! 2985: if (role == ROLE_TARGET)
! 2986: *offset = MIN(*offset, tinfo->user.offset);
! 2987: else
! 2988: *offset = MIN(*offset, tinfo->goal.offset);
! 2989: }
! 2990: }
! 2991:
! 2992: /*
! 2993: * Truncate the given transfer width parameter to a value the
! 2994: * current adapter type is capable of.
! 2995: */
! 2996: void
! 2997: ahd_validate_width(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo,
! 2998: u_int *bus_width, role_t role)
! 2999: {
! 3000: switch (*bus_width) {
! 3001: default:
! 3002: if (ahd->features & AHD_WIDE) {
! 3003: /* Respond Wide */
! 3004: *bus_width = MSG_EXT_WDTR_BUS_16_BIT;
! 3005: break;
! 3006: }
! 3007: /* FALLTHROUGH */
! 3008: case MSG_EXT_WDTR_BUS_8_BIT:
! 3009: *bus_width = MSG_EXT_WDTR_BUS_8_BIT;
! 3010: break;
! 3011: }
! 3012: if (tinfo != NULL) {
! 3013: if (role == ROLE_TARGET)
! 3014: *bus_width = MIN(tinfo->user.width, *bus_width);
! 3015: else
! 3016: *bus_width = MIN(tinfo->goal.width, *bus_width);
! 3017: }
! 3018: }
! 3019:
! 3020: /*
! 3021: * Update the bitmask of targets for which the controller should
! 3022: * negotiate with at the next convenient oportunity. This currently
! 3023: * means the next time we send the initial identify messages for
! 3024: * a new transaction.
! 3025: */
! 3026: int
! 3027: ahd_update_neg_request(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
! 3028: struct ahd_tmode_tstate *tstate,
! 3029: struct ahd_initiator_tinfo *tinfo, ahd_neg_type neg_type)
! 3030: {
! 3031: u_int auto_negotiate_orig;
! 3032:
! 3033: auto_negotiate_orig = tstate->auto_negotiate;
! 3034: if (neg_type == AHD_NEG_ALWAYS) {
! 3035: /*
! 3036: * Force our "current" settings to be
! 3037: * unknown so that unless a bus reset
! 3038: * occurs the need to renegotiate is
! 3039: * recorded persistently.
! 3040: */
! 3041: if ((ahd->features & AHD_WIDE) != 0)
! 3042: tinfo->curr.width = AHD_WIDTH_UNKNOWN;
! 3043: tinfo->curr.period = AHD_PERIOD_UNKNOWN;
! 3044: tinfo->curr.offset = AHD_OFFSET_UNKNOWN;
! 3045: }
! 3046: if (tinfo->curr.period != tinfo->goal.period
! 3047: || tinfo->curr.width != tinfo->goal.width
! 3048: || tinfo->curr.offset != tinfo->goal.offset
! 3049: || tinfo->curr.ppr_options != tinfo->goal.ppr_options
! 3050: || (neg_type == AHD_NEG_IF_NON_ASYNC
! 3051: && (tinfo->goal.offset != 0
! 3052: || tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT
! 3053: || tinfo->goal.ppr_options != 0)))
! 3054: tstate->auto_negotiate |= devinfo->target_mask;
! 3055: else
! 3056: tstate->auto_negotiate &= ~devinfo->target_mask;
! 3057:
! 3058: return (auto_negotiate_orig != tstate->auto_negotiate);
! 3059: }
! 3060:
! 3061: /*
! 3062: * Update the user/goal/curr tables of synchronous negotiation
! 3063: * parameters as well as, in the case of a current or active update,
! 3064: * any data structures on the host controller. In the case of an
! 3065: * active update, the specified target is currently talking to us on
! 3066: * the bus, so the transfer parameter update must take effect
! 3067: * immediately.
! 3068: */
! 3069: void
! 3070: ahd_set_syncrate(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
! 3071: u_int period, u_int offset, u_int ppr_options,
! 3072: u_int type, int paused)
! 3073: {
! 3074: struct ahd_initiator_tinfo *tinfo;
! 3075: struct ahd_tmode_tstate *tstate;
! 3076: u_int old_period;
! 3077: u_int old_offset;
! 3078: u_int old_ppr;
! 3079: int active;
! 3080: int update_needed;
! 3081:
! 3082: active = (type & AHD_TRANS_ACTIVE) == AHD_TRANS_ACTIVE;
! 3083: update_needed = 0;
! 3084:
! 3085: if (period == 0 || offset == 0) {
! 3086: period = 0;
! 3087: offset = 0;
! 3088: }
! 3089:
! 3090: tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
! 3091: devinfo->target, &tstate);
! 3092:
! 3093: if ((type & AHD_TRANS_USER) != 0) {
! 3094: tinfo->user.period = period;
! 3095: tinfo->user.offset = offset;
! 3096: tinfo->user.ppr_options = ppr_options;
! 3097: }
! 3098:
! 3099: if ((type & AHD_TRANS_GOAL) != 0) {
! 3100: tinfo->goal.period = period;
! 3101: tinfo->goal.offset = offset;
! 3102: tinfo->goal.ppr_options = ppr_options;
! 3103: }
! 3104:
! 3105: old_period = tinfo->curr.period;
! 3106: old_offset = tinfo->curr.offset;
! 3107: old_ppr = tinfo->curr.ppr_options;
! 3108:
! 3109: if ((type & AHD_TRANS_CUR) != 0
! 3110: && (old_period != period
! 3111: || old_offset != offset
! 3112: || old_ppr != ppr_options)) {
! 3113:
! 3114: update_needed++;
! 3115:
! 3116: tinfo->curr.period = period;
! 3117: tinfo->curr.offset = offset;
! 3118: tinfo->curr.ppr_options = ppr_options;
! 3119: #if 0
! 3120: ahd_send_async(ahd, devinfo->channel, devinfo->target,
! 3121: CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
! 3122: #endif
! 3123: if (1 /*bootverbose*/) {
! 3124: if (offset != 0) {
! 3125: int options;
! 3126:
! 3127: printf("%s: target %d synchronous with "
! 3128: "period = 0x%x, offset = 0x%x",
! 3129: ahd_name(ahd), devinfo->target,
! 3130: period, offset);
! 3131: options = 0;
! 3132: if ((ppr_options & MSG_EXT_PPR_RD_STRM) != 0) {
! 3133: printf("(RDSTRM");
! 3134: options++;
! 3135: }
! 3136: if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) {
! 3137: printf("%s", options ? "|DT" : "(DT");
! 3138: options++;
! 3139: }
! 3140: if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
! 3141: printf("%s", options ? "|IU" : "(IU");
! 3142: options++;
! 3143: }
! 3144: if ((ppr_options & MSG_EXT_PPR_RTI) != 0) {
! 3145: printf("%s", options ? "|RTI" : "(RTI");
! 3146: options++;
! 3147: }
! 3148: if ((ppr_options & MSG_EXT_PPR_QAS_REQ) != 0) {
! 3149: printf("%s", options ? "|QAS" : "(QAS");
! 3150: options++;
! 3151: }
! 3152: if (options != 0)
! 3153: printf(")\n");
! 3154: else
! 3155: printf("\n");
! 3156: } else {
! 3157: printf("%s: target %d using "
! 3158: "asynchronous transfers%s\n",
! 3159: ahd_name(ahd), devinfo->target,
! 3160: (ppr_options & MSG_EXT_PPR_QAS_REQ) != 0
! 3161: ? "(QAS)" : "");
! 3162: }
! 3163: }
! 3164: }
! 3165: /*
! 3166: * Always refresh the neg-table to handle the case of the
! 3167: * sequencer setting the ENATNO bit for a MK_MESSAGE request.
! 3168: * We will always renegotiate in that case if this is a
! 3169: * packetized request. Also manage the busfree expected flag
! 3170: * from this common routine so that we catch changes due to
! 3171: * WDTR or SDTR messages.
! 3172: */
! 3173: if ((type & AHD_TRANS_CUR) != 0) {
! 3174: if (!paused)
! 3175: ahd_pause(ahd);
! 3176: ahd_update_neg_table(ahd, devinfo, &tinfo->curr);
! 3177: if (!paused)
! 3178: ahd_unpause(ahd);
! 3179: if (ahd->msg_type != MSG_TYPE_NONE) {
! 3180: if ((old_ppr & MSG_EXT_PPR_IU_REQ)
! 3181: != (ppr_options & MSG_EXT_PPR_IU_REQ)) {
! 3182: #ifdef AHD_DEBUG
! 3183: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
! 3184: ahd_print_devinfo(ahd, devinfo);
! 3185: printf("Expecting IU Change busfree\n");
! 3186: }
! 3187: #endif
! 3188: ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE
! 3189: | MSG_FLAG_IU_REQ_CHANGED;
! 3190: }
! 3191: if ((old_ppr & MSG_EXT_PPR_IU_REQ) != 0) {
! 3192: #ifdef AHD_DEBUG
! 3193: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
! 3194: printf("PPR with IU_REQ outstanding\n");
! 3195: #endif
! 3196: ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE;
! 3197: }
! 3198: }
! 3199: }
! 3200:
! 3201: update_needed += ahd_update_neg_request(ahd, devinfo, tstate,
! 3202: tinfo, AHD_NEG_TO_GOAL);
! 3203:
! 3204: if (update_needed && active)
! 3205: ahd_update_pending_scbs(ahd);
! 3206: }
! 3207:
! 3208: /*
! 3209: * Update the user/goal/curr tables of wide negotiation
! 3210: * parameters as well as, in the case of a current or active update,
! 3211: * any data structures on the host controller. In the case of an
! 3212: * active update, the specified target is currently talking to us on
! 3213: * the bus, so the transfer parameter update must take effect
! 3214: * immediately.
! 3215: */
! 3216: void
! 3217: ahd_set_width(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
! 3218: u_int width, u_int type, int paused)
! 3219: {
! 3220: struct ahd_initiator_tinfo *tinfo;
! 3221: struct ahd_tmode_tstate *tstate;
! 3222: u_int oldwidth;
! 3223: int active;
! 3224: int update_needed;
! 3225:
! 3226: active = (type & AHD_TRANS_ACTIVE) == AHD_TRANS_ACTIVE;
! 3227: update_needed = 0;
! 3228: tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
! 3229: devinfo->target, &tstate);
! 3230:
! 3231: if ((type & AHD_TRANS_USER) != 0)
! 3232: tinfo->user.width = width;
! 3233:
! 3234: if ((type & AHD_TRANS_GOAL) != 0)
! 3235: tinfo->goal.width = width;
! 3236:
! 3237: oldwidth = tinfo->curr.width;
! 3238: if ((type & AHD_TRANS_CUR) != 0 && oldwidth != width) {
! 3239:
! 3240: update_needed++;
! 3241:
! 3242: tinfo->curr.width = width;
! 3243: #if 0
! 3244: ahd_send_async(ahd, devinfo->channel, devinfo->target,
! 3245: CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL);
! 3246: #endif
! 3247: if (bootverbose) {
! 3248: printf("%s: target %d using %dbit transfers\n",
! 3249: ahd_name(ahd), devinfo->target,
! 3250: 8 * (0x01 << width));
! 3251: }
! 3252: }
! 3253:
! 3254: if ((type & AHD_TRANS_CUR) != 0) {
! 3255: if (!paused)
! 3256: ahd_pause(ahd);
! 3257: ahd_update_neg_table(ahd, devinfo, &tinfo->curr);
! 3258: if (!paused)
! 3259: ahd_unpause(ahd);
! 3260: }
! 3261:
! 3262: update_needed += ahd_update_neg_request(ahd, devinfo, tstate,
! 3263: tinfo, AHD_NEG_TO_GOAL);
! 3264: if (update_needed && active)
! 3265: ahd_update_pending_scbs(ahd);
! 3266:
! 3267: }
! 3268:
! 3269: /*
! 3270: * Update the current state of tagged queuing for a given target.
! 3271: */
! 3272: void
! 3273: ahd_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
! 3274: ahd_queue_alg alg)
! 3275: {
! 3276: ahd_platform_set_tags(ahd, devinfo, alg);
! 3277: #if 0
! 3278: ahd_send_async(ahd, devinfo->channel, devinfo->target,
! 3279: devinfo->lun, AC_TRANSFER_NEG, &alg);
! 3280: #endif
! 3281: }
! 3282:
! 3283: void
! 3284: ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
! 3285: struct ahd_transinfo *tinfo)
! 3286: {
! 3287: ahd_mode_state saved_modes;
! 3288: u_int period;
! 3289: u_int ppr_opts;
! 3290: u_int con_opts;
! 3291: u_int offset;
! 3292: u_int saved_negoaddr;
! 3293: uint8_t iocell_opts[sizeof(ahd->iocell_opts)];
! 3294:
! 3295: saved_modes = ahd_save_modes(ahd);
! 3296: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 3297:
! 3298: saved_negoaddr = ahd_inb(ahd, NEGOADDR);
! 3299: ahd_outb(ahd, NEGOADDR, devinfo->target);
! 3300: period = tinfo->period;
! 3301: offset = tinfo->offset;
! 3302: memcpy(iocell_opts, ahd->iocell_opts, sizeof(ahd->iocell_opts));
! 3303: ppr_opts = tinfo->ppr_options & (MSG_EXT_PPR_QAS_REQ|MSG_EXT_PPR_DT_REQ
! 3304: |MSG_EXT_PPR_IU_REQ|MSG_EXT_PPR_RTI);
! 3305: con_opts = 0;
! 3306: if (period == 0)
! 3307: period = AHD_SYNCRATE_ASYNC;
! 3308: if (period == AHD_SYNCRATE_160) {
! 3309:
! 3310: if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) {
! 3311: /*
! 3312: * When the SPI4 spec was finalized, PACE transfers
! 3313: * was not made a configurable option in the PPR
! 3314: * message. Instead it is assumed to be enabled for
! 3315: * any syncrate faster than 80MHz. Nevertheless,
! 3316: * Harpoon2A4 allows this to be configurable.
! 3317: *
! 3318: * Harpoon2A4 also assumes at most 2 data bytes per
! 3319: * negotiated REQ/ACK offset. Paced transfers take
! 3320: * 4, so we must adjust our offset.
! 3321: */
! 3322: ppr_opts |= PPROPT_PACE;
! 3323: offset *= 2;
! 3324:
! 3325: /*
! 3326: * Harpoon2A assumed that there would be a
! 3327: * fallback rate between 160MHz and 80MHz,
! 3328: * so 7 is used as the period factor rather
! 3329: * than 8 for 160MHz.
! 3330: */
! 3331: period = AHD_SYNCRATE_REVA_160;
! 3332: }
! 3333: if ((tinfo->ppr_options & MSG_EXT_PPR_PCOMP_EN) == 0)
! 3334: iocell_opts[AHD_PRECOMP_SLEW_INDEX] &=
! 3335: ~AHD_PRECOMP_MASK;
! 3336: } else {
! 3337: /*
! 3338: * Precomp should be disabled for non-paced transfers.
! 3339: */
! 3340: iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK;
! 3341:
! 3342: if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0
! 3343: && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0
! 3344: && (ppr_opts & MSG_EXT_PPR_IU_REQ) == 0) {
! 3345: /*
! 3346: * Slow down our CRC interval to be
! 3347: * compatible with non-packetized
! 3348: * U160 devices that can't handle a
! 3349: * CRC at full speed.
! 3350: */
! 3351: con_opts |= ENSLOWCRC;
! 3352: }
! 3353:
! 3354: if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) {
! 3355: /*
! 3356: * On H2A4, revert to a slower slewrate
! 3357: * on non-paced transfers.
! 3358: */
! 3359: iocell_opts[AHD_PRECOMP_SLEW_INDEX] &=
! 3360: ~AHD_SLEWRATE_MASK;
! 3361: }
! 3362: }
! 3363:
! 3364: ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW);
! 3365: ahd_outb(ahd, ANNEXDAT, iocell_opts[AHD_PRECOMP_SLEW_INDEX]);
! 3366: ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_AMPLITUDE);
! 3367: ahd_outb(ahd, ANNEXDAT, iocell_opts[AHD_AMPLITUDE_INDEX]);
! 3368:
! 3369: ahd_outb(ahd, NEGPERIOD, period);
! 3370: ahd_outb(ahd, NEGPPROPTS, ppr_opts);
! 3371: ahd_outb(ahd, NEGOFFSET, offset);
! 3372:
! 3373: if (tinfo->width == MSG_EXT_WDTR_BUS_16_BIT)
! 3374: con_opts |= WIDEXFER;
! 3375:
! 3376: /*
! 3377: * During packetized transfers, the target will
! 3378: * give us the oportunity to send command packets
! 3379: * without us asserting attention.
! 3380: */
! 3381: if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ) == 0)
! 3382: con_opts |= ENAUTOATNO;
! 3383: ahd_outb(ahd, NEGCONOPTS, con_opts);
! 3384: ahd_outb(ahd, NEGOADDR, saved_negoaddr);
! 3385: ahd_restore_modes(ahd, saved_modes);
! 3386: }
! 3387:
! 3388: /*
! 3389: * When the transfer settings for a connection change, setup for
! 3390: * negotiation in pending SCBs to effect the change as quickly as
! 3391: * possible. We also cancel any negotiations that are scheduled
! 3392: * for inflight SCBs that have not been started yet.
! 3393: */
! 3394: void
! 3395: ahd_update_pending_scbs(struct ahd_softc *ahd)
! 3396: {
! 3397: struct scb *pending_scb;
! 3398: int pending_scb_count;
! 3399: int paused;
! 3400: u_int saved_scbptr;
! 3401: ahd_mode_state saved_modes;
! 3402:
! 3403: /*
! 3404: * Traverse the pending SCB list and ensure that all of the
! 3405: * SCBs there have the proper settings. We can only safely
! 3406: * clear the negotiation required flag (setting requires the
! 3407: * execution queue to be modified) and this is only possible
! 3408: * if we are not already attempting to select out for this
! 3409: * SCB. For this reason, all callers only call this routine
! 3410: * if we are changing the negotiation settings for the currently
! 3411: * active transaction on the bus.
! 3412: */
! 3413: pending_scb_count = 0;
! 3414: LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
! 3415: struct ahd_devinfo devinfo;
! 3416: struct ahd_initiator_tinfo *tinfo;
! 3417: struct ahd_tmode_tstate *tstate;
! 3418:
! 3419: ahd_scb_devinfo(ahd, &devinfo, pending_scb);
! 3420: tinfo = ahd_fetch_transinfo(ahd, devinfo.channel,
! 3421: devinfo.our_scsiid,
! 3422: devinfo.target, &tstate);
! 3423: if ((tstate->auto_negotiate & devinfo.target_mask) == 0
! 3424: && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) {
! 3425: pending_scb->flags &= ~SCB_AUTO_NEGOTIATE;
! 3426: pending_scb->hscb->control &= ~MK_MESSAGE;
! 3427: }
! 3428: ahd_sync_scb(ahd, pending_scb,
! 3429: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 3430: pending_scb_count++;
! 3431: }
! 3432:
! 3433: if (pending_scb_count == 0)
! 3434: return;
! 3435:
! 3436: if (ahd_is_paused(ahd)) {
! 3437: paused = 1;
! 3438: } else {
! 3439: paused = 0;
! 3440: ahd_pause(ahd);
! 3441: }
! 3442:
! 3443: /*
! 3444: * Force the sequencer to reinitialize the selection for
! 3445: * the command at the head of the execution queue if it
! 3446: * has already been setup. The negotiation changes may
! 3447: * effect whether we select-out with ATN. It is only
! 3448: * safe to clear ENSELO when the bus is not free and no
! 3449: * selection is in progres or completed.
! 3450: */
! 3451: saved_modes = ahd_save_modes(ahd);
! 3452: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 3453: if ((ahd_inb(ahd, SCSISIGI) & BSYI) != 0
! 3454: && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0)
! 3455: ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
! 3456: saved_scbptr = ahd_get_scbptr(ahd);
! 3457: /* Ensure that the hscbs down on the card match the new information */
! 3458: LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
! 3459: u_int scb_tag;
! 3460: u_int control;
! 3461:
! 3462: scb_tag = SCB_GET_TAG(pending_scb);
! 3463: ahd_set_scbptr(ahd, scb_tag);
! 3464: control = ahd_inb_scbram(ahd, SCB_CONTROL);
! 3465: control &= ~MK_MESSAGE;
! 3466: control |= pending_scb->hscb->control & MK_MESSAGE;
! 3467: ahd_outb(ahd, SCB_CONTROL, control);
! 3468: }
! 3469: ahd_set_scbptr(ahd, saved_scbptr);
! 3470: ahd_restore_modes(ahd, saved_modes);
! 3471:
! 3472: if (paused == 0)
! 3473: ahd_unpause(ahd);
! 3474: }
! 3475:
! 3476: /**************************** Pathing Information *****************************/
! 3477: void
! 3478: ahd_fetch_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
! 3479: {
! 3480: ahd_mode_state saved_modes;
! 3481: u_int saved_scsiid;
! 3482: role_t role;
! 3483: int our_id;
! 3484:
! 3485: saved_modes = ahd_save_modes(ahd);
! 3486: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 3487:
! 3488: if (ahd_inb(ahd, SSTAT0) & TARGET)
! 3489: role = ROLE_TARGET;
! 3490: else
! 3491: role = ROLE_INITIATOR;
! 3492:
! 3493: if (role == ROLE_TARGET
! 3494: && (ahd_inb(ahd, SEQ_FLAGS) & CMDPHASE_PENDING) != 0) {
! 3495: /* We were selected, so pull our id from TARGIDIN */
! 3496: our_id = ahd_inb(ahd, TARGIDIN) & OID;
! 3497: } else if (role == ROLE_TARGET)
! 3498: our_id = ahd_inb(ahd, TOWNID);
! 3499: else
! 3500: our_id = ahd_inb(ahd, IOWNID);
! 3501:
! 3502: saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
! 3503: ahd_compile_devinfo(devinfo,
! 3504: our_id,
! 3505: SCSIID_TARGET(ahd, saved_scsiid),
! 3506: ahd_inb(ahd, SAVED_LUN),
! 3507: SCSIID_CHANNEL(ahd, saved_scsiid),
! 3508: role);
! 3509: ahd_restore_modes(ahd, saved_modes);
! 3510: }
! 3511:
! 3512: void
! 3513: ahd_print_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
! 3514: {
! 3515: printf("%s:%c:%d:%d: ", ahd_name(ahd), 'A',
! 3516: devinfo->target, devinfo->lun);
! 3517: }
! 3518:
! 3519: struct ahd_phase_table_entry*
! 3520: ahd_lookup_phase_entry(int phase)
! 3521: {
! 3522: struct ahd_phase_table_entry *entry;
! 3523: struct ahd_phase_table_entry *last_entry;
! 3524:
! 3525: /*
! 3526: * num_phases doesn't include the default entry which
! 3527: * will be returned if the phase doesn't match.
! 3528: */
! 3529: last_entry = &ahd_phase_table[num_phases];
! 3530: for (entry = ahd_phase_table; entry < last_entry; entry++) {
! 3531: if (phase == entry->phase)
! 3532: break;
! 3533: }
! 3534: return (entry);
! 3535: }
! 3536:
! 3537: void
! 3538: ahd_compile_devinfo(struct ahd_devinfo *devinfo, u_int our_id, u_int target,
! 3539: u_int lun, char channel, role_t role)
! 3540: {
! 3541: devinfo->our_scsiid = our_id;
! 3542: devinfo->target = target;
! 3543: devinfo->lun = lun;
! 3544: devinfo->target_offset = target;
! 3545: devinfo->channel = channel;
! 3546: devinfo->role = role;
! 3547: if (channel == 'B')
! 3548: devinfo->target_offset += 8;
! 3549: devinfo->target_mask = (0x01 << devinfo->target_offset);
! 3550: }
! 3551:
! 3552: void
! 3553: ahd_scb_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
! 3554: struct scb *scb)
! 3555: {
! 3556: role_t role;
! 3557: int our_id;
! 3558:
! 3559: our_id = SCSIID_OUR_ID(scb->hscb->scsiid);
! 3560: role = ROLE_INITIATOR;
! 3561: if ((scb->hscb->control & TARGET_SCB) != 0)
! 3562: role = ROLE_TARGET;
! 3563: ahd_compile_devinfo(devinfo, our_id, SCB_GET_TARGET(ahd, scb),
! 3564: SCB_GET_LUN(scb), SCB_GET_CHANNEL(ahd, scb), role);
! 3565: }
! 3566:
! 3567:
! 3568: /************************ Message Phase Processing ****************************/
! 3569: /*
! 3570: * When an initiator transaction with the MK_MESSAGE flag either reconnects
! 3571: * or enters the initial message out phase, we are interrupted. Fill our
! 3572: * outgoing message buffer with the appropriate message and beging handing
! 3573: * the message phase(s) manually.
! 3574: */
! 3575: void
! 3576: ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
! 3577: struct scb *scb)
! 3578: {
! 3579: /*
! 3580: * To facilitate adding multiple messages together,
! 3581: * each routine should increment the index and len
! 3582: * variables instead of setting them explicitly.
! 3583: */
! 3584: ahd->msgout_index = 0;
! 3585: ahd->msgout_len = 0;
! 3586:
! 3587: if (ahd_currently_packetized(ahd))
! 3588: ahd->msg_flags |= MSG_FLAG_PACKETIZED;
! 3589:
! 3590: if (ahd->send_msg_perror
! 3591: && ahd_inb(ahd, MSG_OUT) == HOST_MSG) {
! 3592: ahd->msgout_buf[ahd->msgout_index++] = ahd->send_msg_perror;
! 3593: ahd->msgout_len++;
! 3594: ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
! 3595: #ifdef AHD_DEBUG
! 3596: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
! 3597: printf("Setting up for Parity Error delivery\n");
! 3598: #endif
! 3599: return;
! 3600: } else if (scb == NULL) {
! 3601: printf("%s: WARNING. No pending message for "
! 3602: "I_T msgin. Issuing NO-OP\n", ahd_name(ahd));
! 3603: ahd->msgout_buf[ahd->msgout_index++] = MSG_NOOP;
! 3604: ahd->msgout_len++;
! 3605: ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
! 3606: return;
! 3607: }
! 3608:
! 3609: if ((scb->flags & SCB_DEVICE_RESET) == 0
! 3610: && (scb->flags & SCB_PACKETIZED) == 0
! 3611: && ahd_inb(ahd, MSG_OUT) == MSG_IDENTIFYFLAG) {
! 3612: u_int identify_msg;
! 3613:
! 3614: identify_msg = MSG_IDENTIFYFLAG | SCB_GET_LUN(scb);
! 3615: if ((scb->hscb->control & DISCENB) != 0)
! 3616: identify_msg |= MSG_IDENTIFY_DISCFLAG;
! 3617: ahd->msgout_buf[ahd->msgout_index++] = identify_msg;
! 3618: ahd->msgout_len++;
! 3619:
! 3620: if ((scb->hscb->control & TAG_ENB) != 0) {
! 3621: ahd->msgout_buf[ahd->msgout_index++] =
! 3622: scb->hscb->control & (TAG_ENB|SCB_TAG_TYPE);
! 3623: ahd->msgout_buf[ahd->msgout_index++] = SCB_GET_TAG(scb);
! 3624: ahd->msgout_len += 2;
! 3625: }
! 3626: }
! 3627:
! 3628: if (scb->flags & SCB_DEVICE_RESET) {
! 3629: ahd->msgout_buf[ahd->msgout_index++] = MSG_BUS_DEV_RESET;
! 3630: ahd->msgout_len++;
! 3631: ahd_print_path(ahd, scb);
! 3632: printf("Bus Device Reset Message Sent\n");
! 3633: /*
! 3634: * Clear our selection hardware in advance of
! 3635: * the busfree. We may have an entry in the waiting
! 3636: * Q for this target, and we don't want to go about
! 3637: * selecting while we handle the busfree and blow it
! 3638: * away.
! 3639: */
! 3640: ahd_outb(ahd, SCSISEQ0, 0);
! 3641: } else if ((scb->flags & SCB_ABORT) != 0) {
! 3642:
! 3643: if ((scb->hscb->control & TAG_ENB) != 0) {
! 3644: ahd->msgout_buf[ahd->msgout_index++] = MSG_ABORT_TAG;
! 3645: } else {
! 3646: ahd->msgout_buf[ahd->msgout_index++] = MSG_ABORT;
! 3647: }
! 3648: ahd->msgout_len++;
! 3649: ahd_print_path(ahd, scb);
! 3650: printf("Abort%s Message Sent\n",
! 3651: (scb->hscb->control & TAG_ENB) != 0 ? " Tag" : "");
! 3652: /*
! 3653: * Clear our selection hardware in advance of
! 3654: * the busfree. We may have an entry in the waiting
! 3655: * Q for this target, and we don't want to go about
! 3656: * selecting while we handle the busfree and blow it
! 3657: * away.
! 3658: */
! 3659: ahd_outb(ahd, SCSISEQ0, 0);
! 3660: } else if ((scb->flags & (SCB_AUTO_NEGOTIATE|SCB_NEGOTIATE)) != 0) {
! 3661: ahd_build_transfer_msg(ahd, devinfo);
! 3662: /*
! 3663: * Clear our selection hardware in advance of potential
! 3664: * PPR IU status change busfree. We may have an entry in
! 3665: * the waiting Q for this target, and we don't want to go
! 3666: * about selecting while we handle the busfree and blow
! 3667: * it away.
! 3668: */
! 3669: ahd_outb(ahd, SCSISEQ0, 0);
! 3670: } else {
! 3671: printf("ahd_intr: AWAITING_MSG for an SCB that "
! 3672: "does not have a waiting message\n");
! 3673: printf("SCSIID = %x, target_mask = %x\n", scb->hscb->scsiid,
! 3674: devinfo->target_mask);
! 3675: panic("SCB = %d, SCB Control = %x:%x, MSG_OUT = %x "
! 3676: "SCB flags = %x", SCB_GET_TAG(scb), scb->hscb->control,
! 3677: ahd_inb_scbram(ahd, SCB_CONTROL), ahd_inb(ahd, MSG_OUT),
! 3678: scb->flags);
! 3679: }
! 3680:
! 3681: /*
! 3682: * Clear the MK_MESSAGE flag from the SCB so we aren't
! 3683: * asked to send this message again.
! 3684: */
! 3685: ahd_outb(ahd, SCB_CONTROL,
! 3686: ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE);
! 3687: scb->hscb->control &= ~MK_MESSAGE;
! 3688: ahd->msgout_index = 0;
! 3689: ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
! 3690: }
! 3691:
! 3692: /*
! 3693: * Build an appropriate transfer negotiation message for the
! 3694: * currently active target.
! 3695: */
! 3696: void
! 3697: ahd_build_transfer_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
! 3698: {
! 3699: /*
! 3700: * We need to initiate transfer negotiations.
! 3701: * If our current and goal settings are identical,
! 3702: * we want to renegotiate due to a check condition.
! 3703: */
! 3704: struct ahd_initiator_tinfo *tinfo;
! 3705: struct ahd_tmode_tstate *tstate;
! 3706: int dowide;
! 3707: int dosync;
! 3708: int doppr;
! 3709: u_int period;
! 3710: u_int ppr_options;
! 3711: u_int offset;
! 3712:
! 3713: tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
! 3714: devinfo->target, &tstate);
! 3715: /*
! 3716: * Filter our period based on the current connection.
! 3717: * If we can't perform DT transfers on this segment (not in LVD
! 3718: * mode for instance), then our decision to issue a PPR message
! 3719: * may change.
! 3720: */
! 3721: period = tinfo->goal.period;
! 3722: offset = tinfo->goal.offset;
! 3723: ppr_options = tinfo->goal.ppr_options;
! 3724: /* Target initiated PPR is not allowed in the SCSI spec */
! 3725: if (devinfo->role == ROLE_TARGET)
! 3726: ppr_options = 0;
! 3727: ahd_devlimited_syncrate(ahd, tinfo, &period,
! 3728: &ppr_options, devinfo->role);
! 3729: dowide = tinfo->curr.width != tinfo->goal.width;
! 3730: dosync = tinfo->curr.offset != offset || tinfo->curr.period != period;
! 3731: /*
! 3732: * Only use PPR if we have options that need it, even if the device
! 3733: * claims to support it. There might be an expander in the way
! 3734: * that doesn't.
! 3735: */
! 3736: doppr = ppr_options != 0;
! 3737:
! 3738: if (!dowide && !dosync && !doppr) {
! 3739: dowide = tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT;
! 3740: dosync = tinfo->goal.offset != 0;
! 3741: }
! 3742:
! 3743: if (!dowide && !dosync && !doppr) {
! 3744: /*
! 3745: * Force async with a WDTR message if we have a wide bus,
! 3746: * or just issue an SDTR with a 0 offset.
! 3747: */
! 3748: if ((ahd->features & AHD_WIDE) != 0)
! 3749: dowide = 1;
! 3750: else
! 3751: dosync = 1;
! 3752:
! 3753: if (bootverbose) {
! 3754: ahd_print_devinfo(ahd, devinfo);
! 3755: printf("Ensuring async\n");
! 3756: }
! 3757: }
! 3758: /* Target initiated PPR is not allowed in the SCSI spec */
! 3759: if (devinfo->role == ROLE_TARGET)
! 3760: doppr = 0;
! 3761:
! 3762: /*
! 3763: * Both the PPR message and SDTR message require the
! 3764: * goal syncrate to be limited to what the target device
! 3765: * is capable of handling (based on whether an LVD->SE
! 3766: * expander is on the bus), so combine these two cases.
! 3767: * Regardless, guarantee that if we are using WDTR and SDTR
! 3768: * messages that WDTR comes first.
! 3769: */
! 3770: if (doppr || (dosync && !dowide)) {
! 3771:
! 3772: offset = tinfo->goal.offset;
! 3773: ahd_validate_offset(ahd, tinfo, period, &offset,
! 3774: doppr ? tinfo->goal.width
! 3775: : tinfo->curr.width,
! 3776: devinfo->role);
! 3777: if (doppr) {
! 3778: ahd_construct_ppr(ahd, devinfo, period, offset,
! 3779: tinfo->goal.width, ppr_options);
! 3780: } else {
! 3781: ahd_construct_sdtr(ahd, devinfo, period, offset);
! 3782: }
! 3783: } else {
! 3784: ahd_construct_wdtr(ahd, devinfo, tinfo->goal.width);
! 3785: }
! 3786: }
! 3787:
! 3788: /*
! 3789: * Build a synchronous negotiation message in our message
! 3790: * buffer based on the input parameters.
! 3791: */
! 3792: void
! 3793: ahd_construct_sdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
! 3794: u_int period, u_int offset)
! 3795: {
! 3796: if (offset == 0)
! 3797: period = AHD_ASYNC_XFER_PERIOD;
! 3798: ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED;
! 3799: ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR_LEN;
! 3800: ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR;
! 3801: ahd->msgout_buf[ahd->msgout_index++] = period;
! 3802: ahd->msgout_buf[ahd->msgout_index++] = offset;
! 3803: ahd->msgout_len += 5;
! 3804: if (bootverbose) {
! 3805: printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n",
! 3806: ahd_name(ahd), devinfo->channel, devinfo->target,
! 3807: devinfo->lun, period, offset);
! 3808: }
! 3809: }
! 3810:
! 3811: /*
! 3812: * Build a wide negotiateion message in our message
! 3813: * buffer based on the input parameters.
! 3814: */
! 3815: void
! 3816: ahd_construct_wdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
! 3817: u_int bus_width)
! 3818: {
! 3819: ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED;
! 3820: ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR_LEN;
! 3821: ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR;
! 3822: ahd->msgout_buf[ahd->msgout_index++] = bus_width;
! 3823: ahd->msgout_len += 4;
! 3824: if (bootverbose) {
! 3825: printf("(%s:%c:%d:%d): Sending WDTR %x\n",
! 3826: ahd_name(ahd), devinfo->channel, devinfo->target,
! 3827: devinfo->lun, bus_width);
! 3828: }
! 3829: }
! 3830:
! 3831: /*
! 3832: * Build a parallel protocol request message in our message
! 3833: * buffer based on the input parameters.
! 3834: */
! 3835: void
! 3836: ahd_construct_ppr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
! 3837: u_int period, u_int offset, u_int bus_width,
! 3838: u_int ppr_options)
! 3839: {
! 3840: /*
! 3841: * Always request precompensation from
! 3842: * the other target if we are running
! 3843: * at paced syncrates.
! 3844: */
! 3845: if (period <= AHD_SYNCRATE_PACED)
! 3846: ppr_options |= MSG_EXT_PPR_PCOMP_EN;
! 3847: if (offset == 0)
! 3848: period = AHD_ASYNC_XFER_PERIOD;
! 3849: ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED;
! 3850: ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR_LEN;
! 3851: ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR;
! 3852: ahd->msgout_buf[ahd->msgout_index++] = period;
! 3853: ahd->msgout_buf[ahd->msgout_index++] = 0;
! 3854: ahd->msgout_buf[ahd->msgout_index++] = offset;
! 3855: ahd->msgout_buf[ahd->msgout_index++] = bus_width;
! 3856: ahd->msgout_buf[ahd->msgout_index++] = ppr_options;
! 3857: ahd->msgout_len += 8;
! 3858: if (bootverbose) {
! 3859: printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, "
! 3860: "offset %x, ppr_options %x\n", ahd_name(ahd),
! 3861: devinfo->channel, devinfo->target, devinfo->lun,
! 3862: bus_width, period, offset, ppr_options);
! 3863: }
! 3864: }
! 3865:
! 3866: /*
! 3867: * Clear any active message state.
! 3868: */
! 3869: void
! 3870: ahd_clear_msg_state(struct ahd_softc *ahd)
! 3871: {
! 3872: ahd_mode_state saved_modes;
! 3873:
! 3874: saved_modes = ahd_save_modes(ahd);
! 3875: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 3876: ahd->send_msg_perror = 0;
! 3877: ahd->msg_flags = MSG_FLAG_NONE;
! 3878: ahd->msgout_len = 0;
! 3879: ahd->msgin_index = 0;
! 3880: ahd->msg_type = MSG_TYPE_NONE;
! 3881: if ((ahd_inb(ahd, SCSISIGO) & ATNO) != 0) {
! 3882: /*
! 3883: * The target didn't care to respond to our
! 3884: * message request, so clear ATN.
! 3885: */
! 3886: ahd_outb(ahd, CLRSINT1, CLRATNO);
! 3887: }
! 3888: ahd_outb(ahd, MSG_OUT, MSG_NOOP);
! 3889: ahd_outb(ahd, SEQ_FLAGS2,
! 3890: ahd_inb(ahd, SEQ_FLAGS2) & ~TARGET_MSG_PENDING);
! 3891: ahd_restore_modes(ahd, saved_modes);
! 3892: }
! 3893:
! 3894: /*
! 3895: * Manual message loop handler.
! 3896: */
! 3897: void
! 3898: ahd_handle_message_phase(struct ahd_softc *ahd)
! 3899: {
! 3900: struct ahd_devinfo devinfo;
! 3901: u_int bus_phase;
! 3902: int end_session;
! 3903:
! 3904: ahd_fetch_devinfo(ahd, &devinfo);
! 3905: end_session = FALSE;
! 3906: bus_phase = ahd_inb(ahd, LASTPHASE);
! 3907:
! 3908: if ((ahd_inb(ahd, LQISTAT2) & LQIPHASE_OUTPKT) != 0) {
! 3909: printf("LQIRETRY for LQIPHASE_OUTPKT\n");
! 3910: ahd_outb(ahd, LQCTL2, LQIRETRY);
! 3911: }
! 3912: reswitch:
! 3913: switch (ahd->msg_type) {
! 3914: case MSG_TYPE_INITIATOR_MSGOUT:
! 3915: {
! 3916: int lastbyte;
! 3917: int phasemis;
! 3918: int msgdone;
! 3919:
! 3920: if (ahd->msgout_len == 0 && ahd->send_msg_perror == 0)
! 3921: panic("HOST_MSG_LOOP interrupt with no active message");
! 3922:
! 3923: #ifdef AHD_DEBUG
! 3924: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
! 3925: ahd_print_devinfo(ahd, &devinfo);
! 3926: printf("INITIATOR_MSG_OUT");
! 3927: }
! 3928: #endif
! 3929: phasemis = bus_phase != P_MESGOUT;
! 3930: if (phasemis) {
! 3931: #ifdef AHD_DEBUG
! 3932: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
! 3933: printf(" PHASEMIS %s\n",
! 3934: ahd_lookup_phase_entry(bus_phase)
! 3935: ->phasemsg);
! 3936: }
! 3937: #endif
! 3938: if (bus_phase == P_MESGIN) {
! 3939: /*
! 3940: * Change gears and see if
! 3941: * this messages is of interest to
! 3942: * us or should be passed back to
! 3943: * the sequencer.
! 3944: */
! 3945: ahd_outb(ahd, CLRSINT1, CLRATNO);
! 3946: ahd->send_msg_perror = 0;
! 3947: ahd->msg_type = MSG_TYPE_INITIATOR_MSGIN;
! 3948: ahd->msgin_index = 0;
! 3949: goto reswitch;
! 3950: }
! 3951: end_session = TRUE;
! 3952: break;
! 3953: }
! 3954:
! 3955: if (ahd->send_msg_perror) {
! 3956: ahd_outb(ahd, CLRSINT1, CLRATNO);
! 3957: ahd_outb(ahd, CLRSINT1, CLRREQINIT);
! 3958: #ifdef AHD_DEBUG
! 3959: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
! 3960: printf(" byte 0x%x\n", ahd->send_msg_perror);
! 3961: #endif
! 3962: /*
! 3963: * If we are notifying the target of a CRC error
! 3964: * during packetized operations, the target is
! 3965: * within its rights to acknowledge our message
! 3966: * with a busfree.
! 3967: */
! 3968: if ((ahd->msg_flags & MSG_FLAG_PACKETIZED) != 0
! 3969: && ahd->send_msg_perror == MSG_INITIATOR_DET_ERR)
! 3970: ahd->msg_flags |= MSG_FLAG_EXPECT_IDE_BUSFREE;
! 3971:
! 3972: ahd_outb(ahd, RETURN_2, ahd->send_msg_perror);
! 3973: ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_WRITE);
! 3974: break;
! 3975: }
! 3976:
! 3977: msgdone = ahd->msgout_index == ahd->msgout_len;
! 3978: if (msgdone) {
! 3979: /*
! 3980: * The target has requested a retry.
! 3981: * Re-assert ATN, reset our message index to
! 3982: * 0, and try again.
! 3983: */
! 3984: ahd->msgout_index = 0;
! 3985: ahd_assert_atn(ahd);
! 3986: }
! 3987:
! 3988: lastbyte = ahd->msgout_index == (ahd->msgout_len - 1);
! 3989: if (lastbyte) {
! 3990: /* Last byte is signified by dropping ATN */
! 3991: ahd_outb(ahd, CLRSINT1, CLRATNO);
! 3992: }
! 3993:
! 3994: /*
! 3995: * Clear our interrupt status and present
! 3996: * the next byte on the bus.
! 3997: */
! 3998: ahd_outb(ahd, CLRSINT1, CLRREQINIT);
! 3999: #ifdef AHD_DEBUG
! 4000: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
! 4001: printf(" byte 0x%x\n",
! 4002: ahd->msgout_buf[ahd->msgout_index]);
! 4003: #endif
! 4004: ahd_outb(ahd, RETURN_2, ahd->msgout_buf[ahd->msgout_index++]);
! 4005: ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_WRITE);
! 4006: break;
! 4007: }
! 4008: case MSG_TYPE_INITIATOR_MSGIN:
! 4009: {
! 4010: int phasemis;
! 4011: int message_done;
! 4012:
! 4013: #ifdef AHD_DEBUG
! 4014: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
! 4015: ahd_print_devinfo(ahd, &devinfo);
! 4016: printf("INITIATOR_MSG_IN");
! 4017: }
! 4018: #endif
! 4019: phasemis = bus_phase != P_MESGIN;
! 4020: if (phasemis) {
! 4021: #ifdef AHD_DEBUG
! 4022: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
! 4023: printf(" PHASEMIS %s\n",
! 4024: ahd_lookup_phase_entry(bus_phase)
! 4025: ->phasemsg);
! 4026: }
! 4027: #endif
! 4028: ahd->msgin_index = 0;
! 4029: if (bus_phase == P_MESGOUT
! 4030: && (ahd->send_msg_perror != 0
! 4031: || (ahd->msgout_len != 0
! 4032: && ahd->msgout_index == 0))) {
! 4033: ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
! 4034: goto reswitch;
! 4035: }
! 4036: end_session = TRUE;
! 4037: break;
! 4038: }
! 4039:
! 4040: /* Pull the byte in without acking it */
! 4041: ahd->msgin_buf[ahd->msgin_index] = ahd_inb(ahd, SCSIBUS);
! 4042: #ifdef AHD_DEBUG
! 4043: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
! 4044: printf(" byte 0x%x\n",
! 4045: ahd->msgin_buf[ahd->msgin_index]);
! 4046: #endif
! 4047:
! 4048: message_done = ahd_parse_msg(ahd, &devinfo);
! 4049:
! 4050: if (message_done) {
! 4051: /*
! 4052: * Clear our incoming message buffer in case there
! 4053: * is another message following this one.
! 4054: */
! 4055: ahd->msgin_index = 0;
! 4056:
! 4057: /*
! 4058: * If this message illicited a response,
! 4059: * assert ATN so the target takes us to the
! 4060: * message out phase.
! 4061: */
! 4062: if (ahd->msgout_len != 0) {
! 4063: #ifdef AHD_DEBUG
! 4064: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {
! 4065: ahd_print_devinfo(ahd, &devinfo);
! 4066: printf("Asserting ATN for response\n");
! 4067: }
! 4068: #endif
! 4069: ahd_assert_atn(ahd);
! 4070: }
! 4071: } else
! 4072: ahd->msgin_index++;
! 4073:
! 4074: if (message_done == MSGLOOP_TERMINATED) {
! 4075: end_session = TRUE;
! 4076: } else {
! 4077: /* Ack the byte */
! 4078: ahd_outb(ahd, CLRSINT1, CLRREQINIT);
! 4079: ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_READ);
! 4080: }
! 4081: break;
! 4082: }
! 4083: case MSG_TYPE_TARGET_MSGIN:
! 4084: {
! 4085: int msgdone;
! 4086: int msgout_request;
! 4087:
! 4088: /*
! 4089: * By default, the message loop will continue.
! 4090: */
! 4091: ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
! 4092:
! 4093: if (ahd->msgout_len == 0)
! 4094: panic("Target MSGIN with no active message");
! 4095:
! 4096: /*
! 4097: * If we interrupted a mesgout session, the initiator
! 4098: * will not know this until our first REQ. So, we
! 4099: * only honor mesgout requests after we've sent our
! 4100: * first byte.
! 4101: */
! 4102: if ((ahd_inb(ahd, SCSISIGI) & ATNI) != 0
! 4103: && ahd->msgout_index > 0)
! 4104: msgout_request = TRUE;
! 4105: else
! 4106: msgout_request = FALSE;
! 4107:
! 4108: if (msgout_request) {
! 4109:
! 4110: /*
! 4111: * Change gears and see if
! 4112: * this messages is of interest to
! 4113: * us or should be passed back to
! 4114: * the sequencer.
! 4115: */
! 4116: ahd->msg_type = MSG_TYPE_TARGET_MSGOUT;
! 4117: ahd_outb(ahd, SCSISIGO, P_MESGOUT | BSYO);
! 4118: ahd->msgin_index = 0;
! 4119: /* Dummy read to REQ for first byte */
! 4120: ahd_inb(ahd, SCSIDAT);
! 4121: ahd_outb(ahd, SXFRCTL0,
! 4122: ahd_inb(ahd, SXFRCTL0) | SPIOEN);
! 4123: break;
! 4124: }
! 4125:
! 4126: msgdone = ahd->msgout_index == ahd->msgout_len;
! 4127: if (msgdone) {
! 4128: ahd_outb(ahd, SXFRCTL0,
! 4129: ahd_inb(ahd, SXFRCTL0) & ~SPIOEN);
! 4130: end_session = TRUE;
! 4131: break;
! 4132: }
! 4133:
! 4134: /*
! 4135: * Present the next byte on the bus.
! 4136: */
! 4137: ahd_outb(ahd, SXFRCTL0, ahd_inb(ahd, SXFRCTL0) | SPIOEN);
! 4138: ahd_outb(ahd, SCSIDAT, ahd->msgout_buf[ahd->msgout_index++]);
! 4139: break;
! 4140: }
! 4141: case MSG_TYPE_TARGET_MSGOUT:
! 4142: {
! 4143: int lastbyte;
! 4144: int msgdone;
! 4145:
! 4146: /*
! 4147: * By default, the message loop will continue.
! 4148: */
! 4149: ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
! 4150:
! 4151: /*
! 4152: * The initiator signals that this is
! 4153: * the last byte by dropping ATN.
! 4154: */
! 4155: lastbyte = (ahd_inb(ahd, SCSISIGI) & ATNI) == 0;
! 4156:
! 4157: /*
! 4158: * Read the latched byte, but turn off SPIOEN first
! 4159: * so that we don't inadvertently cause a REQ for the
! 4160: * next byte.
! 4161: */
! 4162: ahd_outb(ahd, SXFRCTL0, ahd_inb(ahd, SXFRCTL0) & ~SPIOEN);
! 4163: ahd->msgin_buf[ahd->msgin_index] = ahd_inb(ahd, SCSIDAT);
! 4164: msgdone = ahd_parse_msg(ahd, &devinfo);
! 4165: if (msgdone == MSGLOOP_TERMINATED) {
! 4166: /*
! 4167: * The message is *really* done in that it caused
! 4168: * us to go to bus free. The sequencer has already
! 4169: * been reset at this point, so pull the ejection
! 4170: * handle.
! 4171: */
! 4172: return;
! 4173: }
! 4174:
! 4175: ahd->msgin_index++;
! 4176:
! 4177: /*
! 4178: * XXX Read spec about initiator dropping ATN too soon
! 4179: * and use msgdone to detect it.
! 4180: */
! 4181: if (msgdone == MSGLOOP_MSGCOMPLETE) {
! 4182: ahd->msgin_index = 0;
! 4183:
! 4184: /*
! 4185: * If this message illicited a response, transition
! 4186: * to the Message in phase and send it.
! 4187: */
! 4188: if (ahd->msgout_len != 0) {
! 4189: ahd_outb(ahd, SCSISIGO, P_MESGIN | BSYO);
! 4190: ahd_outb(ahd, SXFRCTL0,
! 4191: ahd_inb(ahd, SXFRCTL0) | SPIOEN);
! 4192: ahd->msg_type = MSG_TYPE_TARGET_MSGIN;
! 4193: ahd->msgin_index = 0;
! 4194: break;
! 4195: }
! 4196: }
! 4197:
! 4198: if (lastbyte)
! 4199: end_session = TRUE;
! 4200: else {
! 4201: /* Ask for the next byte. */
! 4202: ahd_outb(ahd, SXFRCTL0,
! 4203: ahd_inb(ahd, SXFRCTL0) | SPIOEN);
! 4204: }
! 4205:
! 4206: break;
! 4207: }
! 4208: default:
! 4209: panic("Unknown REQINIT message type");
! 4210: }
! 4211:
! 4212: if (end_session) {
! 4213: if ((ahd->msg_flags & MSG_FLAG_PACKETIZED) != 0) {
! 4214: printf("%s: Returning to Idle Loop\n",
! 4215: ahd_name(ahd));
! 4216: ahd_clear_msg_state(ahd);
! 4217:
! 4218: /*
! 4219: * Perform the equivalent of a clear_target_state.
! 4220: */
! 4221: ahd_outb(ahd, LASTPHASE, P_BUSFREE);
! 4222: ahd_outb(ahd, SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT);
! 4223: ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);
! 4224: } else {
! 4225: ahd_clear_msg_state(ahd);
! 4226: ahd_outb(ahd, RETURN_1, EXIT_MSG_LOOP);
! 4227: }
! 4228: }
! 4229: }
! 4230:
! 4231: /*
! 4232: * See if we sent a particular extended message to the target.
! 4233: * If "full" is true, return true only if the target saw the full
! 4234: * message. If "full" is false, return true if the target saw at
! 4235: * least the first byte of the message.
! 4236: */
! 4237: int
! 4238: ahd_sent_msg(struct ahd_softc *ahd, ahd_msgtype type, u_int msgval, int full)
! 4239: {
! 4240: int found;
! 4241: u_int index;
! 4242:
! 4243: found = FALSE;
! 4244: index = 0;
! 4245:
! 4246: while (index < ahd->msgout_len) {
! 4247: if (ahd->msgout_buf[index] == MSG_EXTENDED) {
! 4248: u_int end_index;
! 4249:
! 4250: end_index = index + 1 + ahd->msgout_buf[index + 1];
! 4251: if (ahd->msgout_buf[index+2] == msgval
! 4252: && type == AHDMSG_EXT) {
! 4253:
! 4254: if (full) {
! 4255: if (ahd->msgout_index > end_index)
! 4256: found = TRUE;
! 4257: } else if (ahd->msgout_index > index)
! 4258: found = TRUE;
! 4259: }
! 4260: index = end_index;
! 4261: } else if (ahd->msgout_buf[index] >= MSG_SIMPLE_TASK
! 4262: && ahd->msgout_buf[index] <= MSG_IGN_WIDE_RESIDUE) {
! 4263:
! 4264: /* Skip tag type and tag id or residue param*/
! 4265: index += 2;
! 4266: } else {
! 4267: /* Single byte message */
! 4268: if (type == AHDMSG_1B
! 4269: && ahd->msgout_index > index
! 4270: && (ahd->msgout_buf[index] == msgval
! 4271: || ((ahd->msgout_buf[index] & MSG_IDENTIFYFLAG) != 0
! 4272: && msgval == MSG_IDENTIFYFLAG)))
! 4273: found = TRUE;
! 4274: index++;
! 4275: }
! 4276:
! 4277: if (found)
! 4278: break;
! 4279: }
! 4280: return (found);
! 4281: }
! 4282:
! 4283: /*
! 4284: * Wait for a complete incoming message, parse it, and respond accordingly.
! 4285: */
! 4286: int
! 4287: ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
! 4288: {
! 4289: struct ahd_initiator_tinfo *tinfo;
! 4290: struct ahd_tmode_tstate *tstate;
! 4291: int reject;
! 4292: int done;
! 4293: int response;
! 4294:
! 4295: done = MSGLOOP_IN_PROG;
! 4296: response = FALSE;
! 4297: reject = FALSE;
! 4298: tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
! 4299: devinfo->target, &tstate);
! 4300:
! 4301: /*
! 4302: * Parse as much of the message as is available,
! 4303: * rejecting it if we don't support it. When
! 4304: * the entire message is available and has been
! 4305: * handled, return MSGLOOP_MSGCOMPLETE, indicating
! 4306: * that we have parsed an entire message.
! 4307: *
! 4308: * In the case of extended messages, we accept the length
! 4309: * byte outright and perform more checking once we know the
! 4310: * extended message type.
! 4311: */
! 4312: switch (ahd->msgin_buf[0]) {
! 4313: case MSG_DISCONNECT:
! 4314: case MSG_SAVEDATAPOINTER:
! 4315: case MSG_CMDCOMPLETE:
! 4316: case MSG_RESTOREPOINTERS:
! 4317: case MSG_IGN_WIDE_RESIDUE:
! 4318: /*
! 4319: * End our message loop as these are messages
! 4320: * the sequencer handles on its own.
! 4321: */
! 4322: done = MSGLOOP_TERMINATED;
! 4323: break;
! 4324: case MSG_MESSAGE_REJECT:
! 4325: response = ahd_handle_msg_reject(ahd, devinfo);
! 4326: /* FALLTHROUGH */
! 4327: case MSG_NOOP:
! 4328: done = MSGLOOP_MSGCOMPLETE;
! 4329: break;
! 4330: case MSG_EXTENDED:
! 4331: {
! 4332: /* Wait for enough of the message to begin validation */
! 4333: if (ahd->msgin_index < 2)
! 4334: break;
! 4335: switch (ahd->msgin_buf[2]) {
! 4336: case MSG_EXT_SDTR:
! 4337: {
! 4338: u_int period;
! 4339: u_int ppr_options;
! 4340: u_int offset;
! 4341: u_int saved_offset;
! 4342:
! 4343: if (ahd->msgin_buf[1] != MSG_EXT_SDTR_LEN) {
! 4344: reject = TRUE;
! 4345: break;
! 4346: }
! 4347:
! 4348: /*
! 4349: * Wait until we have both args before validating
! 4350: * and acting on this message.
! 4351: *
! 4352: * Add one to MSG_EXT_SDTR_LEN to account for
! 4353: * the extended message preamble.
! 4354: */
! 4355: if (ahd->msgin_index < (MSG_EXT_SDTR_LEN + 1))
! 4356: break;
! 4357:
! 4358: period = ahd->msgin_buf[3];
! 4359: ppr_options = 0;
! 4360: saved_offset = offset = ahd->msgin_buf[4];
! 4361: ahd_devlimited_syncrate(ahd, tinfo, &period,
! 4362: &ppr_options, devinfo->role);
! 4363: ahd_validate_offset(ahd, tinfo, period, &offset,
! 4364: tinfo->curr.width, devinfo->role);
! 4365: if (bootverbose) {
! 4366: printf("(%s:%c:%d:%d): Received "
! 4367: "SDTR period %x, offset %x\n\t"
! 4368: "Filtered to period %x, offset %x\n",
! 4369: ahd_name(ahd), devinfo->channel,
! 4370: devinfo->target, devinfo->lun,
! 4371: ahd->msgin_buf[3], saved_offset,
! 4372: period, offset);
! 4373: }
! 4374: ahd_set_syncrate(ahd, devinfo, period,
! 4375: offset, ppr_options,
! 4376: AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
! 4377: /*paused*/TRUE);
! 4378:
! 4379: /*
! 4380: * See if we initiated Sync Negotiation
! 4381: * and didn't have to fall down to async
! 4382: * transfers.
! 4383: */
! 4384: if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, TRUE)) {
! 4385: /* We started it */
! 4386: if (saved_offset != offset) {
! 4387: /* Went too low - force async */
! 4388: reject = TRUE;
! 4389: }
! 4390: } else {
! 4391: /*
! 4392: * Send our own SDTR in reply
! 4393: */
! 4394: if (bootverbose
! 4395: && devinfo->role == ROLE_INITIATOR) {
! 4396: printf("(%s:%c:%d:%d): Target "
! 4397: "Initiated SDTR\n",
! 4398: ahd_name(ahd), devinfo->channel,
! 4399: devinfo->target, devinfo->lun);
! 4400: }
! 4401: ahd->msgout_index = 0;
! 4402: ahd->msgout_len = 0;
! 4403: ahd_construct_sdtr(ahd, devinfo,
! 4404: period, offset);
! 4405: ahd->msgout_index = 0;
! 4406: response = TRUE;
! 4407: }
! 4408: done = MSGLOOP_MSGCOMPLETE;
! 4409: break;
! 4410: }
! 4411: case MSG_EXT_WDTR:
! 4412: {
! 4413: u_int bus_width;
! 4414: u_int saved_width;
! 4415: u_int sending_reply;
! 4416:
! 4417: sending_reply = FALSE;
! 4418: if (ahd->msgin_buf[1] != MSG_EXT_WDTR_LEN) {
! 4419: reject = TRUE;
! 4420: break;
! 4421: }
! 4422:
! 4423: /*
! 4424: * Wait until we have our arg before validating
! 4425: * and acting on this message.
! 4426: *
! 4427: * Add one to MSG_EXT_WDTR_LEN to account for
! 4428: * the extended message preamble.
! 4429: */
! 4430: if (ahd->msgin_index < (MSG_EXT_WDTR_LEN + 1))
! 4431: break;
! 4432:
! 4433: bus_width = ahd->msgin_buf[3];
! 4434: saved_width = bus_width;
! 4435: ahd_validate_width(ahd, tinfo, &bus_width,
! 4436: devinfo->role);
! 4437: if (bootverbose) {
! 4438: printf("(%s:%c:%d:%d): Received WDTR "
! 4439: "%x filtered to %x\n",
! 4440: ahd_name(ahd), devinfo->channel,
! 4441: devinfo->target, devinfo->lun,
! 4442: saved_width, bus_width);
! 4443: }
! 4444:
! 4445: if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, TRUE)) {
! 4446: /*
! 4447: * Don't send a WDTR back to the
! 4448: * target, since we asked first.
! 4449: * If the width went higher than our
! 4450: * request, reject it.
! 4451: */
! 4452: if (saved_width > bus_width) {
! 4453: reject = TRUE;
! 4454: printf("(%s:%c:%d:%d): requested %dBit "
! 4455: "transfers. Rejecting...\n",
! 4456: ahd_name(ahd), devinfo->channel,
! 4457: devinfo->target, devinfo->lun,
! 4458: 8 * (0x01 << bus_width));
! 4459: bus_width = 0;
! 4460: }
! 4461: } else {
! 4462: /*
! 4463: * Send our own WDTR in reply
! 4464: */
! 4465: if (bootverbose
! 4466: && devinfo->role == ROLE_INITIATOR) {
! 4467: printf("(%s:%c:%d:%d): Target "
! 4468: "Initiated WDTR\n",
! 4469: ahd_name(ahd), devinfo->channel,
! 4470: devinfo->target, devinfo->lun);
! 4471: }
! 4472: ahd->msgout_index = 0;
! 4473: ahd->msgout_len = 0;
! 4474: ahd_construct_wdtr(ahd, devinfo, bus_width);
! 4475: ahd->msgout_index = 0;
! 4476: response = TRUE;
! 4477: sending_reply = TRUE;
! 4478: }
! 4479: /*
! 4480: * After a wide message, we are async, but
! 4481: * some devices don't seem to honor this portion
! 4482: * of the spec. Force a renegotiation of the
! 4483: * sync component of our transfer agreement even
! 4484: * if our goal is async. By updating our width
! 4485: * after forcing the negotiation, we avoid
! 4486: * renegotiating for width.
! 4487: */
! 4488: ahd_update_neg_request(ahd, devinfo, tstate,
! 4489: tinfo, AHD_NEG_ALWAYS);
! 4490: ahd_set_width(ahd, devinfo, bus_width,
! 4491: AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
! 4492: /*paused*/TRUE);
! 4493: if (sending_reply == FALSE && reject == FALSE) {
! 4494:
! 4495: /*
! 4496: * We will always have an SDTR to send.
! 4497: */
! 4498: ahd->msgout_index = 0;
! 4499: ahd->msgout_len = 0;
! 4500: ahd_build_transfer_msg(ahd, devinfo);
! 4501: ahd->msgout_index = 0;
! 4502: response = TRUE;
! 4503: }
! 4504: done = MSGLOOP_MSGCOMPLETE;
! 4505: break;
! 4506: }
! 4507: case MSG_EXT_PPR:
! 4508: {
! 4509: u_int period;
! 4510: u_int offset;
! 4511: u_int bus_width;
! 4512: u_int ppr_options;
! 4513: u_int saved_width;
! 4514: u_int saved_offset;
! 4515: u_int saved_ppr_options;
! 4516:
! 4517: if (ahd->msgin_buf[1] != MSG_EXT_PPR_LEN) {
! 4518: reject = TRUE;
! 4519: break;
! 4520: }
! 4521:
! 4522: /*
! 4523: * Wait until we have all args before validating
! 4524: * and acting on this message.
! 4525: *
! 4526: * Add one to MSG_EXT_PPR_LEN to account for
! 4527: * the extended message preamble.
! 4528: */
! 4529: if (ahd->msgin_index < (MSG_EXT_PPR_LEN + 1))
! 4530: break;
! 4531:
! 4532: period = ahd->msgin_buf[3];
! 4533: offset = ahd->msgin_buf[5];
! 4534: bus_width = ahd->msgin_buf[6];
! 4535: saved_width = bus_width;
! 4536: ppr_options = ahd->msgin_buf[7];
! 4537: /*
! 4538: * According to the spec, a DT only
! 4539: * period factor with no DT option
! 4540: * set implies async.
! 4541: */
! 4542: if ((ppr_options & MSG_EXT_PPR_DT_REQ) == 0
! 4543: && period <= 9)
! 4544: offset = 0;
! 4545: saved_ppr_options = ppr_options;
! 4546: saved_offset = offset;
! 4547:
! 4548: /*
! 4549: * Transfer options are only available if we
! 4550: * are negotiating wide.
! 4551: */
! 4552: if (bus_width == 0)
! 4553: ppr_options &= MSG_EXT_PPR_QAS_REQ;
! 4554:
! 4555: ahd_validate_width(ahd, tinfo, &bus_width,
! 4556: devinfo->role);
! 4557: ahd_devlimited_syncrate(ahd, tinfo, &period,
! 4558: &ppr_options, devinfo->role);
! 4559: ahd_validate_offset(ahd, tinfo, period, &offset,
! 4560: bus_width, devinfo->role);
! 4561:
! 4562: if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, TRUE)) {
! 4563: /*
! 4564: * If we are unable to do any of the
! 4565: * requested options (we went too low),
! 4566: * then we'll have to reject the message.
! 4567: */
! 4568: if (saved_width > bus_width
! 4569: || saved_offset != offset
! 4570: || saved_ppr_options != ppr_options) {
! 4571: reject = TRUE;
! 4572: period = 0;
! 4573: offset = 0;
! 4574: bus_width = 0;
! 4575: ppr_options = 0;
! 4576: }
! 4577: } else {
! 4578: if (devinfo->role != ROLE_TARGET)
! 4579: printf("(%s:%c:%d:%d): Target "
! 4580: "Initiated PPR\n",
! 4581: ahd_name(ahd), devinfo->channel,
! 4582: devinfo->target, devinfo->lun);
! 4583: else
! 4584: printf("(%s:%c:%d:%d): Initiator "
! 4585: "Initiated PPR\n",
! 4586: ahd_name(ahd), devinfo->channel,
! 4587: devinfo->target, devinfo->lun);
! 4588: ahd->msgout_index = 0;
! 4589: ahd->msgout_len = 0;
! 4590: ahd_construct_ppr(ahd, devinfo, period, offset,
! 4591: bus_width, ppr_options);
! 4592: ahd->msgout_index = 0;
! 4593: response = TRUE;
! 4594: }
! 4595: if (bootverbose) {
! 4596: printf("(%s:%c:%d:%d): Received PPR width %x, "
! 4597: "period %x, offset %x,options %x\n"
! 4598: "\tFiltered to width %x, period %x, "
! 4599: "offset %x, options %x\n",
! 4600: ahd_name(ahd), devinfo->channel,
! 4601: devinfo->target, devinfo->lun,
! 4602: saved_width, ahd->msgin_buf[3],
! 4603: saved_offset, saved_ppr_options,
! 4604: bus_width, period, offset, ppr_options);
! 4605: }
! 4606: ahd_set_width(ahd, devinfo, bus_width,
! 4607: AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
! 4608: /*paused*/TRUE);
! 4609: ahd_set_syncrate(ahd, devinfo, period,
! 4610: offset, ppr_options,
! 4611: AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
! 4612: /*paused*/TRUE);
! 4613:
! 4614: done = MSGLOOP_MSGCOMPLETE;
! 4615: break;
! 4616: }
! 4617: default:
! 4618: /* Unknown extended message. Reject it. */
! 4619: reject = TRUE;
! 4620: break;
! 4621: }
! 4622: break;
! 4623: }
! 4624: #ifdef AHD_TARGET_MODE
! 4625: case MSG_BUS_DEV_RESET:
! 4626: ahd_handle_devreset(ahd, devinfo, CAM_LUN_WILDCARD,
! 4627: CAM_BDR_SENT,
! 4628: "Bus Device Reset Received",
! 4629: /*verbose_level*/0);
! 4630: ahd_restart(ahd);
! 4631: done = MSGLOOP_TERMINATED;
! 4632: break;
! 4633: case MSG_ABORT_TAG:
! 4634: case MSG_ABORT:
! 4635: case MSG_CLEAR_QUEUE:
! 4636: {
! 4637: int tag;
! 4638:
! 4639: /* Target mode messages */
! 4640: if (devinfo->role != ROLE_TARGET) {
! 4641: reject = TRUE;
! 4642: break;
! 4643: }
! 4644: tag = SCB_LIST_NULL;
! 4645: if (ahd->msgin_buf[0] == MSG_ABORT_TAG)
! 4646: tag = ahd_inb(ahd, INITIATOR_TAG);
! 4647: ahd_abort_scbs(ahd, devinfo->target, devinfo->channel,
! 4648: devinfo->lun, tag, ROLE_TARGET,
! 4649: CAM_REQ_ABORTED);
! 4650:
! 4651: tstate = ahd->enabled_targets[devinfo->our_scsiid];
! 4652: if (tstate != NULL) {
! 4653: struct ahd_tmode_lstate* lstate;
! 4654:
! 4655: lstate = tstate->enabled_luns[devinfo->lun];
! 4656: if (lstate != NULL) {
! 4657: ahd_queue_lstate_event(ahd, lstate,
! 4658: devinfo->our_scsiid,
! 4659: ahd->msgin_buf[0],
! 4660: /*arg*/tag);
! 4661: ahd_send_lstate_events(ahd, lstate);
! 4662: }
! 4663: }
! 4664: ahd_restart(ahd);
! 4665: done = MSGLOOP_TERMINATED;
! 4666: break;
! 4667: }
! 4668: #endif
! 4669: case MSG_QAS_REQUEST:
! 4670: #ifdef AHD_DEBUG
! 4671: if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)
! 4672: printf("%s: QAS request. SCSISIGI == 0x%x\n",
! 4673: ahd_name(ahd), ahd_inb(ahd, SCSISIGI));
! 4674: #endif
! 4675: ahd->msg_flags |= MSG_FLAG_EXPECT_QASREJ_BUSFREE;
! 4676: /* FALLTHROUGH */
! 4677: case MSG_TERM_IO_PROC:
! 4678: default:
! 4679: reject = TRUE;
! 4680: break;
! 4681: }
! 4682:
! 4683: if (reject) {
! 4684: /*
! 4685: * Setup to reject the message.
! 4686: */
! 4687: ahd->msgout_index = 0;
! 4688: ahd->msgout_len = 1;
! 4689: ahd->msgout_buf[0] = MSG_MESSAGE_REJECT;
! 4690: done = MSGLOOP_MSGCOMPLETE;
! 4691: response = TRUE;
! 4692: }
! 4693:
! 4694: if (done != MSGLOOP_IN_PROG && !response)
! 4695: /* Clear the outgoing message buffer */
! 4696: ahd->msgout_len = 0;
! 4697:
! 4698: return (done);
! 4699: }
! 4700:
! 4701: /*
! 4702: * Process a message reject message.
! 4703: */
! 4704: int
! 4705: ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
! 4706: {
! 4707: /*
! 4708: * What we care about here is if we had an
! 4709: * outstanding SDTR or WDTR message for this
! 4710: * target. If we did, this is a signal that
! 4711: * the target is refusing negotiation.
! 4712: */
! 4713: struct scb *scb;
! 4714: struct ahd_initiator_tinfo *tinfo;
! 4715: struct ahd_tmode_tstate *tstate;
! 4716: u_int scb_index;
! 4717: u_int last_msg;
! 4718: int response = 0;
! 4719:
! 4720: scb_index = ahd_get_scbptr(ahd);
! 4721: scb = ahd_lookup_scb(ahd, scb_index);
! 4722: tinfo = ahd_fetch_transinfo(ahd, devinfo->channel,
! 4723: devinfo->our_scsiid,
! 4724: devinfo->target, &tstate);
! 4725: /* Might be necessary */
! 4726: last_msg = ahd_inb(ahd, LAST_MSG);
! 4727:
! 4728: if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, /*full*/FALSE)) {
! 4729: if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_PPR, /*full*/TRUE)
! 4730: && tinfo->goal.period <= AHD_SYNCRATE_PACED) {
! 4731: /*
! 4732: * Target may not like our SPI-4 PPR Options.
! 4733: * Attempt to negotiate 80MHz which will turn
! 4734: * off these options.
! 4735: */
! 4736: if (bootverbose) {
! 4737: printf("(%s:%c:%d:%d): PPR Rejected. "
! 4738: "Trying simple U160 PPR\n",
! 4739: ahd_name(ahd), devinfo->channel,
! 4740: devinfo->target, devinfo->lun);
! 4741: }
! 4742: tinfo->goal.period = AHD_SYNCRATE_DT;
! 4743: tinfo->goal.ppr_options &= MSG_EXT_PPR_IU_REQ
! 4744: | MSG_EXT_PPR_QAS_REQ
! 4745: | MSG_EXT_PPR_DT_REQ;
! 4746: } else {
! 4747: /*
! 4748: * Target does not support the PPR message.
! 4749: * Attempt to negotiate SPI-2 style.
! 4750: */
! 4751: if (bootverbose) {
! 4752: printf("(%s:%c:%d:%d): PPR Rejected. "
! 4753: "Trying WDTR/SDTR\n",
! 4754: ahd_name(ahd), devinfo->channel,
! 4755: devinfo->target, devinfo->lun);
! 4756: }
! 4757: tinfo->goal.ppr_options = 0;
! 4758: tinfo->curr.transport_version = 2;
! 4759: tinfo->goal.transport_version = 2;
! 4760: }
! 4761: ahd->msgout_index = 0;
! 4762: ahd->msgout_len = 0;
! 4763: ahd_build_transfer_msg(ahd, devinfo);
! 4764: ahd->msgout_index = 0;
! 4765: response = 1;
! 4766: } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, /*full*/FALSE)) {
! 4767:
! 4768: /* note 8bit xfers */
! 4769: printf("(%s:%c:%d:%d): refuses WIDE negotiation. Using "
! 4770: "8bit transfers\n", ahd_name(ahd),
! 4771: devinfo->channel, devinfo->target, devinfo->lun);
! 4772: ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT,
! 4773: AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
! 4774: /*paused*/TRUE);
! 4775: /*
! 4776: * No need to clear the sync rate. If the target
! 4777: * did not accept the command, our syncrate is
! 4778: * unaffected. If the target started the negotiation,
! 4779: * but rejected our response, we already cleared the
! 4780: * sync rate before sending our WDTR.
! 4781: */
! 4782: if (tinfo->goal.offset != tinfo->curr.offset) {
! 4783:
! 4784: /* Start the sync negotiation */
! 4785: ahd->msgout_index = 0;
! 4786: ahd->msgout_len = 0;
! 4787: ahd_build_transfer_msg(ahd, devinfo);
! 4788: ahd->msgout_index = 0;
! 4789: response = 1;
! 4790: }
! 4791: } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, /*full*/FALSE)) {
! 4792: /* note asynch xfers and clear flag */
! 4793: ahd_set_syncrate(ahd, devinfo, /*period*/0,
! 4794: /*offset*/0, /*ppr_options*/0,
! 4795: AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,
! 4796: /*paused*/TRUE);
! 4797: printf("(%s:%c:%d:%d): refuses synchronous negotiation. "
! 4798: "Using asynchronous transfers\n",
! 4799: ahd_name(ahd), devinfo->channel,
! 4800: devinfo->target, devinfo->lun);
! 4801: } else if ((scb->hscb->control & MSG_SIMPLE_TASK) != 0) {
! 4802: int tag_type;
! 4803: int mask;
! 4804:
! 4805: tag_type = (scb->hscb->control & MSG_SIMPLE_TASK);
! 4806:
! 4807: if (tag_type == MSG_SIMPLE_TASK) {
! 4808: printf("(%s:%c:%d:%d): refuses tagged commands. "
! 4809: "Performing non-tagged I/O\n", ahd_name(ahd),
! 4810: devinfo->channel, devinfo->target, devinfo->lun);
! 4811: ahd_set_tags(ahd, devinfo, AHD_QUEUE_NONE);
! 4812: mask = ~0x23;
! 4813: } else {
! 4814: printf("(%s:%c:%d:%d): refuses %s tagged commands. "
! 4815: "Performing simple queue tagged I/O only\n",
! 4816: ahd_name(ahd), devinfo->channel, devinfo->target,
! 4817: devinfo->lun, tag_type == MSG_ORDERED_TASK
! 4818: ? "ordered" : "head of queue");
! 4819: ahd_set_tags(ahd, devinfo, AHD_QUEUE_BASIC);
! 4820: mask = ~0x03;
! 4821: }
! 4822:
! 4823: /*
! 4824: * Resend the identify for this CCB as the target
! 4825: * may believe that the selection is invalid otherwise.
! 4826: */
! 4827: ahd_outb(ahd, SCB_CONTROL,
! 4828: ahd_inb_scbram(ahd, SCB_CONTROL) & mask);
! 4829: scb->hscb->control &= mask;
! 4830: aic_set_transaction_tag(scb, /*enabled*/FALSE,
! 4831: /*type*/MSG_SIMPLE_TASK);
! 4832: ahd_outb(ahd, MSG_OUT, MSG_IDENTIFYFLAG);
! 4833: ahd_assert_atn(ahd);
! 4834: ahd_busy_tcl(ahd, BUILD_TCL(scb->hscb->scsiid, devinfo->lun),
! 4835: SCB_GET_TAG(scb));
! 4836:
! 4837: /*
! 4838: * Requeue all tagged commands for this target
! 4839: * currently in our posession so they can be
! 4840: * converted to untagged commands.
! 4841: */
! 4842: ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),
! 4843: SCB_GET_CHANNEL(ahd, scb),
! 4844: SCB_GET_LUN(scb), /*tag*/SCB_LIST_NULL,
! 4845: ROLE_INITIATOR, CAM_REQUEUE_REQ,
! 4846: SEARCH_COMPLETE);
! 4847: } else if (ahd_sent_msg(ahd, AHDMSG_1B, MSG_IDENTIFYFLAG, TRUE)) {
! 4848: /*
! 4849: * Most likely the device believes that we had
! 4850: * previously negotiated packetized.
! 4851: */
! 4852: ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE
! 4853: | MSG_FLAG_IU_REQ_CHANGED;
! 4854:
! 4855: ahd_force_renegotiation(ahd, devinfo);
! 4856: ahd->msgout_index = 0;
! 4857: ahd->msgout_len = 0;
! 4858: ahd_build_transfer_msg(ahd, devinfo);
! 4859: ahd->msgout_index = 0;
! 4860: response = 1;
! 4861: } else {
! 4862: /*
! 4863: * Otherwise, we ignore it.
! 4864: */
! 4865: printf("%s:%c:%d: Message reject for %x -- ignored\n",
! 4866: ahd_name(ahd), devinfo->channel, devinfo->target,
! 4867: last_msg);
! 4868: }
! 4869: return (response);
! 4870: }
! 4871:
! 4872: /*
! 4873: * Process an ingnore wide residue message.
! 4874: */
! 4875: void
! 4876: ahd_handle_ign_wide_residue(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
! 4877: {
! 4878: u_int scb_index;
! 4879: struct scb *scb;
! 4880:
! 4881: scb_index = ahd_get_scbptr(ahd);
! 4882: scb = ahd_lookup_scb(ahd, scb_index);
! 4883: /*
! 4884: * XXX Actually check data direction in the sequencer?
! 4885: * Perhaps add datadir to some spare bits in the hscb?
! 4886: */
! 4887: if ((ahd_inb(ahd, SEQ_FLAGS) & DPHASE) == 0
! 4888: || aic_get_transfer_dir(scb) != CAM_DIR_IN) {
! 4889: /*
! 4890: * Ignore the message if we haven't
! 4891: * seen an appropriate data phase yet.
! 4892: */
! 4893: } else {
! 4894: /*
! 4895: * If the residual occurred on the last
! 4896: * transfer and the transfer request was
! 4897: * expected to end on an odd count, do
! 4898: * nothing. Otherwise, subtract a byte
! 4899: * and update the residual count accordingly.
! 4900: */
! 4901: uint32_t sgptr;
! 4902:
! 4903: sgptr = ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR);
! 4904: if ((sgptr & SG_LIST_NULL) != 0
! 4905: && (ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE)
! 4906: & SCB_XFERLEN_ODD) != 0) {
! 4907: /*
! 4908: * If the residual occurred on the last
! 4909: * transfer and the transfer request was
! 4910: * expected to end on an odd count, do
! 4911: * nothing.
! 4912: */
! 4913: } else {
! 4914: uint32_t data_cnt;
! 4915: uint64_t data_addr;
! 4916: uint32_t sglen;
! 4917:
! 4918: /* Pull in the rest of the sgptr */
! 4919: sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
! 4920: data_cnt = ahd_inl_scbram(ahd, SCB_RESIDUAL_DATACNT);
! 4921: if ((sgptr & SG_LIST_NULL) != 0) {
! 4922: /*
! 4923: * The residual data count is not updated
! 4924: * for the command run to completion case.
! 4925: * Explicitly zero the count.
! 4926: */
! 4927: data_cnt &= ~AHD_SG_LEN_MASK;
! 4928: }
! 4929: data_addr = ahd_inq(ahd, SHADDR);
! 4930: data_cnt += 1;
! 4931: data_addr -= 1;
! 4932: sgptr &= SG_PTR_MASK;
! 4933: if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
! 4934: struct ahd_dma64_seg *sg;
! 4935:
! 4936: sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
! 4937:
! 4938: /*
! 4939: * The residual sg ptr points to the next S/G
! 4940: * to load so we must go back one.
! 4941: */
! 4942: sg--;
! 4943: sglen = aic_le32toh(sg->len) & AHD_SG_LEN_MASK;
! 4944: if (sg != scb->sg_list
! 4945: && sglen < (data_cnt & AHD_SG_LEN_MASK)) {
! 4946:
! 4947: sg--;
! 4948: sglen = aic_le32toh(sg->len);
! 4949: /*
! 4950: * Preserve High Address and SG_LIST
! 4951: * bits while setting the count to 1.
! 4952: */
! 4953: data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK));
! 4954: data_addr = aic_le64toh(sg->addr)
! 4955: + (sglen & AHD_SG_LEN_MASK)
! 4956: - 1;
! 4957:
! 4958: /*
! 4959: * Increment sg so it points to the
! 4960: * "next" sg.
! 4961: */
! 4962: sg++;
! 4963: sgptr = ahd_sg_virt_to_bus(ahd, scb,
! 4964: sg);
! 4965: }
! 4966: } else {
! 4967: struct ahd_dma_seg *sg;
! 4968:
! 4969: sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
! 4970:
! 4971: /*
! 4972: * The residual sg ptr points to the next S/G
! 4973: * to load so we must go back one.
! 4974: */
! 4975: sg--;
! 4976: sglen = aic_le32toh(sg->len) & AHD_SG_LEN_MASK;
! 4977: if (sg != scb->sg_list
! 4978: && sglen < (data_cnt & AHD_SG_LEN_MASK)) {
! 4979:
! 4980: sg--;
! 4981: sglen = aic_le32toh(sg->len);
! 4982: /*
! 4983: * Preserve High Address and SG_LIST
! 4984: * bits while setting the count to 1.
! 4985: */
! 4986: data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK));
! 4987: data_addr = aic_le32toh(sg->addr)
! 4988: + (sglen & AHD_SG_LEN_MASK)
! 4989: - 1;
! 4990:
! 4991: /*
! 4992: * Increment sg so it points to the
! 4993: * "next" sg.
! 4994: */
! 4995: sg++;
! 4996: sgptr = ahd_sg_virt_to_bus(ahd, scb,
! 4997: sg);
! 4998: }
! 4999: }
! 5000: /*
! 5001: * Toggle the "oddness" of the transfer length
! 5002: * to handle this mid-transfer ignore wide
! 5003: * residue. This ensures that the oddness is
! 5004: * correct for subsequent data transfers.
! 5005: */
! 5006: ahd_outb(ahd, SCB_TASK_ATTRIBUTE,
! 5007: ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE)
! 5008: ^ SCB_XFERLEN_ODD);
! 5009:
! 5010: ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
! 5011: ahd_outl(ahd, SCB_RESIDUAL_DATACNT, data_cnt);
! 5012: /*
! 5013: * The FIFO's pointers will be updated if/when the
! 5014: * sequencer re-enters a data phase.
! 5015: */
! 5016: }
! 5017: }
! 5018: }
! 5019:
! 5020:
! 5021: /*
! 5022: * Reinitialize the data pointers for the active transfer
! 5023: * based on its current residual.
! 5024: */
! 5025: void
! 5026: ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
! 5027: {
! 5028: struct scb *scb;
! 5029: ahd_mode_state saved_modes;
! 5030: u_int scb_index;
! 5031: u_int wait;
! 5032: uint32_t sgptr;
! 5033: uint32_t resid;
! 5034: uint64_t dataptr;
! 5035:
! 5036: AHD_ASSERT_MODES(ahd, AHD_MODE_DFF0_MSK|AHD_MODE_DFF1_MSK,
! 5037: AHD_MODE_DFF0_MSK|AHD_MODE_DFF1_MSK);
! 5038:
! 5039: scb_index = ahd_get_scbptr(ahd);
! 5040: scb = ahd_lookup_scb(ahd, scb_index);
! 5041:
! 5042: /*
! 5043: * Release and reacquire the FIFO so we
! 5044: * have a clean slate.
! 5045: */
! 5046: ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
! 5047: wait = 1000;
! 5048: while (--wait && !(ahd_inb(ahd, MDFFSTAT) & FIFOFREE))
! 5049: aic_delay(100);
! 5050: if (wait == 0) {
! 5051: ahd_print_path(ahd, scb);
! 5052: printf("ahd_reinitialize_dataptrs: Forcing FIFO free.\n");
! 5053: ahd_outb(ahd, DFFSXFRCTL, RSTCHN|CLRSHCNT);
! 5054: }
! 5055: saved_modes = ahd_save_modes(ahd);
! 5056: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 5057: ahd_outb(ahd, DFFSTAT,
! 5058: ahd_inb(ahd, DFFSTAT)
! 5059: | (saved_modes == 0x11 ? CURRFIFO_1 : CURRFIFO_0));
! 5060:
! 5061: /*
! 5062: * Determine initial values for data_addr and data_cnt
! 5063: * for resuming the data phase.
! 5064: */
! 5065: sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
! 5066: sgptr &= SG_PTR_MASK;
! 5067:
! 5068: resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16)
! 5069: | (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 1) << 8)
! 5070: | ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT);
! 5071:
! 5072: if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
! 5073: struct ahd_dma64_seg *sg;
! 5074:
! 5075: sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
! 5076:
! 5077: /* The residual sg_ptr always points to the next sg */
! 5078: sg--;
! 5079:
! 5080: dataptr = aic_le64toh(sg->addr)
! 5081: + (aic_le32toh(sg->len) & AHD_SG_LEN_MASK)
! 5082: - resid;
! 5083: ahd_outl(ahd, HADDR + 4, dataptr >> 32);
! 5084: } else {
! 5085: struct ahd_dma_seg *sg;
! 5086:
! 5087: sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);
! 5088:
! 5089: /* The residual sg_ptr always points to the next sg */
! 5090: sg--;
! 5091:
! 5092: dataptr = aic_le32toh(sg->addr)
! 5093: + (aic_le32toh(sg->len) & AHD_SG_LEN_MASK)
! 5094: - resid;
! 5095: ahd_outb(ahd, HADDR + 4,
! 5096: (aic_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24);
! 5097: }
! 5098: ahd_outl(ahd, HADDR, dataptr);
! 5099: ahd_outb(ahd, HCNT + 2, resid >> 16);
! 5100: ahd_outb(ahd, HCNT + 1, resid >> 8);
! 5101: ahd_outb(ahd, HCNT, resid);
! 5102: }
! 5103:
! 5104: /*
! 5105: * Handle the effects of issuing a bus device reset message.
! 5106: */
! 5107: void
! 5108: ahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
! 5109: u_int lun, cam_status status, char *message,
! 5110: int verbose_level)
! 5111: {
! 5112: #ifdef AHD_TARGET_MODE
! 5113: struct ahd_tmode_tstate* tstate;
! 5114: #endif
! 5115: int found;
! 5116:
! 5117: found = ahd_abort_scbs(ahd, devinfo->target, devinfo->channel,
! 5118: lun, SCB_LIST_NULL, devinfo->role,
! 5119: status);
! 5120:
! 5121: #ifdef AHD_TARGET_MODE
! 5122: /*
! 5123: * Send an immediate notify ccb to all target mord peripheral
! 5124: * drivers affected by this action.
! 5125: */
! 5126: tstate = ahd->enabled_targets[devinfo->our_scsiid];
! 5127: if (tstate != NULL) {
! 5128: u_int cur_lun;
! 5129: u_int max_lun;
! 5130:
! 5131: if (lun != CAM_LUN_WILDCARD) {
! 5132: cur_lun = 0;
! 5133: max_lun = AHD_NUM_LUNS - 1;
! 5134: } else {
! 5135: cur_lun = lun;
! 5136: max_lun = lun;
! 5137: }
! 5138: for (cur_lun <= max_lun; cur_lun++) {
! 5139: struct ahd_tmode_lstate* lstate;
! 5140:
! 5141: lstate = tstate->enabled_luns[cur_lun];
! 5142: if (lstate == NULL)
! 5143: continue;
! 5144:
! 5145: ahd_queue_lstate_event(ahd, lstate, devinfo->our_scsiid,
! 5146: MSG_BUS_DEV_RESET, /*arg*/0);
! 5147: ahd_send_lstate_events(ahd, lstate);
! 5148: }
! 5149: }
! 5150: #endif
! 5151:
! 5152: /*
! 5153: * Go back to async/narrow transfers and renegotiate.
! 5154: */
! 5155: ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT,
! 5156: AHD_TRANS_CUR, /*paused*/TRUE);
! 5157: ahd_set_syncrate(ahd, devinfo, /*period*/0, /*offset*/0,
! 5158: /*ppr_options*/0, AHD_TRANS_CUR,
! 5159: /*paused*/TRUE);
! 5160:
! 5161: #if 0
! 5162: if (status != CAM_SEL_TIMEOUT)
! 5163: ahd_send_async(ahd, devinfo->channel, devinfo->target,
! 5164: lun, AC_SENT_BDR, NULL);
! 5165: #endif
! 5166:
! 5167: if (message != NULL
! 5168: && (verbose_level <= bootverbose))
! 5169: printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd),
! 5170: message, devinfo->channel, devinfo->target, found);
! 5171: }
! 5172:
! 5173: #ifdef AHD_TARGET_MODE
! 5174: void
! 5175: ahd_setup_target_msgin(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
! 5176: struct scb *scb)
! 5177: {
! 5178:
! 5179: /*
! 5180: * To facilitate adding multiple messages together,
! 5181: * each routine should increment the index and len
! 5182: * variables instead of setting them explicitly.
! 5183: */
! 5184: ahd->msgout_index = 0;
! 5185: ahd->msgout_len = 0;
! 5186:
! 5187: if (scb != NULL && (scb->flags & SCB_AUTO_NEGOTIATE) != 0)
! 5188: ahd_build_transfer_msg(ahd, devinfo);
! 5189: else
! 5190: panic("ahd_intr: AWAITING target message with no message");
! 5191:
! 5192: ahd->msgout_index = 0;
! 5193: ahd->msg_type = MSG_TYPE_TARGET_MSGIN;
! 5194: }
! 5195: #endif
! 5196: /**************************** Initialization **********************************/
! 5197: u_int
! 5198: ahd_sglist_size(struct ahd_softc *ahd)
! 5199: {
! 5200: bus_size_t list_size;
! 5201:
! 5202: list_size = sizeof(struct ahd_dma_seg) * AHD_NSEG;
! 5203: if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)
! 5204: list_size = sizeof(struct ahd_dma64_seg) * AHD_NSEG;
! 5205: return (list_size);
! 5206: }
! 5207:
! 5208: /*
! 5209: * Calculate the optimum S/G List allocation size. S/G elements used
! 5210: * for a given transaction must be physically contiguous. Assume the
! 5211: * OS will allocate full pages to us, so it doesn't make sense to request
! 5212: * less than a page.
! 5213: */
! 5214: u_int
! 5215: ahd_sglist_allocsize(struct ahd_softc *ahd)
! 5216: {
! 5217: bus_size_t sg_list_increment;
! 5218: bus_size_t sg_list_size;
! 5219: bus_size_t max_list_size;
! 5220: bus_size_t best_list_size;
! 5221:
! 5222: /* Start out with the minimum required for AHD_NSEG. */
! 5223: sg_list_increment = ahd_sglist_size(ahd);
! 5224: sg_list_size = sg_list_increment;
! 5225:
! 5226: /* Get us as close as possible to a page in size. */
! 5227: while ((sg_list_size + sg_list_increment) <= PAGE_SIZE)
! 5228: sg_list_size += sg_list_increment;
! 5229:
! 5230: /*
! 5231: * Try to reduce the amount of wastage by allocating
! 5232: * multiple pages.
! 5233: */
! 5234: best_list_size = sg_list_size;
! 5235: max_list_size = roundup(sg_list_increment, PAGE_SIZE);
! 5236: if (max_list_size < 4 * PAGE_SIZE)
! 5237: max_list_size = 4 * PAGE_SIZE;
! 5238: if (max_list_size > (AHD_SCB_MAX_ALLOC * sg_list_increment))
! 5239: max_list_size = (AHD_SCB_MAX_ALLOC * sg_list_increment);
! 5240: while ((sg_list_size + sg_list_increment) <= max_list_size
! 5241: && (sg_list_size % PAGE_SIZE) != 0) {
! 5242: bus_size_t new_mod;
! 5243: bus_size_t best_mod;
! 5244:
! 5245: sg_list_size += sg_list_increment;
! 5246: new_mod = sg_list_size % PAGE_SIZE;
! 5247: best_mod = best_list_size % PAGE_SIZE;
! 5248: if (new_mod > best_mod || new_mod == 0) {
! 5249: best_list_size = sg_list_size;
! 5250: }
! 5251: }
! 5252: return (best_list_size);
! 5253: }
! 5254:
! 5255: /*
! 5256: * Perform initial initialization for a controller structure.
! 5257: */
! 5258: struct ahd_softc *
! 5259: ahd_alloc(void *platform_arg, char *name)
! 5260: {
! 5261: struct ahd_softc *ahd = (struct ahd_softc *)platform_arg;
! 5262:
! 5263: ahd->seep_config = malloc(sizeof(*ahd->seep_config),
! 5264: M_DEVBUF, M_NOWAIT);
! 5265: if (ahd->seep_config == NULL)
! 5266: return (NULL);
! 5267:
! 5268: LIST_INIT(&ahd->pending_scbs);
! 5269: LIST_INIT(&ahd->timedout_scbs);
! 5270:
! 5271: /* We don't know our unit number until the OSM sets it */
! 5272: ahd->name = name;
! 5273: ahd->unit = -1;
! 5274: ahd->bus_description = NULL;
! 5275: ahd->channel = 'A';
! 5276: ahd->chip = AHD_NONE;
! 5277: ahd->features = AHD_FENONE;
! 5278: ahd->bugs = AHD_BUGNONE;
! 5279: ahd->flags = AHD_SPCHK_ENB_A|AHD_RESET_BUS_A|AHD_TERM_ENB_A
! 5280: | AHD_EXTENDED_TRANS_A|AHD_STPWLEVEL_A;
! 5281: ahd->int_coalescing_timer = AHD_INT_COALESCING_TIMER_DEFAULT;
! 5282: ahd->int_coalescing_maxcmds = AHD_INT_COALESCING_MAXCMDS_DEFAULT;
! 5283: ahd->int_coalescing_mincmds = AHD_INT_COALESCING_MINCMDS_DEFAULT;
! 5284: ahd->int_coalescing_threshold = AHD_INT_COALESCING_THRESHOLD_DEFAULT;
! 5285: ahd->int_coalescing_stop_threshold =
! 5286: AHD_INT_COALESCING_STOP_THRESHOLD_DEFAULT;
! 5287:
! 5288: if (ahd_platform_alloc(ahd, platform_arg) != 0) {
! 5289: free(ahd->seep_config, M_DEVBUF);
! 5290: return (NULL);
! 5291: }
! 5292:
! 5293: #ifdef AHD_DEBUG
! 5294: if ((ahd_debug & AHD_SHOW_MEMORY) != 0) {
! 5295: printf("%s: scb size = 0x%x, hscb size = 0x%x\n",
! 5296: ahd_name(ahd), (u_int)sizeof(struct scb),
! 5297: (u_int)sizeof(struct hardware_scb));
! 5298: }
! 5299: #endif
! 5300: return (ahd);
! 5301: }
! 5302:
! 5303: int
! 5304: ahd_softc_init(struct ahd_softc *ahd)
! 5305: {
! 5306:
! 5307: ahd->unpause = 0;
! 5308: ahd->pause = PAUSE;
! 5309: return (0);
! 5310: }
! 5311:
! 5312: void
! 5313: ahd_softc_insert(struct ahd_softc *ahd)
! 5314: {
! 5315: struct ahd_softc *list_ahd;
! 5316:
! 5317: #if AHD_PCI_CONFIG > 0
! 5318: /*
! 5319: * Second Function PCI devices need to inherit some
! 5320: * settings from function 0.
! 5321: */
! 5322: if ((ahd->features & AHD_MULTI_FUNC) != 0) {
! 5323: TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
! 5324: aic_dev_softc_t list_pci;
! 5325: aic_dev_softc_t pci;
! 5326:
! 5327: list_pci = list_ahd->dev_softc;
! 5328: pci = ahd->dev_softc;
! 5329: if (aic_get_pci_slot(list_pci) == aic_get_pci_slot(pci)
! 5330: && aic_get_pci_bus(list_pci) == aic_get_pci_bus(pci)) {
! 5331: struct ahd_softc *master;
! 5332: struct ahd_softc *slave;
! 5333:
! 5334: if (aic_get_pci_function(list_pci) == 0) {
! 5335: master = list_ahd;
! 5336: slave = ahd;
! 5337: } else {
! 5338: master = ahd;
! 5339: slave = list_ahd;
! 5340: }
! 5341: slave->flags &= ~AHD_BIOS_ENABLED;
! 5342: slave->flags |=
! 5343: master->flags & AHD_BIOS_ENABLED;
! 5344: break;
! 5345: }
! 5346: }
! 5347: }
! 5348: #endif
! 5349:
! 5350: /*
! 5351: * Insertion sort into our list of softcs.
! 5352: */
! 5353: list_ahd = TAILQ_FIRST(&ahd_tailq);
! 5354: while (list_ahd != NULL
! 5355: && ahd_softc_comp(ahd, list_ahd) <= 0)
! 5356: list_ahd = TAILQ_NEXT(list_ahd, links);
! 5357: if (list_ahd != NULL)
! 5358: TAILQ_INSERT_BEFORE(list_ahd, ahd, links);
! 5359: else
! 5360: TAILQ_INSERT_TAIL(&ahd_tailq, ahd, links);
! 5361: ahd->init_level++;
! 5362: }
! 5363:
! 5364: /*
! 5365: * Verify that the passed in softc pointer is for a
! 5366: * controller that is still configured.
! 5367: */
! 5368: struct ahd_softc *
! 5369: ahd_find_softc(struct ahd_softc *ahd)
! 5370: {
! 5371: struct ahd_softc *list_ahd;
! 5372:
! 5373: TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
! 5374: if (list_ahd == ahd)
! 5375: return (ahd);
! 5376: }
! 5377: return (NULL);
! 5378: }
! 5379:
! 5380: void
! 5381: ahd_set_unit(struct ahd_softc *ahd, int unit)
! 5382: {
! 5383: ahd->unit = unit;
! 5384: }
! 5385:
! 5386: void
! 5387: ahd_set_name(struct ahd_softc *ahd, char *name)
! 5388: {
! 5389: if (ahd->name != NULL)
! 5390: free(ahd->name, M_DEVBUF);
! 5391: ahd->name = name;
! 5392: }
! 5393:
! 5394: void
! 5395: ahd_free(struct ahd_softc *ahd)
! 5396: {
! 5397: int i;
! 5398:
! 5399: switch (ahd->init_level) {
! 5400: default:
! 5401: case 2:
! 5402: ahd_shutdown(ahd);
! 5403: TAILQ_REMOVE(&ahd_tailq, ahd, links);
! 5404: /* FALLTHROUGH */
! 5405: case 1:
! 5406: ahd_freedmamem(ahd, &ahd->shared_data_map);
! 5407: break;
! 5408: case 0:
! 5409: break;
! 5410: }
! 5411:
! 5412: ahd_platform_free(ahd);
! 5413: ahd_fini_scbdata(ahd);
! 5414: for (i = 0; i < AHD_NUM_TARGETS; i++) {
! 5415: struct ahd_tmode_tstate *tstate;
! 5416:
! 5417: tstate = ahd->enabled_targets[i];
! 5418: if (tstate != NULL) {
! 5419: #if AHD_TARGET_MODE
! 5420: int j;
! 5421:
! 5422: for (j = 0; j < AHD_NUM_LUNS; j++) {
! 5423: struct ahd_tmode_lstate *lstate;
! 5424:
! 5425: lstate = tstate->enabled_luns[j];
! 5426: if (lstate != NULL) {
! 5427: xpt_free_path(lstate->path);
! 5428: free(lstate, M_DEVBUF);
! 5429: }
! 5430: }
! 5431: #endif
! 5432: free(tstate, M_DEVBUF);
! 5433: }
! 5434: }
! 5435: #if AHD_TARGET_MODE
! 5436: if (ahd->black_hole != NULL) {
! 5437: xpt_free_path(ahd->black_hole->path);
! 5438: free(ahd->black_hole, M_DEVBUF);
! 5439: }
! 5440: #endif
! 5441: if (ahd->seep_config != NULL)
! 5442: free(ahd->seep_config, M_DEVBUF);
! 5443: if (ahd->saved_stack != NULL)
! 5444: free(ahd->saved_stack, M_DEVBUF);
! 5445: return;
! 5446: }
! 5447:
! 5448: void
! 5449: ahd_shutdown(void *arg)
! 5450: {
! 5451: struct ahd_softc *ahd;
! 5452:
! 5453: ahd = (struct ahd_softc *)arg;
! 5454:
! 5455: /*
! 5456: * Stop periodic timer callbacks.
! 5457: */
! 5458: aic_timer_stop(&ahd->reset_timer);
! 5459: aic_timer_stop(&ahd->stat_timer);
! 5460:
! 5461: /* This will reset most registers to 0, but not all */
! 5462: ahd_reset(ahd, /*reinit*/FALSE);
! 5463: }
! 5464:
! 5465: /*
! 5466: * Reset the controller and record some information about it
! 5467: * that is only available just after a reset. If "reinit" is
! 5468: * non-zero, this reset occured after initial configuration
! 5469: * and the caller requests that the chip be fully reinitialized
! 5470: * to a runable state. Chip interrupts are *not* enabled after
! 5471: * a reinitialization. The caller must enable interrupts via
! 5472: * ahd_intr_enable().
! 5473: */
! 5474: int
! 5475: ahd_reset(struct ahd_softc *ahd, int reinit)
! 5476: {
! 5477: const pci_chipset_tag_t pc = ahd->dev_softc->pa_pc;
! 5478: const pcitag_t tag = ahd->dev_softc->pa_tag;
! 5479: u_int sxfrctl1;
! 5480: int wait;
! 5481: pcireg_t cmd;
! 5482:
! 5483: /*
! 5484: * Preserve the value of the SXFRCTL1 register for all channels.
! 5485: * It contains settings that affect termination and we don't want
! 5486: * to disturb the integrity of the bus.
! 5487: */
! 5488: ahd_pause(ahd);
! 5489: ahd_update_modes(ahd);
! 5490: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 5491: sxfrctl1 = ahd_inb(ahd, SXFRCTL1);
! 5492:
! 5493: cmd = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
! 5494:
! 5495: if ((ahd->bugs & AHD_PCIX_CHIPRST_BUG) != 0) {
! 5496: pcireg_t mod_cmd;
! 5497:
! 5498: /*
! 5499: * A4 Razor #632
! 5500: * During the assertion of CHIPRST, the chip
! 5501: * does not disable its parity logic prior to
! 5502: * the start of the reset. This may cause a
! 5503: * parity error to be detected and thus a
! 5504: * spurious SERR or PERR assertion. Disble
! 5505: * PERR and SERR responses during the CHIPRST.
! 5506: */
! 5507: mod_cmd = cmd & ~(PCI_COMMAND_PARITY_ENABLE|PCI_COMMAND_SERR_ENABLE);
! 5508: pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, mod_cmd);
! 5509: }
! 5510: ahd_outb(ahd, HCNTRL, CHIPRST | ahd->pause);
! 5511:
! 5512: /*
! 5513: * Ensure that the reset has finished. We delay 1000us
! 5514: * prior to reading the register to make sure the chip
! 5515: * has sufficiently completed its reset to handle register
! 5516: * accesses.
! 5517: */
! 5518: wait = 1000;
! 5519: do {
! 5520: aic_delay(1000);
! 5521: } while (--wait && !(ahd_inb(ahd, HCNTRL) & CHIPRSTACK));
! 5522:
! 5523: if (wait == 0) {
! 5524: printf("%s: WARNING - Failed chip reset! "
! 5525: "Trying to initialize anyway.\n", ahd_name(ahd));
! 5526: }
! 5527: ahd_outb(ahd, HCNTRL, ahd->pause);
! 5528:
! 5529: if ((ahd->bugs & AHD_PCIX_CHIPRST_BUG) != 0) {
! 5530: /*
! 5531: * Clear any latched PCI error status and restore
! 5532: * previous SERR and PERR response enables.
! 5533: */
! 5534: pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, cmd |
! 5535: (PCI_STATUS_PARITY_ERROR | PCI_STATUS_TARGET_TARGET_ABORT |
! 5536: PCI_STATUS_MASTER_TARGET_ABORT | PCI_STATUS_MASTER_ABORT |
! 5537: PCI_STATUS_SPECIAL_ERROR));
! 5538:
! 5539: }
! 5540:
! 5541: /*
! 5542: * Mode should be SCSI after a chip reset, but lets
! 5543: * set it just to be safe. We touch the MODE_PTR
! 5544: * register directly so as to bypass the lazy update
! 5545: * code in ahd_set_modes().
! 5546: */
! 5547: ahd_known_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 5548: ahd_outb(ahd, MODE_PTR,
! 5549: ahd_build_mode_state(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI));
! 5550:
! 5551: /*
! 5552: * Restore SXFRCTL1.
! 5553: *
! 5554: * We must always initialize STPWEN to 1 before we
! 5555: * restore the saved values. STPWEN is initialized
! 5556: * to a tri-state condition which can only be cleared
! 5557: * by turning it on.
! 5558: */
! 5559: ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN);
! 5560: ahd_outb(ahd, SXFRCTL1, sxfrctl1);
! 5561:
! 5562: /* Determine chip configuration */
! 5563: ahd->features &= ~AHD_WIDE;
! 5564: if ((ahd_inb(ahd, SBLKCTL) & SELWIDE) != 0)
! 5565: ahd->features |= AHD_WIDE;
! 5566:
! 5567: /*
! 5568: * If a recovery action has forced a chip reset,
! 5569: * re-initialize the chip to our liking.
! 5570: */
! 5571: if (reinit != 0)
! 5572: ahd_chip_init(ahd);
! 5573:
! 5574: return (0);
! 5575: }
! 5576:
! 5577: /*
! 5578: * Determine the number of SCBs available on the controller
! 5579: */
! 5580: int
! 5581: ahd_probe_scbs(struct ahd_softc *ahd) {
! 5582: int i;
! 5583:
! 5584: AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
! 5585: ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
! 5586: for (i = 0; i < AHD_SCB_MAX; i++) {
! 5587: int j;
! 5588:
! 5589: ahd_set_scbptr(ahd, i);
! 5590: ahd_outw(ahd, SCB_BASE, i);
! 5591: for (j = 2; j < 64; j++)
! 5592: ahd_outb(ahd, SCB_BASE+j, 0);
! 5593: /* Start out life as unallocated (needing an abort) */
! 5594: ahd_outb(ahd, SCB_CONTROL, MK_MESSAGE);
! 5595: if (ahd_inw_scbram(ahd, SCB_BASE) != i)
! 5596: break;
! 5597: ahd_set_scbptr(ahd, 0);
! 5598: if (ahd_inw_scbram(ahd, SCB_BASE) != 0)
! 5599: break;
! 5600: }
! 5601: return (i);
! 5602: }
! 5603:
! 5604: void
! 5605: ahd_initialize_hscbs(struct ahd_softc *ahd)
! 5606: {
! 5607: int i;
! 5608:
! 5609: for (i = 0; i < ahd->scb_data.maxhscbs; i++) {
! 5610: ahd_set_scbptr(ahd, i);
! 5611:
! 5612: /* Clear the control byte. */
! 5613: ahd_outb(ahd, SCB_CONTROL, 0);
! 5614:
! 5615: /* Set the next pointer */
! 5616: ahd_outw(ahd, SCB_NEXT, SCB_LIST_NULL);
! 5617: }
! 5618: }
! 5619:
! 5620: int
! 5621: ahd_init_scbdata(struct ahd_softc *ahd)
! 5622: {
! 5623: struct scb_data *scb_data;
! 5624: int i;
! 5625:
! 5626: scb_data = &ahd->scb_data;
! 5627: TAILQ_INIT(&scb_data->free_scbs);
! 5628: for (i = 0; i < AHD_NUM_TARGETS * AHD_NUM_LUNS_NONPKT; i++)
! 5629: LIST_INIT(&scb_data->free_scb_lists[i]);
! 5630: LIST_INIT(&scb_data->any_dev_free_scb_list);
! 5631: SLIST_INIT(&scb_data->hscb_maps);
! 5632: SLIST_INIT(&scb_data->sg_maps);
! 5633: SLIST_INIT(&scb_data->sense_maps);
! 5634:
! 5635: /* Determine the number of hardware SCBs and initialize them */
! 5636: scb_data->maxhscbs = ahd_probe_scbs(ahd);
! 5637: if (scb_data->maxhscbs == 0) {
! 5638: printf("%s: No SCB space found\n", ahd_name(ahd));
! 5639: return (ENXIO);
! 5640: }
! 5641:
! 5642: ahd_initialize_hscbs(ahd);
! 5643:
! 5644: /*
! 5645: * Create our DMA tags. These tags define the kinds of device
! 5646: * accessible memory allocations and memory mappings we will
! 5647: * need to perform during normal operation.
! 5648: *
! 5649: * Unless we need to further restrict the allocation, we rely
! 5650: * on the restrictions of the parent dmat, hence the common
! 5651: * use of MAXADDR and MAXSIZE.
! 5652: */
! 5653:
! 5654: /* Perform initial CCB allocation */
! 5655: do {
! 5656: i = scb_data->numscbs;
! 5657: ahd_alloc_scbs(ahd);
! 5658: } while ((i != scb_data->numscbs) &&
! 5659: (scb_data->numscbs < AHD_SCB_MAX_ALLOC));
! 5660:
! 5661: if (scb_data->numscbs != AHD_SCB_MAX_ALLOC) {
! 5662: printf("%s: ahd_init_scbdata - "
! 5663: "Unable to allocate initial scbs\n",
! 5664: ahd_name(ahd));
! 5665: goto error_exit;
! 5666: }
! 5667:
! 5668: /*
! 5669: * Note that we were successfull
! 5670: */
! 5671: return (0);
! 5672:
! 5673: error_exit:
! 5674:
! 5675: return (ENOMEM);
! 5676: }
! 5677:
! 5678: struct scb *
! 5679: ahd_find_scb_by_tag(struct ahd_softc *ahd, u_int tag)
! 5680: {
! 5681: struct scb *scb;
! 5682:
! 5683: /*
! 5684: * Look on the pending list.
! 5685: */
! 5686: LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
! 5687: if (SCB_GET_TAG(scb) == tag)
! 5688: return (scb);
! 5689: }
! 5690:
! 5691: /*
! 5692: * Then on all of the collision free lists.
! 5693: */
! 5694: TAILQ_FOREACH(scb, &ahd->scb_data.free_scbs, links.tqe) {
! 5695: struct scb *list_scb;
! 5696:
! 5697: list_scb = scb;
! 5698: do {
! 5699: if (SCB_GET_TAG(list_scb) == tag)
! 5700: return (list_scb);
! 5701: list_scb = LIST_NEXT(list_scb, collision_links);
! 5702: } while (list_scb);
! 5703: }
! 5704:
! 5705: /*
! 5706: * And finally on the generic free list.
! 5707: */
! 5708: LIST_FOREACH(scb, &ahd->scb_data.any_dev_free_scb_list, links.le) {
! 5709: if (SCB_GET_TAG(scb) == tag)
! 5710: return (scb);
! 5711: }
! 5712:
! 5713: return (NULL);
! 5714: }
! 5715:
! 5716: void
! 5717: ahd_fini_scbdata(struct ahd_softc *ahd)
! 5718: {
! 5719: struct scb_data *scb_data;
! 5720:
! 5721: scb_data = &ahd->scb_data;
! 5722: if (scb_data == NULL)
! 5723: return;
! 5724:
! 5725: switch (scb_data->init_level) {
! 5726: default:
! 5727: case 3:
! 5728: {
! 5729: struct map_node *sns_map;
! 5730:
! 5731: while ((sns_map = SLIST_FIRST(&scb_data->sense_maps)) != NULL) {
! 5732: SLIST_REMOVE_HEAD(&scb_data->sense_maps, links);
! 5733: ahd_freedmamem(ahd, sns_map);
! 5734: free(sns_map, M_DEVBUF);
! 5735: }
! 5736: /* FALLTHROUGH */
! 5737: }
! 5738: case 2:
! 5739: {
! 5740: struct map_node *sg_map;
! 5741:
! 5742: while ((sg_map = SLIST_FIRST(&scb_data->sg_maps)) != NULL) {
! 5743: SLIST_REMOVE_HEAD(&scb_data->sg_maps, links);
! 5744: ahd_freedmamem(ahd, sg_map);
! 5745: free(sg_map, M_DEVBUF);
! 5746: }
! 5747: /* FALLTHROUGH */
! 5748: }
! 5749: case 1:
! 5750: {
! 5751: struct map_node *hscb_map;
! 5752:
! 5753: while ((hscb_map = SLIST_FIRST(&scb_data->hscb_maps)) != NULL) {
! 5754: SLIST_REMOVE_HEAD(&scb_data->hscb_maps, links);
! 5755: ahd_freedmamem(ahd, hscb_map);
! 5756: free(hscb_map, M_DEVBUF);
! 5757: }
! 5758: /* FALLTHROUGH */
! 5759: }
! 5760: case 0:
! 5761: break;
! 5762: }
! 5763: }
! 5764:
! 5765: /*
! 5766: * DSP filter Bypass must be enabled until the first selection
! 5767: * after a change in bus mode (Razor #491 and #493).
! 5768: */
! 5769: void
! 5770: ahd_setup_iocell_workaround(struct ahd_softc *ahd)
! 5771: {
! 5772: ahd_mode_state saved_modes;
! 5773:
! 5774: saved_modes = ahd_save_modes(ahd);
! 5775: ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
! 5776: ahd_outb(ahd, DSPDATACTL, ahd_inb(ahd, DSPDATACTL)
! 5777: | BYPASSENAB | RCVROFFSTDIS | XMITOFFSTDIS);
! 5778: ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) | (ENSELDO|ENSELDI));
! 5779: #ifdef AHD_DEBUG
! 5780: if ((ahd_debug & AHD_SHOW_MISC) != 0)
! 5781: printf("%s: Setting up iocell workaround\n", ahd_name(ahd));
! 5782: #endif
! 5783: ahd_restore_modes(ahd, saved_modes);
! 5784: ahd->flags &= ~AHD_HAD_FIRST_SEL;
! 5785: }
! 5786:
! 5787: void
! 5788: ahd_iocell_first_selection(struct ahd_softc *ahd)
! 5789: {
! 5790: ahd_mode_state saved_modes;
! 5791: u_int sblkctl;
! 5792:
! 5793: if ((ahd->flags & AHD_HAD_FIRST_SEL) != 0)
! 5794: return;
! 5795: saved_modes = ahd_save_modes(ahd);
! 5796: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 5797: sblkctl = ahd_inb(ahd, SBLKCTL);
! 5798: ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
! 5799: #ifdef AHD_DEBUG
! 5800: if ((ahd_debug & AHD_SHOW_MISC) != 0)
! 5801: printf("%s: iocell first selection\n", ahd_name(ahd));
! 5802: #endif
! 5803: if ((sblkctl & ENAB40) != 0) {
! 5804: ahd_outb(ahd, DSPDATACTL,
! 5805: ahd_inb(ahd, DSPDATACTL) & ~BYPASSENAB);
! 5806: #ifdef AHD_DEBUG
! 5807: if ((ahd_debug & AHD_SHOW_MISC) != 0)
! 5808: printf("%s: BYPASS now disabled\n", ahd_name(ahd));
! 5809: #endif
! 5810: }
! 5811: ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) & ~(ENSELDO|ENSELDI));
! 5812: ahd_outb(ahd, CLRINT, CLRSCSIINT);
! 5813: ahd_restore_modes(ahd, saved_modes);
! 5814: ahd->flags |= AHD_HAD_FIRST_SEL;
! 5815: }
! 5816:
! 5817: /*************************** SCB Management ***********************************/
! 5818: void
! 5819: ahd_add_col_list(struct ahd_softc *ahd, struct scb *scb, u_int col_idx)
! 5820: {
! 5821: struct scb_list *free_list;
! 5822: struct scb_tailq *free_tailq;
! 5823: struct scb *first_scb;
! 5824:
! 5825: scb->flags |= SCB_ON_COL_LIST;
! 5826: AHD_SET_SCB_COL_IDX(scb, col_idx);
! 5827: free_list = &ahd->scb_data.free_scb_lists[col_idx];
! 5828: free_tailq = &ahd->scb_data.free_scbs;
! 5829: first_scb = LIST_FIRST(free_list);
! 5830: if (first_scb != NULL) {
! 5831: LIST_INSERT_AFTER(first_scb, scb, collision_links);
! 5832: } else {
! 5833: LIST_INSERT_HEAD(free_list, scb, collision_links);
! 5834: TAILQ_INSERT_TAIL(free_tailq, scb, links.tqe);
! 5835: }
! 5836: }
! 5837:
! 5838: void
! 5839: ahd_rem_col_list(struct ahd_softc *ahd, struct scb *scb)
! 5840: {
! 5841: struct scb_list *free_list;
! 5842: struct scb_tailq *free_tailq;
! 5843: struct scb *first_scb;
! 5844: u_int col_idx;
! 5845:
! 5846: scb->flags &= ~SCB_ON_COL_LIST;
! 5847: col_idx = AHD_GET_SCB_COL_IDX(ahd, scb);
! 5848: free_list = &ahd->scb_data.free_scb_lists[col_idx];
! 5849: free_tailq = &ahd->scb_data.free_scbs;
! 5850: first_scb = LIST_FIRST(free_list);
! 5851: if (first_scb == scb) {
! 5852: struct scb *next_scb;
! 5853:
! 5854: /*
! 5855: * Maintain order in the collision free
! 5856: * lists for fairness if this device has
! 5857: * other colliding tags active.
! 5858: */
! 5859: next_scb = LIST_NEXT(scb, collision_links);
! 5860: if (next_scb != NULL) {
! 5861: TAILQ_INSERT_AFTER(free_tailq, scb,
! 5862: next_scb, links.tqe);
! 5863: }
! 5864: TAILQ_REMOVE(free_tailq, scb, links.tqe);
! 5865: }
! 5866: LIST_REMOVE(scb, collision_links);
! 5867: }
! 5868:
! 5869: /*
! 5870: * Get a free scb. If there are none, see if we can allocate a new SCB.
! 5871: */
! 5872: struct scb *
! 5873: ahd_get_scb(struct ahd_softc *ahd, u_int col_idx)
! 5874: {
! 5875: struct scb *scb;
! 5876:
! 5877: TAILQ_FOREACH(scb, &ahd->scb_data.free_scbs, links.tqe) {
! 5878: if (AHD_GET_SCB_COL_IDX(ahd, scb) != col_idx) {
! 5879: ahd_rem_col_list(ahd, scb);
! 5880: goto found;
! 5881: }
! 5882: }
! 5883: if ((scb = LIST_FIRST(&ahd->scb_data.any_dev_free_scb_list)) == NULL) {
! 5884: /* All scb's are allocated at initialization in OpenBSD. */
! 5885: return (NULL);
! 5886: }
! 5887: LIST_REMOVE(scb, links.le);
! 5888: if (col_idx != AHD_NEVER_COL_IDX
! 5889: && (scb->col_scb != NULL)
! 5890: && (scb->col_scb->flags & SCB_ACTIVE) == 0) {
! 5891: LIST_REMOVE(scb->col_scb, links.le);
! 5892: ahd_add_col_list(ahd, scb->col_scb, col_idx);
! 5893: }
! 5894: found:
! 5895: scb->flags |= SCB_ACTIVE;
! 5896: return (scb);
! 5897: }
! 5898:
! 5899: /*
! 5900: * Return an SCB resource to the free list.
! 5901: */
! 5902: void
! 5903: ahd_free_scb(struct ahd_softc *ahd, struct scb *scb)
! 5904: {
! 5905:
! 5906: /* Clean up for the next user */
! 5907: scb->flags = SCB_FLAG_NONE;
! 5908: scb->hscb->control = 0;
! 5909: ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = NULL;
! 5910:
! 5911: if (scb->col_scb == NULL) {
! 5912:
! 5913: /*
! 5914: * No collision possible. Just free normally.
! 5915: */
! 5916: LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,
! 5917: scb, links.le);
! 5918: } else if ((scb->col_scb->flags & SCB_ON_COL_LIST) != 0) {
! 5919:
! 5920: /*
! 5921: * The SCB we might have collided with is on
! 5922: * a free collision list. Put both SCBs on
! 5923: * the generic list.
! 5924: */
! 5925: ahd_rem_col_list(ahd, scb->col_scb);
! 5926: LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,
! 5927: scb, links.le);
! 5928: LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,
! 5929: scb->col_scb, links.le);
! 5930: } else if ((scb->col_scb->flags
! 5931: & (SCB_PACKETIZED|SCB_ACTIVE)) == SCB_ACTIVE
! 5932: && (scb->col_scb->hscb->control & TAG_ENB) != 0) {
! 5933:
! 5934: /*
! 5935: * The SCB we might collide with on the next allocation
! 5936: * is still active in a non-packetized, tagged, context.
! 5937: * Put us on the SCB collision list.
! 5938: */
! 5939: ahd_add_col_list(ahd, scb,
! 5940: AHD_GET_SCB_COL_IDX(ahd, scb->col_scb));
! 5941: } else {
! 5942: /*
! 5943: * The SCB we might collide with on the next allocation
! 5944: * is either active in a packetized context, or free.
! 5945: * Since we can't collide, put this SCB on the generic
! 5946: * free list.
! 5947: */
! 5948: LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,
! 5949: scb, links.le);
! 5950: }
! 5951:
! 5952: aic_platform_scb_free(ahd, scb);
! 5953: }
! 5954:
! 5955: void
! 5956: ahd_alloc_scbs(struct ahd_softc *ahd)
! 5957: {
! 5958: struct scb_data *scb_data;
! 5959: struct scb *next_scb;
! 5960: struct hardware_scb *hscb;
! 5961: struct map_node *hscb_map;
! 5962: struct map_node *sg_map;
! 5963: struct map_node *sense_map;
! 5964: uint8_t *segs;
! 5965: uint8_t *sense_data;
! 5966: bus_addr_t hscb_busaddr;
! 5967: bus_addr_t sg_busaddr;
! 5968: bus_addr_t sense_busaddr;
! 5969: int newcount;
! 5970: int i;
! 5971:
! 5972: scb_data = &ahd->scb_data;
! 5973: if (scb_data->numscbs >= AHD_SCB_MAX_ALLOC)
! 5974: /* Can't allocate any more */
! 5975: return;
! 5976:
! 5977: KASSERT(scb_data->scbs_left >= 0);
! 5978: if (scb_data->scbs_left != 0) {
! 5979: int offset;
! 5980:
! 5981: offset = (PAGE_SIZE / sizeof(*hscb)) - scb_data->scbs_left;
! 5982: hscb_map = SLIST_FIRST(&scb_data->hscb_maps);
! 5983: hscb = &((struct hardware_scb *)hscb_map->vaddr)[offset];
! 5984: hscb_busaddr = hscb_map->busaddr + (offset * sizeof(*hscb));
! 5985: } else {
! 5986: hscb_map = malloc(sizeof(*hscb_map), M_DEVBUF, M_NOWAIT);
! 5987:
! 5988: if (hscb_map == NULL)
! 5989: return;
! 5990:
! 5991: /* Allocate the next batch of hardware SCBs */
! 5992: if (ahd_createdmamem(ahd, PAGE_SIZE, hscb_map,
! 5993: "hardware SCB structures") < 0) {
! 5994: free(hscb_map, M_DEVBUF);
! 5995: return;
! 5996: }
! 5997:
! 5998: SLIST_INSERT_HEAD(&scb_data->hscb_maps, hscb_map, links);
! 5999:
! 6000: hscb = (struct hardware_scb *)hscb_map->vaddr;
! 6001: hscb_busaddr = hscb_map->busaddr;
! 6002: scb_data->scbs_left = PAGE_SIZE / sizeof(*hscb);
! 6003: }
! 6004:
! 6005: scb_data->init_level++;
! 6006:
! 6007: if (scb_data->sgs_left != 0) {
! 6008: int offset;
! 6009:
! 6010: offset = ((ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd))
! 6011: - scb_data->sgs_left) * ahd_sglist_size(ahd);
! 6012: sg_map = SLIST_FIRST(&scb_data->sg_maps);
! 6013: segs = sg_map->vaddr + offset;
! 6014: sg_busaddr = sg_map->busaddr + offset;
! 6015: } else {
! 6016: sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT);
! 6017:
! 6018: if (sg_map == NULL)
! 6019: return;
! 6020:
! 6021: /* Allocate the next batch of S/G lists */
! 6022: if (ahd_createdmamem(ahd, ahd_sglist_allocsize(ahd), sg_map,
! 6023: "SG data structures") < 0) {
! 6024: free(sg_map, M_DEVBUF);
! 6025: return;
! 6026: }
! 6027:
! 6028: SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links);
! 6029:
! 6030: segs = sg_map->vaddr;
! 6031: sg_busaddr = sg_map->busaddr;
! 6032: scb_data->sgs_left =
! 6033: ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd);
! 6034: #ifdef AHD_DEBUG
! 6035: if (ahd_debug & AHD_SHOW_MEMORY)
! 6036: printf("%s: ahd_alloc_scbs - Mapped SG data\n", ahd_name(ahd));
! 6037: #endif
! 6038: }
! 6039:
! 6040: scb_data->init_level++;
! 6041:
! 6042: if (scb_data->sense_left != 0) {
! 6043: int offset;
! 6044:
! 6045: offset = PAGE_SIZE - (AHD_SENSE_BUFSIZE * scb_data->sense_left);
! 6046: sense_map = SLIST_FIRST(&scb_data->sense_maps);
! 6047: sense_data = sense_map->vaddr + offset;
! 6048: sense_busaddr = sense_map->busaddr + offset;
! 6049: } else {
! 6050: sense_map = malloc(sizeof(*sense_map), M_DEVBUF, M_NOWAIT);
! 6051:
! 6052: if (sense_map == NULL)
! 6053: return;
! 6054:
! 6055: /* Allocate the next batch of sense buffers */
! 6056: if (ahd_createdmamem(ahd, PAGE_SIZE, sense_map,
! 6057: "Sense Data structures") < 0) {
! 6058: free(sense_map, M_DEVBUF);
! 6059: return;
! 6060: }
! 6061:
! 6062: SLIST_INSERT_HEAD(&scb_data->sense_maps, sense_map, links);
! 6063:
! 6064: sense_data = sense_map->vaddr;
! 6065: sense_busaddr = sense_map->busaddr;
! 6066: scb_data->sense_left = PAGE_SIZE / AHD_SENSE_BUFSIZE;
! 6067: #ifdef AHD_DEBUG
! 6068: if (ahd_debug & AHD_SHOW_MEMORY)
! 6069: printf("%s: ahd_alloc_scbs - Mapped sense data\n", ahd_name(ahd));
! 6070: #endif
! 6071: }
! 6072:
! 6073: scb_data->init_level++;
! 6074:
! 6075: newcount = MIN(scb_data->sense_left, scb_data->scbs_left);
! 6076: newcount = MIN(newcount, scb_data->sgs_left);
! 6077: newcount = MIN(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs));
! 6078: scb_data->sense_left -= newcount;
! 6079: scb_data->scbs_left -= newcount;
! 6080: scb_data->sgs_left -= newcount;
! 6081: for (i = 0; i < newcount; i++) {
! 6082: struct scb_platform_data *pdata = NULL;
! 6083: u_int col_tag;
! 6084: #ifndef __linux__
! 6085: int error;
! 6086: #endif
! 6087:
! 6088: next_scb = (struct scb *)malloc(sizeof(*next_scb),
! 6089: M_DEVBUF, M_NOWAIT);
! 6090: if (next_scb == NULL)
! 6091: break;
! 6092:
! 6093: if (sizeof(*pdata) > 0) {
! 6094: pdata = malloc(sizeof(*pdata), M_DEVBUF, M_NOWAIT);
! 6095: if (pdata == NULL) {
! 6096: free(next_scb, M_DEVBUF);
! 6097: break;
! 6098: }
! 6099: }
! 6100: next_scb->platform_data = pdata;
! 6101: next_scb->hscb_map = hscb_map;
! 6102: next_scb->sg_map = sg_map;
! 6103: next_scb->sense_map = sense_map;
! 6104: next_scb->sg_list = segs;
! 6105: next_scb->sense_data = sense_data;
! 6106: next_scb->sense_busaddr = sense_busaddr;
! 6107: memset(hscb, 0, sizeof(*hscb));
! 6108: next_scb->hscb = hscb;
! 6109: KASSERT((vaddr_t)hscb >= (vaddr_t)hscb_map->vaddr &&
! 6110: (vaddr_t)hscb < (vaddr_t)hscb_map->vaddr + PAGE_SIZE);
! 6111: hscb->hscb_busaddr = aic_htole32(hscb_busaddr);
! 6112:
! 6113: /*
! 6114: * The sequencer always starts with the second entry.
! 6115: * The first entry is embedded in the scb.
! 6116: */
! 6117: next_scb->sg_list_busaddr = sg_busaddr;
! 6118: if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)
! 6119: next_scb->sg_list_busaddr
! 6120: += sizeof(struct ahd_dma64_seg);
! 6121: else
! 6122: next_scb->sg_list_busaddr += sizeof(struct ahd_dma_seg);
! 6123: next_scb->ahd_softc = ahd;
! 6124: next_scb->flags = SCB_FLAG_NONE;
! 6125:
! 6126: error = bus_dmamap_create(ahd->parent_dmat,
! 6127: AHD_MAXTRANSFER_SIZE, AHD_NSEG, MAXBSIZE, 0,
! 6128: BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &next_scb->dmamap);
! 6129:
! 6130: if (error != 0) {
! 6131: free(next_scb, M_DEVBUF);
! 6132: free(pdata, M_DEVBUF);
! 6133: break;
! 6134: }
! 6135: next_scb->hscb->tag = aic_htole16(scb_data->numscbs);
! 6136: col_tag = scb_data->numscbs ^ 0x100;
! 6137: next_scb->col_scb = ahd_find_scb_by_tag(ahd, col_tag);
! 6138: if (next_scb->col_scb != NULL)
! 6139: next_scb->col_scb->col_scb = next_scb;
! 6140: ahd_free_scb(ahd, next_scb);
! 6141: hscb++;
! 6142: hscb_busaddr += sizeof(*hscb);
! 6143: segs += ahd_sglist_size(ahd);
! 6144: sg_busaddr += ahd_sglist_size(ahd);
! 6145: sense_data += AHD_SENSE_BUFSIZE;
! 6146: sense_busaddr += AHD_SENSE_BUFSIZE;
! 6147: scb_data->numscbs++;
! 6148: }
! 6149: }
! 6150:
! 6151: void
! 6152: ahd_controller_info(struct ahd_softc *ahd, char *buf, size_t bufsz)
! 6153: {
! 6154: snprintf(buf, bufsz, "%s: %s, U320 %s Channel %c, SCSI Id=%d, %s, %d SCBs",
! 6155: ahd_name(ahd), ahd_chip_names[ahd->chip & AHD_CHIPID_MASK],
! 6156: ((ahd->features & AHD_WIDE) != 0) ? "Wide" : "Single",
! 6157: ahd->channel, ahd->our_id, ahd->bus_description,
! 6158: ahd->scb_data.maxhscbs);
! 6159: }
! 6160:
! 6161: static const char *channel_strings[] = {
! 6162: "Primary Low",
! 6163: "Primary High",
! 6164: "Secondary Low",
! 6165: "Secondary High"
! 6166: };
! 6167:
! 6168: static const char *termstat_strings[] = {
! 6169: "Terminated Correctly",
! 6170: "Over Terminated",
! 6171: "Under Terminated",
! 6172: "Not Configured"
! 6173: };
! 6174:
! 6175: /*
! 6176: * Start the board, ready for normal operation
! 6177: */
! 6178: int
! 6179: ahd_init(struct ahd_softc *ahd)
! 6180: {
! 6181: uint8_t *next_vaddr;
! 6182: bus_addr_t next_baddr;
! 6183: size_t driver_data_size;
! 6184: int i;
! 6185: int error;
! 6186: u_int warn_user;
! 6187: uint8_t current_sensing;
! 6188: uint8_t fstat;
! 6189:
! 6190: AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
! 6191:
! 6192: ahd->stack_size = ahd_probe_stack_size(ahd);
! 6193: ahd->saved_stack = malloc(ahd->stack_size * sizeof(uint16_t),
! 6194: M_DEVBUF, M_NOWAIT);
! 6195: if (ahd->saved_stack == NULL)
! 6196: return (ENOMEM);
! 6197:
! 6198: /* Zero the memory */
! 6199: memset(ahd->saved_stack, 0, ahd->stack_size * sizeof(uint16_t));
! 6200:
! 6201: /*
! 6202: * Verify that the compiler hasn't over-agressively
! 6203: * padded important structures.
! 6204: */
! 6205: if (sizeof(struct hardware_scb) != 64)
! 6206: panic("Hardware SCB size is incorrect");
! 6207:
! 6208: #ifdef AHD_DEBUG
! 6209: if ((ahd_debug & AHD_DEBUG_SEQUENCER) != 0)
! 6210: ahd->flags |= AHD_SEQUENCER_DEBUG;
! 6211: #endif
! 6212:
! 6213: /*
! 6214: * Default to allowing initiator operations.
! 6215: */
! 6216: ahd->flags |= AHD_INITIATORROLE;
! 6217:
! 6218: /*
! 6219: * Only allow target mode features if this unit has them enabled.
! 6220: */
! 6221: if ((AHD_TMODE_ENABLE & (0x1 << ahd->unit)) == 0)
! 6222: ahd->features &= ~AHD_TARGETMODE;
! 6223:
! 6224: /*
! 6225: * DMA tag for our command fifos and other data in system memory
! 6226: * the card's sequencer must be able to access. For initiator
! 6227: * roles, we need to allocate space for the qoutfifo. When providing
! 6228: * for the target mode role, we must additionally provide space for
! 6229: * the incoming target command fifo.
! 6230: */
! 6231: driver_data_size = AHD_SCB_MAX * sizeof(*ahd->qoutfifo)
! 6232: + sizeof(struct hardware_scb);
! 6233: if ((ahd->features & AHD_TARGETMODE) != 0)
! 6234: driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd);
! 6235: if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0)
! 6236: driver_data_size += PKT_OVERRUN_BUFSIZE;
! 6237: if (ahd_createdmamem(ahd, driver_data_size, &ahd->shared_data_map,
! 6238: "shared data") < 0)
! 6239: return (ENOMEM);
! 6240:
! 6241: ahd->qoutfifo = (struct ahd_completion *)ahd->shared_data_map.vaddr;
! 6242:
! 6243: ahd->init_level++;
! 6244:
! 6245: next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE];
! 6246: next_baddr = ahd->shared_data_map.busaddr
! 6247: + AHD_QOUT_SIZE*sizeof(struct ahd_completion);
! 6248: if ((ahd->features & AHD_TARGETMODE) != 0) {
! 6249: ahd->targetcmds = (struct target_cmd *)next_vaddr;
! 6250: next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd);
! 6251: next_baddr += AHD_TMODE_CMDS * sizeof(struct target_cmd);
! 6252: }
! 6253:
! 6254: if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) {
! 6255: ahd->overrun_buf = next_vaddr;
! 6256: next_vaddr += PKT_OVERRUN_BUFSIZE;
! 6257: next_baddr += PKT_OVERRUN_BUFSIZE;
! 6258: }
! 6259:
! 6260: /*
! 6261: * We need one SCB to serve as the "next SCB". Since the
! 6262: * tag identifier in this SCB will never be used, there is
! 6263: * no point in using a valid HSCB tag from an SCB pulled from
! 6264: * the standard free pool. So, we allocate this "sentinel"
! 6265: * specially from the DMA safe memory chunk used for the QOUTFIFO.
! 6266: */
! 6267: ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr;
! 6268: ahd->next_queued_hscb_map = &ahd->shared_data_map;
! 6269: ahd->next_queued_hscb->hscb_busaddr = aic_htole32(next_baddr);
! 6270:
! 6271: /* Allocate SCB data now that buffer_dmat is initialized */
! 6272: if (ahd_init_scbdata(ahd) != 0)
! 6273: return (ENOMEM);
! 6274:
! 6275: if ((ahd->flags & AHD_INITIATORROLE) == 0)
! 6276: ahd->flags &= ~AHD_RESET_BUS_A;
! 6277:
! 6278: /*
! 6279: * Before committing these settings to the chip, give
! 6280: * the OSM one last chance to modify our configuration.
! 6281: */
! 6282: ahd_platform_init(ahd);
! 6283:
! 6284: /* Bring up the chip. */
! 6285: ahd_chip_init(ahd);
! 6286:
! 6287: AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
! 6288:
! 6289: if ((ahd->flags & AHD_CURRENT_SENSING) == 0)
! 6290: goto init_done;
! 6291:
! 6292: /*
! 6293: * Verify termination based on current draw and
! 6294: * warn user if the bus is over/under terminated.
! 6295: */
! 6296: error = ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL,
! 6297: CURSENSE_ENB);
! 6298: if (error != 0) {
! 6299: printf("%s: current sensing timeout 1\n", ahd_name(ahd));
! 6300: goto init_done;
! 6301: }
! 6302: for (i = 20, fstat = FLX_FSTAT_BUSY;
! 6303: (fstat & FLX_FSTAT_BUSY) != 0 && i; i--) {
! 6304: error = ahd_read_flexport(ahd, FLXADDR_FLEXSTAT, &fstat);
! 6305: if (error != 0) {
! 6306: printf("%s: current sensing timeout 2\n",
! 6307: ahd_name(ahd));
! 6308: goto init_done;
! 6309: }
! 6310: }
! 6311: if (i == 0) {
! 6312: printf("%s: Timeout during current-sensing test\n",
! 6313: ahd_name(ahd));
! 6314: goto init_done;
! 6315: }
! 6316:
! 6317: /* Latch Current Sensing status. */
! 6318: error = ahd_read_flexport(ahd, FLXADDR_CURRENT_STAT, ¤t_sensing);
! 6319: if (error != 0) {
! 6320: printf("%s: current sensing timeout 3\n", ahd_name(ahd));
! 6321: goto init_done;
! 6322: }
! 6323:
! 6324: /* Disable current sensing. */
! 6325: ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, 0);
! 6326:
! 6327: #ifdef AHD_DEBUG
! 6328: if ((ahd_debug & AHD_SHOW_TERMCTL) != 0) {
! 6329: printf("%s: current_sensing == 0x%x\n",
! 6330: ahd_name(ahd), current_sensing);
! 6331: }
! 6332: #endif
! 6333: warn_user = 0;
! 6334: for (i = 0; i < 4; i++, current_sensing >>= FLX_CSTAT_SHIFT) {
! 6335: u_int term_stat;
! 6336:
! 6337: term_stat = (current_sensing & FLX_CSTAT_MASK);
! 6338: switch (term_stat) {
! 6339: case FLX_CSTAT_OVER:
! 6340: case FLX_CSTAT_UNDER:
! 6341: warn_user++;
! 6342: case FLX_CSTAT_INVALID:
! 6343: case FLX_CSTAT_OKAY:
! 6344: if (warn_user == 0 && bootverbose == 0)
! 6345: break;
! 6346: printf("%s: %s Channel %s\n", ahd_name(ahd),
! 6347: channel_strings[i], termstat_strings[term_stat]);
! 6348: break;
! 6349: }
! 6350: }
! 6351: if (warn_user) {
! 6352: printf("%s: WARNING. Termination is not configured correctly.\n"
! 6353: "%s: WARNING. SCSI bus operations may FAIL.\n",
! 6354: ahd_name(ahd), ahd_name(ahd));
! 6355: }
! 6356: init_done:
! 6357: ahd_reset_current_bus(ahd);
! 6358: ahd_restart(ahd);
! 6359: aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_MS,
! 6360: ahd_stat_timer, ahd);
! 6361:
! 6362: /* We have to wait until after any system dumps... */
! 6363: ahd->shutdown_hook = shutdownhook_establish(ahd_shutdown, ahd);
! 6364: return (0);
! 6365: }
! 6366:
! 6367: /*
! 6368: * (Re)initialize chip state after a chip reset.
! 6369: */
! 6370: void
! 6371: ahd_chip_init(struct ahd_softc *ahd)
! 6372: {
! 6373: uint32_t busaddr;
! 6374: u_int sxfrctl1;
! 6375: u_int scsiseq_template;
! 6376: u_int wait;
! 6377: u_int i;
! 6378: u_int target;
! 6379:
! 6380: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 6381: /*
! 6382: * Take the LED out of diagnostic mode
! 6383: */
! 6384: ahd_outb(ahd, SBLKCTL, ahd_inb(ahd, SBLKCTL) & ~(DIAGLEDEN|DIAGLEDON));
! 6385:
! 6386: /*
! 6387: * Return HS_MAILBOX to its default value.
! 6388: */
! 6389: ahd->hs_mailbox = 0;
! 6390: ahd_outb(ahd, HS_MAILBOX, 0);
! 6391:
! 6392: /* Set the SCSI Id, SXFRCTL0, SXFRCTL1, and SIMODE1. */
! 6393: ahd_outb(ahd, IOWNID, ahd->our_id);
! 6394: ahd_outb(ahd, TOWNID, ahd->our_id);
! 6395: sxfrctl1 = (ahd->flags & AHD_TERM_ENB_A) != 0 ? STPWEN : 0;
! 6396: sxfrctl1 |= (ahd->flags & AHD_SPCHK_ENB_A) != 0 ? ENSPCHK : 0;
! 6397: if ((ahd->bugs & AHD_LONG_SETIMO_BUG)
! 6398: && (ahd->seltime != STIMESEL_MIN)) {
! 6399: /*
! 6400: * The selection timer duration is twice as long
! 6401: * as it should be. Halve it by adding "1" to
! 6402: * the user specified setting.
! 6403: */
! 6404: sxfrctl1 |= ahd->seltime + STIMESEL_BUG_ADJ;
! 6405: } else {
! 6406: sxfrctl1 |= ahd->seltime;
! 6407: }
! 6408:
! 6409: ahd_outb(ahd, SXFRCTL0, DFON);
! 6410: ahd_outb(ahd, SXFRCTL1, sxfrctl1|ahd->seltime|ENSTIMER|ACTNEGEN);
! 6411: ahd_outb(ahd, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);
! 6412:
! 6413: /*
! 6414: * Now that termination is set, wait for up
! 6415: * to 500ms for our transceivers to settle. If
! 6416: * the adapter does not have a cable attached,
! 6417: * the transceivers may never settle, so don't
! 6418: * complain if we fail here.
! 6419: */
! 6420: for (wait = 10000;
! 6421: (ahd_inb(ahd, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait;
! 6422: wait--)
! 6423: aic_delay(100);
! 6424:
! 6425: /* Clear any false bus resets due to the transceivers settling */
! 6426: ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI);
! 6427: ahd_outb(ahd, CLRINT, CLRSCSIINT);
! 6428:
! 6429: /* Initialize mode specific S/G state. */
! 6430: for (i = 0; i < 2; i++) {
! 6431: ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i);
! 6432: ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
! 6433: ahd_outb(ahd, SG_STATE, 0);
! 6434: ahd_outb(ahd, CLRSEQINTSRC, 0xFF);
! 6435: ahd_outb(ahd, SEQIMODE,
! 6436: ENSAVEPTRS|ENCFG4DATA|ENCFG4ISTAT
! 6437: |ENCFG4TSTAT|ENCFG4ICMD|ENCFG4TCMD);
! 6438: }
! 6439:
! 6440: ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
! 6441: ahd_outb(ahd, DSCOMMAND0, ahd_inb(ahd, DSCOMMAND0)|MPARCKEN|CACHETHEN);
! 6442: ahd_outb(ahd, DFF_THRSH, RD_DFTHRSH_75|WR_DFTHRSH_75);
! 6443: ahd_outb(ahd, SIMODE0, ENIOERR|ENOVERRUN);
! 6444: ahd_outb(ahd, SIMODE3, ENNTRAMPERR|ENOSRAMPERR);
! 6445: if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
! 6446: ahd_outb(ahd, OPTIONMODE, AUTOACKEN|AUTO_MSGOUT_DE);
! 6447: } else {
! 6448: ahd_outb(ahd, OPTIONMODE, AUTOACKEN|BUSFREEREV|AUTO_MSGOUT_DE);
! 6449: }
! 6450: ahd_outb(ahd, SCSCHKN, CURRFIFODEF|WIDERESEN|SHVALIDSTDIS);
! 6451: if ((ahd->chip & AHD_BUS_MASK) == AHD_PCIX)
! 6452: /*
! 6453: * Do not issue a target abort when a split completion
! 6454: * error occurs. Let our PCIX interrupt handler deal
! 6455: * with it instead. H2A4 Razor #625
! 6456: */
! 6457: ahd_outb(ahd, PCIXCTL, ahd_inb(ahd, PCIXCTL) | SPLTSTADIS);
! 6458:
! 6459: if ((ahd->bugs & AHD_LQOOVERRUN_BUG) != 0)
! 6460: ahd_outb(ahd, LQOSCSCTL, LQONOCHKOVER);
! 6461:
! 6462: /*
! 6463: * Tweak IOCELL settings.
! 6464: */
! 6465: if ((ahd->flags & AHD_HP_BOARD) != 0) {
! 6466: for (i = 0; i < NUMDSPS; i++) {
! 6467: ahd_outb(ahd, DSPSELECT, i);
! 6468: ahd_outb(ahd, WRTBIASCTL, WRTBIASCTL_HP_DEFAULT);
! 6469: }
! 6470: #ifdef AHD_DEBUG
! 6471: if ((ahd_debug & AHD_SHOW_MISC) != 0)
! 6472: printf("%s: WRTBIASCTL now 0x%x\n", ahd_name(ahd),
! 6473: WRTBIASCTL_HP_DEFAULT);
! 6474: #endif
! 6475: }
! 6476: ahd_setup_iocell_workaround(ahd);
! 6477:
! 6478: /*
! 6479: * Enable LQI Manager interrupts.
! 6480: */
! 6481: ahd_outb(ahd, LQIMODE1, ENLQIPHASE_LQ|ENLQIPHASE_NLQ|ENLIQABORT
! 6482: | ENLQICRCI_LQ|ENLQICRCI_NLQ|ENLQIBADLQI
! 6483: | ENLQIOVERI_LQ|ENLQIOVERI_NLQ);
! 6484: ahd_outb(ahd, LQOMODE0, ENLQOATNLQ|ENLQOATNPKT|ENLQOTCRC);
! 6485: /*
! 6486: * We choose to have the sequencer catch LQOPHCHGINPKT errors
! 6487: * manually for the command phase at the start of a packetized
! 6488: * selection case. ENLQOBUSFREE should be made redundant by
! 6489: * the BUSFREE interrupt, but it seems that some LQOBUSFREE
! 6490: * events fail to assert the BUSFREE interrupt so we must
! 6491: * also enable LQOBUSFREE interrupts.
! 6492: */
! 6493: ahd_outb(ahd, LQOMODE1, ENLQOBUSFREE);
! 6494:
! 6495: /*
! 6496: * Setup sequencer interrupt handlers.
! 6497: */
! 6498: ahd_outw(ahd, INTVEC1_ADDR, ahd_resolve_seqaddr(ahd, LABEL_seq_isr));
! 6499: ahd_outw(ahd, INTVEC2_ADDR, ahd_resolve_seqaddr(ahd, LABEL_timer_isr));
! 6500:
! 6501: /*
! 6502: * Setup SCB Offset registers.
! 6503: */
! 6504: if ((ahd->bugs & AHD_PKT_LUN_BUG) != 0) {
! 6505: ahd_outb(ahd, LUNPTR, offsetof(struct hardware_scb,
! 6506: pkt_long_lun));
! 6507: } else {
! 6508: ahd_outb(ahd, LUNPTR, offsetof(struct hardware_scb, lun));
! 6509: }
! 6510: ahd_outb(ahd, CMDLENPTR, offsetof(struct hardware_scb, cdb_len));
! 6511: ahd_outb(ahd, ATTRPTR, offsetof(struct hardware_scb, task_attribute));
! 6512: ahd_outb(ahd, FLAGPTR, offsetof(struct hardware_scb, task_management));
! 6513: ahd_outb(ahd, CMDPTR, offsetof(struct hardware_scb,
! 6514: shared_data.idata.cdb));
! 6515: ahd_outb(ahd, QNEXTPTR,
! 6516: offsetof(struct hardware_scb, next_hscb_busaddr));
! 6517: ahd_outb(ahd, ABRTBITPTR, MK_MESSAGE_BIT_OFFSET);
! 6518: ahd_outb(ahd, ABRTBYTEPTR, offsetof(struct hardware_scb, control));
! 6519: if ((ahd->bugs & AHD_PKT_LUN_BUG) != 0) {
! 6520: ahd_outb(ahd, LUNLEN,
! 6521: sizeof(ahd->next_queued_hscb->pkt_long_lun) - 1);
! 6522: } else {
! 6523: ahd_outb(ahd, LUNLEN, LUNLEN_SINGLE_LEVEL_LUN);
! 6524: }
! 6525: ahd_outb(ahd, CDBLIMIT, SCB_CDB_LEN_PTR - 1);
! 6526: ahd_outb(ahd, MAXCMD, 0xFF);
! 6527: ahd_outb(ahd, SCBAUTOPTR,
! 6528: AUSCBPTR_EN | offsetof(struct hardware_scb, tag));
! 6529:
! 6530: /* We haven't been enabled for target mode yet. */
! 6531: ahd_outb(ahd, MULTARGID, 0);
! 6532: ahd_outb(ahd, MULTARGID + 1, 0);
! 6533:
! 6534: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 6535: /* Initialize the negotiation table. */
! 6536: if ((ahd->features & AHD_NEW_IOCELL_OPTS) == 0) {
! 6537: /*
! 6538: * Clear the spare bytes in the neg table to avoid
! 6539: * spurious parity errors.
! 6540: */
! 6541: for (target = 0; target < AHD_NUM_TARGETS; target++) {
! 6542: ahd_outb(ahd, NEGOADDR, target);
! 6543: ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PER_DEV0);
! 6544: for (i = 0; i < AHD_NUM_PER_DEV_ANNEXCOLS; i++)
! 6545: ahd_outb(ahd, ANNEXDAT, 0);
! 6546: }
! 6547: }
! 6548: for (target = 0; target < AHD_NUM_TARGETS; target++) {
! 6549: struct ahd_devinfo devinfo;
! 6550: struct ahd_initiator_tinfo *tinfo;
! 6551: struct ahd_tmode_tstate *tstate;
! 6552:
! 6553: tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
! 6554: target, &tstate);
! 6555: ahd_compile_devinfo(&devinfo, ahd->our_id,
! 6556: target, CAM_LUN_WILDCARD,
! 6557: 'A', ROLE_INITIATOR);
! 6558: ahd_update_neg_table(ahd, &devinfo, &tinfo->curr);
! 6559: }
! 6560:
! 6561: ahd_outb(ahd, CLRSINT3, NTRAMPERR|OSRAMPERR);
! 6562: ahd_outb(ahd, CLRINT, CLRSCSIINT);
! 6563:
! 6564: #if NEEDS_MORE_TESTING
! 6565: /*
! 6566: * Always enable abort on incoming L_Qs if this feature is
! 6567: * supported. We use this to catch invalid SCB references.
! 6568: */
! 6569: if ((ahd->bugs & AHD_ABORT_LQI_BUG) == 0)
! 6570: ahd_outb(ahd, LQCTL1, ABORTPENDING);
! 6571: else
! 6572: #endif
! 6573: ahd_outb(ahd, LQCTL1, 0);
! 6574:
! 6575: /* All of our queues are empty */
! 6576: ahd->qoutfifonext = 0;
! 6577: ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID;
! 6578: ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID);
! 6579: for (i = 0; i < AHD_QOUT_SIZE; i++)
! 6580: ahd->qoutfifo[i].valid_tag = 0;
! 6581: ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD);
! 6582:
! 6583: ahd->qinfifonext = 0;
! 6584: for (i = 0; i < AHD_QIN_SIZE; i++)
! 6585: ahd->qinfifo[i] = SCB_LIST_NULL;
! 6586:
! 6587: if ((ahd->features & AHD_TARGETMODE) != 0) {
! 6588: /* All target command blocks start out invalid. */
! 6589: for (i = 0; i < AHD_TMODE_CMDS; i++)
! 6590: ahd->targetcmds[i].cmd_valid = 0;
! 6591: ahd_sync_tqinfifo(ahd, BUS_DMASYNC_PREREAD);
! 6592: ahd->tqinfifonext = 1;
! 6593: ahd_outb(ahd, KERNEL_TQINPOS, ahd->tqinfifonext - 1);
! 6594: ahd_outb(ahd, TQINPOS, ahd->tqinfifonext);
! 6595: }
! 6596:
! 6597: /* Initialize Scratch Ram. */
! 6598: ahd_outb(ahd, SEQ_FLAGS, 0);
! 6599: ahd_outb(ahd, SEQ_FLAGS2, 0);
! 6600:
! 6601: /* We don't have any waiting selections */
! 6602: ahd_outw(ahd, WAITING_TID_HEAD, SCB_LIST_NULL);
! 6603: ahd_outw(ahd, WAITING_TID_TAIL, SCB_LIST_NULL);
! 6604: ahd_outw(ahd, MK_MESSAGE_SCB, SCB_LIST_NULL);
! 6605: ahd_outw(ahd, MK_MESSAGE_SCSIID, 0xFF);
! 6606: for (i = 0; i < AHD_NUM_TARGETS; i++)
! 6607: ahd_outw(ahd, WAITING_SCB_TAILS + (2 * i), SCB_LIST_NULL);
! 6608:
! 6609: /*
! 6610: * Nobody is waiting to be DMAed into the QOUTFIFO.
! 6611: */
! 6612: ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);
! 6613: ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL);
! 6614: ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);
! 6615: ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);
! 6616: ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);
! 6617:
! 6618: /*
! 6619: * The Freeze Count is 0.
! 6620: */
! 6621: ahd->qfreeze_cnt = 0;
! 6622: ahd_outw(ahd, QFREEZE_COUNT, 0);
! 6623: ahd_outw(ahd, KERNEL_QFREEZE_COUNT, 0);
! 6624:
! 6625: /*
! 6626: * Tell the sequencer where it can find our arrays in memory.
! 6627: */
! 6628: busaddr = ahd->shared_data_map.busaddr;
! 6629: ahd_outl(ahd, SHARED_DATA_ADDR, busaddr);
! 6630: ahd_outl(ahd, QOUTFIFO_NEXT_ADDR, busaddr);
! 6631:
! 6632: /*
! 6633: * Setup the allowed SCSI Sequences based on operational mode.
! 6634: * If we are a target, we'll enable select in operations once
! 6635: * we've had a lun enabled.
! 6636: */
! 6637: scsiseq_template = ENAUTOATNP;
! 6638: if ((ahd->flags & AHD_INITIATORROLE) != 0)
! 6639: scsiseq_template |= ENRSELI;
! 6640: ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq_template);
! 6641:
! 6642: /* There are no busy SCBs yet. */
! 6643: for (target = 0; target < AHD_NUM_TARGETS; target++) {
! 6644: int lun;
! 6645:
! 6646: for (lun = 0; lun < AHD_NUM_LUNS_NONPKT; lun++)
! 6647: ahd_unbusy_tcl(ahd, BUILD_TCL_RAW(target, 'A', lun));
! 6648: }
! 6649:
! 6650: /*
! 6651: * Initialize the group code to command length table.
! 6652: * Vendor Unique codes are set to 0 so we only capture
! 6653: * the first byte of the cdb. These can be overridden
! 6654: * when target mode is enabled.
! 6655: */
! 6656: ahd_outb(ahd, CMDSIZE_TABLE, 5);
! 6657: ahd_outb(ahd, CMDSIZE_TABLE + 1, 9);
! 6658: ahd_outb(ahd, CMDSIZE_TABLE + 2, 9);
! 6659: ahd_outb(ahd, CMDSIZE_TABLE + 3, 0);
! 6660: ahd_outb(ahd, CMDSIZE_TABLE + 4, 15);
! 6661: ahd_outb(ahd, CMDSIZE_TABLE + 5, 11);
! 6662: ahd_outb(ahd, CMDSIZE_TABLE + 6, 0);
! 6663: ahd_outb(ahd, CMDSIZE_TABLE + 7, 0);
! 6664:
! 6665: /* Tell the sequencer of our initial queue positions */
! 6666: ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
! 6667: ahd_outb(ahd, QOFF_CTLSTA, SCB_QSIZE_512);
! 6668: ahd->qinfifonext = 0;
! 6669: ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
! 6670: ahd_set_hescb_qoff(ahd, 0);
! 6671: ahd_set_snscb_qoff(ahd, 0);
! 6672: ahd_set_sescb_qoff(ahd, 0);
! 6673: ahd_set_sdscb_qoff(ahd, 0);
! 6674:
! 6675: /*
! 6676: * Tell the sequencer which SCB will be the next one it receives.
! 6677: */
! 6678: busaddr = aic_le32toh(ahd->next_queued_hscb->hscb_busaddr);
! 6679: ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
! 6680:
! 6681: /*
! 6682: * Default to coalescing disabled.
! 6683: */
! 6684: ahd_outw(ahd, INT_COALESCING_CMDCOUNT, 0);
! 6685: ahd_outw(ahd, CMDS_PENDING, 0);
! 6686: ahd_update_coalescing_values(ahd, ahd->int_coalescing_timer,
! 6687: ahd->int_coalescing_maxcmds,
! 6688: ahd->int_coalescing_mincmds);
! 6689: ahd_enable_coalescing(ahd, FALSE);
! 6690:
! 6691: ahd_loadseq(ahd);
! 6692: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 6693: }
! 6694:
! 6695: /*
! 6696: * Setup default device and controller settings.
! 6697: * This should only be called if our probe has
! 6698: * determined that no configuration data is available.
! 6699: */
! 6700: int
! 6701: ahd_default_config(struct ahd_softc *ahd)
! 6702: {
! 6703: int targ;
! 6704:
! 6705: ahd->our_id = 7;
! 6706:
! 6707: /*
! 6708: * Allocate a tstate to house information for our
! 6709: * initiator presence on the bus as well as the user
! 6710: * data for any target mode initiator.
! 6711: */
! 6712: if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL) {
! 6713: printf("%s: unable to allocate ahd_tmode_tstate. "
! 6714: "Failing attach\n", ahd_name(ahd));
! 6715: return (ENOMEM);
! 6716: }
! 6717:
! 6718: for (targ = 0; targ < AHD_NUM_TARGETS; targ++) {
! 6719: struct ahd_devinfo devinfo;
! 6720: struct ahd_initiator_tinfo *tinfo;
! 6721: struct ahd_tmode_tstate *tstate;
! 6722: uint16_t target_mask;
! 6723:
! 6724: tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
! 6725: targ, &tstate);
! 6726: /*
! 6727: * We support SPC2 and SPI4.
! 6728: */
! 6729: tinfo->user.protocol_version = 4;
! 6730: tinfo->user.transport_version = 4;
! 6731:
! 6732: target_mask = 0x01 << targ;
! 6733: ahd->user_discenable |= target_mask;
! 6734: tstate->discenable |= target_mask;
! 6735: ahd->user_tagenable |= target_mask;
! 6736: #ifdef AHD_FORCE_160
! 6737: tinfo->user.period = AHD_SYNCRATE_DT;
! 6738: #else
! 6739: tinfo->user.period = AHD_SYNCRATE_160;
! 6740: #endif
! 6741: tinfo->user.offset = MAX_OFFSET;
! 6742: tinfo->user.ppr_options = MSG_EXT_PPR_RD_STRM
! 6743: | MSG_EXT_PPR_WR_FLOW
! 6744: | MSG_EXT_PPR_HOLD_MCS
! 6745: | MSG_EXT_PPR_IU_REQ
! 6746: | MSG_EXT_PPR_QAS_REQ
! 6747: | MSG_EXT_PPR_DT_REQ;
! 6748: if ((ahd->features & AHD_RTI) != 0)
! 6749: tinfo->user.ppr_options |= MSG_EXT_PPR_RTI;
! 6750:
! 6751: tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT;
! 6752:
! 6753: /*
! 6754: * Start out Async/Narrow/Untagged and with
! 6755: * conservative protocol support.
! 6756: */
! 6757: tinfo->goal.protocol_version = 2;
! 6758: tinfo->goal.transport_version = 2;
! 6759: tinfo->curr.protocol_version = 2;
! 6760: tinfo->curr.transport_version = 2;
! 6761: ahd_compile_devinfo(&devinfo, ahd->our_id,
! 6762: targ, CAM_LUN_WILDCARD,
! 6763: 'A', ROLE_INITIATOR);
! 6764: tstate->tagenable &= ~target_mask;
! 6765: ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
! 6766: AHD_TRANS_CUR|AHD_TRANS_GOAL, /*paused*/TRUE);
! 6767: ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0,
! 6768: /*ppr_options*/0, AHD_TRANS_CUR|AHD_TRANS_GOAL,
! 6769: /*paused*/TRUE);
! 6770: }
! 6771: return (0);
! 6772: }
! 6773:
! 6774: /*
! 6775: * Parse device configuration information.
! 6776: */
! 6777: int
! 6778: ahd_parse_cfgdata(struct ahd_softc *ahd, struct seeprom_config *sc)
! 6779: {
! 6780: int targ;
! 6781: int max_targ;
! 6782:
! 6783: max_targ = sc->max_targets & CFMAXTARG;
! 6784: ahd->our_id = sc->brtime_id & CFSCSIID;
! 6785:
! 6786: /*
! 6787: * Allocate a tstate to house information for our
! 6788: * initiator presence on the bus as well as the user
! 6789: * data for any target mode initiator.
! 6790: */
! 6791: if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL) {
! 6792: printf("%s: unable to allocate ahd_tmode_tstate. "
! 6793: "Failing attach\n", ahd_name(ahd));
! 6794: return (ENOMEM);
! 6795: }
! 6796:
! 6797: for (targ = 0; targ < max_targ; targ++) {
! 6798: struct ahd_devinfo devinfo;
! 6799: struct ahd_initiator_tinfo *tinfo;
! 6800: struct ahd_transinfo *user_tinfo;
! 6801: struct ahd_tmode_tstate *tstate;
! 6802: uint16_t target_mask;
! 6803:
! 6804: tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
! 6805: targ, &tstate);
! 6806: user_tinfo = &tinfo->user;
! 6807:
! 6808: /*
! 6809: * We support SPC2 and SPI4.
! 6810: */
! 6811: tinfo->user.protocol_version = 4;
! 6812: tinfo->user.transport_version = 4;
! 6813:
! 6814: target_mask = 0x01 << targ;
! 6815: ahd->user_discenable &= ~target_mask;
! 6816: tstate->discenable &= ~target_mask;
! 6817: ahd->user_tagenable &= ~target_mask;
! 6818: if (sc->device_flags[targ] & CFDISC) {
! 6819: tstate->discenable |= target_mask;
! 6820: ahd->user_discenable |= target_mask;
! 6821: ahd->user_tagenable |= target_mask;
! 6822: } else {
! 6823: /*
! 6824: * Cannot be packetized without disconnection.
! 6825: */
! 6826: sc->device_flags[targ] &= ~CFPACKETIZED;
! 6827: }
! 6828:
! 6829: user_tinfo->ppr_options = 0;
! 6830: user_tinfo->period = (sc->device_flags[targ] & CFXFER);
! 6831: if (user_tinfo->period < CFXFER_ASYNC) {
! 6832: if (user_tinfo->period <= AHD_PERIOD_10MHz)
! 6833: user_tinfo->ppr_options |= MSG_EXT_PPR_DT_REQ;
! 6834: user_tinfo->offset = MAX_OFFSET;
! 6835: } else {
! 6836: user_tinfo->offset = 0;
! 6837: user_tinfo->period = AHD_ASYNC_XFER_PERIOD;
! 6838: }
! 6839: #ifdef AHD_FORCE_160
! 6840: if (user_tinfo->period <= AHD_SYNCRATE_160)
! 6841: user_tinfo->period = AHD_SYNCRATE_DT;
! 6842: #endif
! 6843:
! 6844: if ((sc->device_flags[targ] & CFPACKETIZED) != 0) {
! 6845: user_tinfo->ppr_options |= MSG_EXT_PPR_RD_STRM
! 6846: | MSG_EXT_PPR_WR_FLOW
! 6847: | MSG_EXT_PPR_HOLD_MCS
! 6848: | MSG_EXT_PPR_IU_REQ;
! 6849: if ((ahd->features & AHD_RTI) != 0)
! 6850: user_tinfo->ppr_options |= MSG_EXT_PPR_RTI;
! 6851: }
! 6852:
! 6853: if ((sc->device_flags[targ] & CFQAS) != 0)
! 6854: user_tinfo->ppr_options |= MSG_EXT_PPR_QAS_REQ;
! 6855:
! 6856: if ((sc->device_flags[targ] & CFWIDEB) != 0)
! 6857: user_tinfo->width = MSG_EXT_WDTR_BUS_16_BIT;
! 6858: else
! 6859: user_tinfo->width = MSG_EXT_WDTR_BUS_8_BIT;
! 6860: #ifdef AHD_DEBUG
! 6861: if ((ahd_debug & AHD_SHOW_MISC) != 0)
! 6862: printf("(%d): %x:%x:%x:%x\n", targ, user_tinfo->width,
! 6863: user_tinfo->period, user_tinfo->offset,
! 6864: user_tinfo->ppr_options);
! 6865: #endif
! 6866: /*
! 6867: * Start out Async/Narrow/Untagged and with
! 6868: * conservative protocol support.
! 6869: */
! 6870: tstate->tagenable &= ~target_mask;
! 6871: tinfo->goal.protocol_version = 2;
! 6872: tinfo->goal.transport_version = 2;
! 6873: tinfo->curr.protocol_version = 2;
! 6874: tinfo->curr.transport_version = 2;
! 6875: ahd_compile_devinfo(&devinfo, ahd->our_id,
! 6876: targ, CAM_LUN_WILDCARD,
! 6877: 'A', ROLE_INITIATOR);
! 6878: ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
! 6879: AHD_TRANS_CUR|AHD_TRANS_GOAL, /*paused*/TRUE);
! 6880: ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0,
! 6881: /*ppr_options*/0, AHD_TRANS_CUR|AHD_TRANS_GOAL,
! 6882: /*paused*/TRUE);
! 6883: }
! 6884:
! 6885: ahd->flags &= ~AHD_SPCHK_ENB_A;
! 6886: if (sc->bios_control & CFSPARITY)
! 6887: ahd->flags |= AHD_SPCHK_ENB_A;
! 6888:
! 6889: ahd->flags &= ~AHD_RESET_BUS_A;
! 6890: if (sc->bios_control & CFRESETB)
! 6891: ahd->flags |= AHD_RESET_BUS_A;
! 6892:
! 6893: ahd->flags &= ~AHD_EXTENDED_TRANS_A;
! 6894: if (sc->bios_control & CFEXTEND)
! 6895: ahd->flags |= AHD_EXTENDED_TRANS_A;
! 6896:
! 6897: ahd->flags &= ~AHD_BIOS_ENABLED;
! 6898: if ((sc->bios_control & CFBIOSSTATE) == CFBS_ENABLED)
! 6899: ahd->flags |= AHD_BIOS_ENABLED;
! 6900:
! 6901: ahd->flags &= ~AHD_STPWLEVEL_A;
! 6902: if ((sc->adapter_control & CFSTPWLEVEL) != 0)
! 6903: ahd->flags |= AHD_STPWLEVEL_A;
! 6904:
! 6905: return (0);
! 6906: }
! 6907:
! 6908: /*
! 6909: * Parse device configuration information.
! 6910: */
! 6911: int
! 6912: ahd_parse_vpddata(struct ahd_softc *ahd, struct vpd_config *vpd)
! 6913: {
! 6914: int error;
! 6915:
! 6916: error = ahd_verify_vpd_cksum(vpd);
! 6917: if (error == 0)
! 6918: return (EINVAL);
! 6919: if ((vpd->bios_flags & VPDBOOTHOST) != 0)
! 6920: ahd->flags |= AHD_BOOT_CHANNEL;
! 6921: return (0);
! 6922: }
! 6923:
! 6924: void
! 6925: ahd_intr_enable(struct ahd_softc *ahd, int enable)
! 6926: {
! 6927: u_int hcntrl;
! 6928:
! 6929: hcntrl = ahd_inb(ahd, HCNTRL);
! 6930: hcntrl &= ~INTEN;
! 6931: ahd->pause &= ~INTEN;
! 6932: ahd->unpause &= ~INTEN;
! 6933: if (enable) {
! 6934: hcntrl |= INTEN;
! 6935: ahd->pause |= INTEN;
! 6936: ahd->unpause |= INTEN;
! 6937: }
! 6938: ahd_outb(ahd, HCNTRL, hcntrl);
! 6939: }
! 6940:
! 6941: void
! 6942: ahd_update_coalescing_values(struct ahd_softc *ahd, u_int timer, u_int maxcmds,
! 6943: u_int mincmds)
! 6944: {
! 6945: if (timer > AHD_TIMER_MAX_US)
! 6946: timer = AHD_TIMER_MAX_US;
! 6947: ahd->int_coalescing_timer = timer;
! 6948:
! 6949: if (maxcmds > AHD_INT_COALESCING_MAXCMDS_MAX)
! 6950: maxcmds = AHD_INT_COALESCING_MAXCMDS_MAX;
! 6951: if (mincmds > AHD_INT_COALESCING_MINCMDS_MAX)
! 6952: mincmds = AHD_INT_COALESCING_MINCMDS_MAX;
! 6953: ahd->int_coalescing_maxcmds = maxcmds;
! 6954: ahd_outw(ahd, INT_COALESCING_TIMER, timer / AHD_TIMER_US_PER_TICK);
! 6955: ahd_outb(ahd, INT_COALESCING_MAXCMDS, -maxcmds);
! 6956: ahd_outb(ahd, INT_COALESCING_MINCMDS, -mincmds);
! 6957: }
! 6958:
! 6959: void
! 6960: ahd_enable_coalescing(struct ahd_softc *ahd, int enable)
! 6961: {
! 6962:
! 6963: ahd->hs_mailbox &= ~ENINT_COALESCE;
! 6964: if (enable)
! 6965: ahd->hs_mailbox |= ENINT_COALESCE;
! 6966: ahd_outb(ahd, HS_MAILBOX, ahd->hs_mailbox);
! 6967: ahd_flush_device_writes(ahd);
! 6968: ahd_run_qoutfifo(ahd);
! 6969: }
! 6970:
! 6971: /*
! 6972: * Ensure that the card is paused in a location
! 6973: * outside of all critical sections and that all
! 6974: * pending work is completed prior to returning.
! 6975: * This routine should only be called from outside
! 6976: * an interrupt context.
! 6977: */
! 6978: void
! 6979: ahd_pause_and_flushwork(struct ahd_softc *ahd)
! 6980: {
! 6981: u_int intstat;
! 6982: u_int maxloops;
! 6983:
! 6984: maxloops = 1000;
! 6985: ahd->flags |= AHD_ALL_INTERRUPTS;
! 6986: ahd_pause(ahd);
! 6987: /*
! 6988: * Freeze the outgoing selections. We do this only
! 6989: * until we are safely paused without further selections
! 6990: * pending.
! 6991: */
! 6992: ahd->qfreeze_cnt--;
! 6993: ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
! 6994: ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN);
! 6995: do {
! 6996:
! 6997: ahd_unpause(ahd);
! 6998: /*
! 6999: * Give the sequencer some time to service
! 7000: * any active selections.
! 7001: */
! 7002: aic_delay(500);
! 7003:
! 7004: ahd_intr(ahd);
! 7005: ahd_pause(ahd);
! 7006: intstat = ahd_inb(ahd, INTSTAT);
! 7007: if ((intstat & INT_PEND) == 0) {
! 7008: ahd_clear_critical_section(ahd);
! 7009: intstat = ahd_inb(ahd, INTSTAT);
! 7010: }
! 7011: } while (--maxloops
! 7012: && (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0)
! 7013: && ((intstat & INT_PEND) != 0
! 7014: || (ahd_inb(ahd, SCSISEQ0) & ENSELO) != 0
! 7015: || (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0));
! 7016:
! 7017: if (maxloops == 0) {
! 7018: printf("Infinite interrupt loop, INTSTAT = %x",
! 7019: ahd_inb(ahd, INTSTAT));
! 7020: }
! 7021: ahd->qfreeze_cnt++;
! 7022: ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
! 7023:
! 7024: ahd_flush_qoutfifo(ahd);
! 7025:
! 7026: ahd_platform_flushwork(ahd);
! 7027: ahd->flags &= ~AHD_ALL_INTERRUPTS;
! 7028: }
! 7029:
! 7030: int
! 7031: ahd_suspend(struct ahd_softc *ahd)
! 7032: {
! 7033:
! 7034: ahd_pause_and_flushwork(ahd);
! 7035:
! 7036: if (LIST_FIRST(&ahd->pending_scbs) != NULL) {
! 7037: ahd_unpause(ahd);
! 7038: return (EBUSY);
! 7039: }
! 7040: ahd_shutdown(ahd);
! 7041: return (0);
! 7042: }
! 7043:
! 7044: int
! 7045: ahd_resume(struct ahd_softc *ahd)
! 7046: {
! 7047:
! 7048: ahd_reset(ahd, /*reinit*/TRUE);
! 7049: ahd_intr_enable(ahd, TRUE);
! 7050: ahd_restart(ahd);
! 7051: return (0);
! 7052: }
! 7053:
! 7054: /************************** Busy Target Table *********************************/
! 7055: /*
! 7056: * Set SCBPTR to the SCB that contains the busy
! 7057: * table entry for TCL. Return the offset into
! 7058: * the SCB that contains the entry for TCL.
! 7059: * saved_scbid is dereferenced and set to the
! 7060: * scbid that should be restored once manipualtion
! 7061: * of the TCL entry is complete.
! 7062: */
! 7063: __inline u_int ahd_index_busy_tcl(struct ahd_softc *, u_int *, u_int);
! 7064: __inline u_int
! 7065: ahd_index_busy_tcl(struct ahd_softc *ahd, u_int *saved_scbid, u_int tcl)
! 7066: {
! 7067: /*
! 7068: * Index to the SCB that contains the busy entry.
! 7069: */
! 7070: AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
! 7071: *saved_scbid = ahd_get_scbptr(ahd);
! 7072: ahd_set_scbptr(ahd, TCL_LUN(tcl)
! 7073: | ((TCL_TARGET_OFFSET(tcl) & 0xC) << 4));
! 7074:
! 7075: /*
! 7076: * And now calculate the SCB offset to the entry.
! 7077: * Each entry is 2 bytes wide, hence the
! 7078: * multiplication by 2.
! 7079: */
! 7080: return (((TCL_TARGET_OFFSET(tcl) & 0x3) << 1) + SCB_DISCONNECTED_LISTS);
! 7081: }
! 7082:
! 7083: /*
! 7084: * Return the untagged transaction id for a given target/channel lun.
! 7085: */
! 7086: u_int
! 7087: ahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl)
! 7088: {
! 7089: u_int scbid;
! 7090: u_int scb_offset;
! 7091: u_int saved_scbptr;
! 7092:
! 7093: scb_offset = ahd_index_busy_tcl(ahd, &saved_scbptr, tcl);
! 7094: scbid = ahd_inw_scbram(ahd, scb_offset);
! 7095: ahd_set_scbptr(ahd, saved_scbptr);
! 7096: return (scbid);
! 7097: }
! 7098:
! 7099: void
! 7100: ahd_busy_tcl(struct ahd_softc *ahd, u_int tcl, u_int scbid)
! 7101: {
! 7102: u_int scb_offset;
! 7103: u_int saved_scbptr;
! 7104:
! 7105: scb_offset = ahd_index_busy_tcl(ahd, &saved_scbptr, tcl);
! 7106: ahd_outw(ahd, scb_offset, scbid);
! 7107: ahd_set_scbptr(ahd, saved_scbptr);
! 7108: }
! 7109:
! 7110: /************************** SCB and SCB queue management **********************/
! 7111: int
! 7112: ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, int target,
! 7113: char channel, int lun, u_int tag, role_t role)
! 7114: {
! 7115: int targ = SCB_GET_TARGET(ahd, scb);
! 7116: char chan = SCB_GET_CHANNEL(ahd, scb);
! 7117: int slun = SCB_GET_LUN(scb);
! 7118: int match;
! 7119:
! 7120: match = ((chan == channel) || (channel == ALL_CHANNELS));
! 7121: if (match != 0)
! 7122: match = ((targ == target) || (target == CAM_TARGET_WILDCARD));
! 7123: if (match != 0)
! 7124: match = ((lun == slun) || (lun == CAM_LUN_WILDCARD));
! 7125: if (match != 0) {
! 7126: #if AHD_TARGET_MODE
! 7127: int group;
! 7128:
! 7129: group = XPT_FC_GROUP(scb->io_ctx->ccb_h.func_code);
! 7130: if (role == ROLE_INITIATOR) {
! 7131: match = (group != XPT_FC_GROUP_TMODE)
! 7132: && ((tag == SCB_GET_TAG(scb))
! 7133: || (tag == SCB_LIST_NULL));
! 7134: } else if (role == ROLE_TARGET) {
! 7135: match = (group == XPT_FC_GROUP_TMODE)
! 7136: && ((tag == scb->io_ctx->csio.tag_id)
! 7137: || (tag == SCB_LIST_NULL));
! 7138: }
! 7139: #else /* !AHD_TARGET_MODE */
! 7140: match = ((tag == SCB_GET_TAG(scb)) || (tag == SCB_LIST_NULL));
! 7141: #endif /* AHD_TARGET_MODE */
! 7142: }
! 7143:
! 7144: return match;
! 7145: }
! 7146:
! 7147: void
! 7148: ahd_freeze_devq(struct ahd_softc *ahd, struct scb *scb)
! 7149: {
! 7150: int target;
! 7151: char channel;
! 7152: int lun;
! 7153:
! 7154: target = SCB_GET_TARGET(ahd, scb);
! 7155: lun = SCB_GET_LUN(scb);
! 7156: channel = SCB_GET_CHANNEL(ahd, scb);
! 7157:
! 7158: ahd_search_qinfifo(ahd, target, channel, lun,
! 7159: /*tag*/SCB_LIST_NULL, ROLE_UNKNOWN,
! 7160: CAM_REQUEUE_REQ, SEARCH_COMPLETE);
! 7161:
! 7162: ahd_platform_freeze_devq(ahd, scb);
! 7163: }
! 7164:
! 7165: void
! 7166: ahd_qinfifo_requeue_tail(struct ahd_softc *ahd, struct scb *scb)
! 7167: {
! 7168: struct scb *prev_scb;
! 7169: ahd_mode_state saved_modes;
! 7170:
! 7171: saved_modes = ahd_save_modes(ahd);
! 7172: ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
! 7173: prev_scb = NULL;
! 7174: if (ahd_qinfifo_count(ahd) != 0) {
! 7175: u_int prev_tag;
! 7176: u_int prev_pos;
! 7177:
! 7178: prev_pos = AHD_QIN_WRAP(ahd->qinfifonext - 1);
! 7179: prev_tag = ahd->qinfifo[prev_pos];
! 7180: prev_scb = ahd_lookup_scb(ahd, prev_tag);
! 7181: }
! 7182: ahd_qinfifo_requeue(ahd, prev_scb, scb);
! 7183: ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
! 7184: ahd_restore_modes(ahd, saved_modes);
! 7185: }
! 7186:
! 7187: void
! 7188: ahd_qinfifo_requeue(struct ahd_softc *ahd, struct scb *prev_scb,
! 7189: struct scb *scb)
! 7190: {
! 7191: if (prev_scb == NULL) {
! 7192: uint32_t busaddr;
! 7193:
! 7194: busaddr = aic_le32toh(scb->hscb->hscb_busaddr);
! 7195: ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
! 7196: } else {
! 7197: prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
! 7198: ahd_sync_scb(ahd, prev_scb,
! 7199: BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 7200: }
! 7201: ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb);
! 7202: ahd->qinfifonext++;
! 7203: scb->hscb->next_hscb_busaddr = ahd->next_queued_hscb->hscb_busaddr;
! 7204: ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 7205: }
! 7206:
! 7207: int
! 7208: ahd_qinfifo_count(struct ahd_softc *ahd)
! 7209: {
! 7210: u_int qinpos;
! 7211: u_int wrap_qinpos;
! 7212: u_int wrap_qinfifonext;
! 7213:
! 7214: AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
! 7215: qinpos = ahd_get_snscb_qoff(ahd);
! 7216: wrap_qinpos = AHD_QIN_WRAP(qinpos);
! 7217: wrap_qinfifonext = AHD_QIN_WRAP(ahd->qinfifonext);
! 7218: if (wrap_qinfifonext >= wrap_qinpos)
! 7219: return (wrap_qinfifonext - wrap_qinpos);
! 7220: else
! 7221: return (wrap_qinfifonext
! 7222: + NUM_ELEMENTS(ahd->qinfifo) - wrap_qinpos);
! 7223: }
! 7224:
! 7225: void
! 7226: ahd_reset_cmds_pending(struct ahd_softc *ahd)
! 7227: {
! 7228: struct scb *scb;
! 7229: ahd_mode_state saved_modes;
! 7230: u_int pending_cmds;
! 7231:
! 7232: saved_modes = ahd_save_modes(ahd);
! 7233: ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
! 7234:
! 7235: /*
! 7236: * Don't count any commands as outstanding that the
! 7237: * sequencer has already marked for completion.
! 7238: */
! 7239: ahd_flush_qoutfifo(ahd);
! 7240:
! 7241: pending_cmds = 0;
! 7242: LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
! 7243: pending_cmds++;
! 7244: }
! 7245: ahd_outw(ahd, CMDS_PENDING, pending_cmds - ahd_qinfifo_count(ahd));
! 7246: ahd_restore_modes(ahd, saved_modes);
! 7247: ahd->flags &= ~AHD_UPDATE_PEND_CMDS;
! 7248: }
! 7249:
! 7250: void
! 7251: ahd_done_with_status(struct ahd_softc *ahd, struct scb *scb, uint32_t status)
! 7252: {
! 7253: cam_status ostat;
! 7254: cam_status cstat;
! 7255:
! 7256: ostat = aic_get_transaction_status(scb);
! 7257: if (ostat == CAM_REQ_INPROG)
! 7258: aic_set_transaction_status(scb, status);
! 7259: cstat = aic_get_transaction_status(scb);
! 7260: if (cstat != CAM_REQ_CMP)
! 7261: aic_freeze_scb(scb);
! 7262: ahd_done(ahd, scb);
! 7263: }
! 7264:
! 7265: int
! 7266: ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
! 7267: int lun, u_int tag, role_t role, uint32_t status,
! 7268: ahd_search_action action)
! 7269: {
! 7270: struct scb *scb;
! 7271: struct scb *mk_msg_scb;
! 7272: struct scb *prev_scb;
! 7273: ahd_mode_state saved_modes;
! 7274: u_int qinstart;
! 7275: u_int qinpos;
! 7276: u_int qintail;
! 7277: u_int tid_next;
! 7278: u_int tid_prev;
! 7279: u_int scbid;
! 7280: u_int seq_flags2;
! 7281: u_int savedscbptr;
! 7282: uint32_t busaddr;
! 7283: int found;
! 7284: int targets;
! 7285:
! 7286: /* Must be in CCHAN mode */
! 7287: saved_modes = ahd_save_modes(ahd);
! 7288: ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
! 7289:
! 7290: /*
! 7291: * Halt any pending SCB DMA. The sequencer will reinitiate
! 7292: * this dma if the qinfifo is not empty once we unpause.
! 7293: */
! 7294: if ((ahd_inb(ahd, CCSCBCTL) & (CCARREN|CCSCBEN|CCSCBDIR))
! 7295: == (CCARREN|CCSCBEN|CCSCBDIR)) {
! 7296: ahd_outb(ahd, CCSCBCTL,
! 7297: ahd_inb(ahd, CCSCBCTL) & ~(CCARREN|CCSCBEN));
! 7298: while ((ahd_inb(ahd, CCSCBCTL) & (CCARREN|CCSCBEN)) != 0)
! 7299: ;
! 7300: }
! 7301: /* Determine sequencer's position in the qinfifo. */
! 7302: qintail = AHD_QIN_WRAP(ahd->qinfifonext);
! 7303: qinstart = ahd_get_snscb_qoff(ahd);
! 7304: qinpos = AHD_QIN_WRAP(qinstart);
! 7305: found = 0;
! 7306: prev_scb = NULL;
! 7307:
! 7308: if (action == SEARCH_PRINT) {
! 7309: printf("qinstart = %d qinfifonext = %d\nQINFIFO:",
! 7310: qinstart, ahd->qinfifonext);
! 7311: }
! 7312:
! 7313: /*
! 7314: * Start with an empty queue. Entries that are not chosen
! 7315: * for removal will be re-added to the queue as we go.
! 7316: */
! 7317: ahd->qinfifonext = qinstart;
! 7318: busaddr = aic_le32toh(ahd->next_queued_hscb->hscb_busaddr);
! 7319: ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);
! 7320:
! 7321: while (qinpos != qintail) {
! 7322: scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]);
! 7323: if (scb == NULL) {
! 7324: printf("qinpos = %d, SCB index = %d\n",
! 7325: qinpos, ahd->qinfifo[qinpos]);
! 7326: panic("Loop 1");
! 7327: }
! 7328:
! 7329: if (ahd_match_scb(ahd, scb, target, channel, lun, tag, role)) {
! 7330: /*
! 7331: * We found an scb that needs to be acted on.
! 7332: */
! 7333: found++;
! 7334: switch (action) {
! 7335: case SEARCH_COMPLETE:
! 7336: if ((scb->flags & SCB_ACTIVE) == 0)
! 7337: printf("Inactive SCB in qinfifo\n");
! 7338: ahd_done_with_status(ahd, scb, status);
! 7339: /* FALLTHROUGH */
! 7340: case SEARCH_REMOVE:
! 7341: break;
! 7342: case SEARCH_PRINT:
! 7343: printf(" 0x%x", ahd->qinfifo[qinpos]);
! 7344: /* FALLTHROUGH */
! 7345: case SEARCH_COUNT:
! 7346: ahd_qinfifo_requeue(ahd, prev_scb, scb);
! 7347: prev_scb = scb;
! 7348: break;
! 7349: }
! 7350: } else {
! 7351: ahd_qinfifo_requeue(ahd, prev_scb, scb);
! 7352: prev_scb = scb;
! 7353: }
! 7354: qinpos = AHD_QIN_WRAP(qinpos+1);
! 7355: }
! 7356:
! 7357: ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
! 7358:
! 7359: if (action == SEARCH_PRINT)
! 7360: printf("\nWAITING_TID_QUEUES:\n");
! 7361:
! 7362: /*
! 7363: * Search waiting for selection lists. We traverse the
! 7364: * list of "their ids" waiting for selection and, if
! 7365: * appropriate, traverse the SCBs of each "their id"
! 7366: * looking for matches.
! 7367: */
! 7368: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 7369: seq_flags2 = ahd_inb(ahd, SEQ_FLAGS2);
! 7370: if ((seq_flags2 & PENDING_MK_MESSAGE) != 0) {
! 7371: scbid = ahd_inw(ahd, MK_MESSAGE_SCB);
! 7372: mk_msg_scb = ahd_lookup_scb(ahd, scbid);
! 7373: } else
! 7374: mk_msg_scb = NULL;
! 7375: savedscbptr = ahd_get_scbptr(ahd);
! 7376: tid_next = ahd_inw(ahd, WAITING_TID_HEAD);
! 7377: tid_prev = SCB_LIST_NULL;
! 7378: targets = 0;
! 7379: for (scbid = tid_next; !SCBID_IS_NULL(scbid); scbid = tid_next) {
! 7380: u_int tid_head;
! 7381: u_int tid_tail;
! 7382:
! 7383: targets++;
! 7384: if (targets > AHD_NUM_TARGETS)
! 7385: panic("TID LIST LOOP");
! 7386:
! 7387: if (scbid >= ahd->scb_data.numscbs) {
! 7388: printf("%s: Waiting TID List inconsistency. "
! 7389: "SCB index == 0x%x, yet numscbs == 0x%x.",
! 7390: ahd_name(ahd), scbid, ahd->scb_data.numscbs);
! 7391: ahd_dump_card_state(ahd);
! 7392: panic("for safety");
! 7393: }
! 7394: scb = ahd_lookup_scb(ahd, scbid);
! 7395: if (scb == NULL) {
! 7396: printf("%s: SCB = 0x%x Not Active!\n",
! 7397: ahd_name(ahd), scbid);
! 7398: panic("Waiting TID List traversal");
! 7399: }
! 7400: ahd_set_scbptr(ahd, scbid);
! 7401: tid_next = ahd_inw_scbram(ahd, SCB_NEXT2);
! 7402: if (ahd_match_scb(ahd, scb, target, channel, CAM_LUN_WILDCARD,
! 7403: SCB_LIST_NULL, ROLE_UNKNOWN) == 0) {
! 7404: tid_prev = scbid;
! 7405: continue;
! 7406: }
! 7407:
! 7408: /*
! 7409: * We found a list of scbs that needs to be searched.
! 7410: */
! 7411: if (action == SEARCH_PRINT)
! 7412: printf(" %d ( ", SCB_GET_TARGET(ahd, scb));
! 7413: tid_head = scbid;
! 7414: found += ahd_search_scb_list(ahd, target, channel,
! 7415: lun, tag, role, status,
! 7416: action, &tid_head, &tid_tail,
! 7417: SCB_GET_TARGET(ahd, scb));
! 7418: /*
! 7419: * Check any MK_MESSAGE SCB that is still waiting to
! 7420: * enter this target's waiting for selection queue.
! 7421: */
! 7422: if (mk_msg_scb != NULL
! 7423: && ahd_match_scb(ahd, mk_msg_scb, target, channel,
! 7424: lun, tag, role)) {
! 7425:
! 7426: /*
! 7427: * We found an scb that needs to be acted on.
! 7428: */
! 7429: found++;
! 7430: switch (action) {
! 7431: case SEARCH_COMPLETE:
! 7432: if ((mk_msg_scb->flags & SCB_ACTIVE) == 0)
! 7433: printf("Inactive SCB pending MK_MSG\n");
! 7434: ahd_done_with_status(ahd, mk_msg_scb, status);
! 7435: /* FALLTHROUGH */
! 7436: case SEARCH_REMOVE:
! 7437: {
! 7438: u_int tail_offset;
! 7439:
! 7440: printf("Removing MK_MSG scb\n");
! 7441:
! 7442: /*
! 7443: * Reset our tail to the tail of the
! 7444: * main per-target list.
! 7445: */
! 7446: tail_offset = WAITING_SCB_TAILS
! 7447: + (2 * SCB_GET_TARGET(ahd, mk_msg_scb));
! 7448: ahd_outw(ahd, tail_offset, tid_tail);
! 7449:
! 7450: seq_flags2 &= ~PENDING_MK_MESSAGE;
! 7451: ahd_outb(ahd, SEQ_FLAGS2, seq_flags2);
! 7452: ahd_outw(ahd, CMDS_PENDING,
! 7453: ahd_inw(ahd, CMDS_PENDING)-1);
! 7454: mk_msg_scb = NULL;
! 7455: break;
! 7456: }
! 7457: case SEARCH_PRINT:
! 7458: printf(" 0x%x", SCB_GET_TAG(scb));
! 7459: /* FALLTHROUGH */
! 7460: case SEARCH_COUNT:
! 7461: break;
! 7462: }
! 7463: }
! 7464:
! 7465: if (mk_msg_scb != NULL
! 7466: && SCBID_IS_NULL(tid_head)
! 7467: && ahd_match_scb(ahd, scb, target, channel, CAM_LUN_WILDCARD,
! 7468: SCB_LIST_NULL, ROLE_UNKNOWN)) {
! 7469:
! 7470: /*
! 7471: * When removing the last SCB for a target
! 7472: * queue with a pending MK_MESSAGE scb, we
! 7473: * must queue the MK_MESSAGE scb.
! 7474: */
! 7475: printf("Queueing mk_msg_scb\n");
! 7476: tid_head = ahd_inw(ahd, MK_MESSAGE_SCB);
! 7477: seq_flags2 &= ~PENDING_MK_MESSAGE;
! 7478: ahd_outb(ahd, SEQ_FLAGS2, seq_flags2);
! 7479: mk_msg_scb = NULL;
! 7480: }
! 7481: if (tid_head != scbid)
! 7482: ahd_stitch_tid_list(ahd, tid_prev, tid_head, tid_next);
! 7483: if (!SCBID_IS_NULL(tid_head))
! 7484: tid_prev = tid_head;
! 7485: if (action == SEARCH_PRINT)
! 7486: printf(")\n");
! 7487: }
! 7488:
! 7489: /* Restore saved state. */
! 7490: ahd_set_scbptr(ahd, savedscbptr);
! 7491: ahd_restore_modes(ahd, saved_modes);
! 7492: return (found);
! 7493: }
! 7494:
! 7495: int
! 7496: ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel,
! 7497: int lun, u_int tag, role_t role, uint32_t status,
! 7498: ahd_search_action action, u_int *list_head,
! 7499: u_int *list_tail, u_int tid)
! 7500: {
! 7501: struct scb *scb;
! 7502: u_int scbid;
! 7503: u_int next;
! 7504: u_int prev;
! 7505: int found;
! 7506:
! 7507: AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
! 7508: found = 0;
! 7509: prev = SCB_LIST_NULL;
! 7510: next = *list_head;
! 7511: *list_tail = SCB_LIST_NULL;
! 7512: for (scbid = next; !SCBID_IS_NULL(scbid); scbid = next) {
! 7513: if (scbid >= ahd->scb_data.numscbs) {
! 7514: printf("%s:SCB List inconsistency. "
! 7515: "SCB == 0x%x, yet numscbs == 0x%x.",
! 7516: ahd_name(ahd), scbid, ahd->scb_data.numscbs);
! 7517: ahd_dump_card_state(ahd);
! 7518: panic("for safety");
! 7519: }
! 7520: scb = ahd_lookup_scb(ahd, scbid);
! 7521: if (scb == NULL) {
! 7522: printf("%s: SCB = %d Not Active!\n",
! 7523: ahd_name(ahd), scbid);
! 7524: panic("Waiting List traversal");
! 7525: }
! 7526: ahd_set_scbptr(ahd, scbid);
! 7527: *list_tail = scbid;
! 7528: next = ahd_inw_scbram(ahd, SCB_NEXT);
! 7529: if (ahd_match_scb(ahd, scb, target, channel,
! 7530: lun, SCB_LIST_NULL, role) == 0) {
! 7531: prev = scbid;
! 7532: continue;
! 7533: }
! 7534: found++;
! 7535: switch (action) {
! 7536: case SEARCH_COMPLETE:
! 7537: if ((scb->flags & SCB_ACTIVE) == 0)
! 7538: printf("Inactive SCB in Waiting List\n");
! 7539: ahd_done_with_status(ahd, scb, status);
! 7540: /* FALLTHROUGH */
! 7541: case SEARCH_REMOVE:
! 7542: ahd_rem_wscb(ahd, scbid, prev, next, tid);
! 7543: *list_tail = prev;
! 7544: if (SCBID_IS_NULL(prev))
! 7545: *list_head = next;
! 7546: break;
! 7547: case SEARCH_PRINT:
! 7548: printf("0x%x ", scbid);
! 7549: case SEARCH_COUNT:
! 7550: prev = scbid;
! 7551: break;
! 7552: }
! 7553: if (found > AHD_SCB_MAX)
! 7554: panic("SCB LIST LOOP");
! 7555: }
! 7556: if (action == SEARCH_COMPLETE
! 7557: || action == SEARCH_REMOVE)
! 7558: ahd_outw(ahd, CMDS_PENDING, ahd_inw(ahd, CMDS_PENDING) - found);
! 7559: return (found);
! 7560: }
! 7561:
! 7562: void
! 7563: ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev,
! 7564: u_int tid_cur, u_int tid_next)
! 7565: {
! 7566: AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
! 7567:
! 7568: if (SCBID_IS_NULL(tid_cur)) {
! 7569:
! 7570: /* Bypass current TID list */
! 7571: if (SCBID_IS_NULL(tid_prev)) {
! 7572: ahd_outw(ahd, WAITING_TID_HEAD, tid_next);
! 7573: } else {
! 7574: ahd_set_scbptr(ahd, tid_prev);
! 7575: ahd_outw(ahd, SCB_NEXT2, tid_next);
! 7576: }
! 7577: if (SCBID_IS_NULL(tid_next))
! 7578: ahd_outw(ahd, WAITING_TID_TAIL, tid_prev);
! 7579: } else {
! 7580:
! 7581: /* Stitch through tid_cur */
! 7582: if (SCBID_IS_NULL(tid_prev)) {
! 7583: ahd_outw(ahd, WAITING_TID_HEAD, tid_cur);
! 7584: } else {
! 7585: ahd_set_scbptr(ahd, tid_prev);
! 7586: ahd_outw(ahd, SCB_NEXT2, tid_cur);
! 7587: }
! 7588: ahd_set_scbptr(ahd, tid_cur);
! 7589: ahd_outw(ahd, SCB_NEXT2, tid_next);
! 7590:
! 7591: if (SCBID_IS_NULL(tid_next))
! 7592: ahd_outw(ahd, WAITING_TID_TAIL, tid_cur);
! 7593: }
! 7594: }
! 7595:
! 7596: /*
! 7597: * Manipulate the waiting for selection list and return the
! 7598: * scb that follows the one that we remove.
! 7599: */
! 7600: u_int
! 7601: ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid,
! 7602: u_int prev, u_int next, u_int tid)
! 7603: {
! 7604: u_int tail_offset;
! 7605:
! 7606: AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
! 7607: if (!SCBID_IS_NULL(prev)) {
! 7608: ahd_set_scbptr(ahd, prev);
! 7609: ahd_outw(ahd, SCB_NEXT, next);
! 7610: }
! 7611:
! 7612: /*
! 7613: * SCBs that have MK_MESSAGE set in them may
! 7614: * cause the tail pointer to be updated without
! 7615: * setting the next pointer of the previous tail.
! 7616: * Only clear the tail if the removed SCB was
! 7617: * the tail.
! 7618: */
! 7619: tail_offset = WAITING_SCB_TAILS + (2 * tid);
! 7620: if (SCBID_IS_NULL(next)
! 7621: && ahd_inw(ahd, tail_offset) == scbid)
! 7622: ahd_outw(ahd, tail_offset, prev);
! 7623:
! 7624: ahd_add_scb_to_free_list(ahd, scbid);
! 7625: return (next);
! 7626: }
! 7627:
! 7628: /*
! 7629: * Add the SCB as selected by SCBPTR onto the on chip list of
! 7630: * free hardware SCBs. This list is empty/unused if we are not
! 7631: * performing SCB paging.
! 7632: */
! 7633: void
! 7634: ahd_add_scb_to_free_list(struct ahd_softc *ahd, u_int scbid)
! 7635: {
! 7636: /* XXX Need some other mechanism to designate "free". */
! 7637: /*
! 7638: * Invalidate the tag so that our abort
! 7639: * routines don't think it's active.
! 7640: ahd_outb(ahd, SCB_TAG, SCB_LIST_NULL);
! 7641: */
! 7642: }
! 7643:
! 7644: /******************************** Error Handling ******************************/
! 7645: /*
! 7646: * Abort all SCBs that match the given description (target/channel/lun/tag),
! 7647: * setting their status to the passed in status if the status has not already
! 7648: * been modified from CAM_REQ_INPROG. This routine assumes that the sequencer
! 7649: * is paused before it is called.
! 7650: */
! 7651: int
! 7652: ahd_abort_scbs(struct ahd_softc *ahd, int target, char channel,
! 7653: int lun, u_int tag, role_t role, uint32_t status)
! 7654: {
! 7655: struct scb *scbp;
! 7656: struct scb *scbp_next;
! 7657: u_int i, j;
! 7658: u_int maxtarget;
! 7659: u_int minlun;
! 7660: u_int maxlun;
! 7661: int found;
! 7662: ahd_mode_state saved_modes;
! 7663:
! 7664: /* restore this when we're done */
! 7665: saved_modes = ahd_save_modes(ahd);
! 7666: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 7667:
! 7668: found = ahd_search_qinfifo(ahd, target, channel, lun, SCB_LIST_NULL,
! 7669: role, CAM_REQUEUE_REQ, SEARCH_COMPLETE);
! 7670:
! 7671: /*
! 7672: * Clean out the busy target table for any untagged commands.
! 7673: */
! 7674: i = 0;
! 7675: maxtarget = 16;
! 7676: if (target != CAM_TARGET_WILDCARD) {
! 7677: i = target;
! 7678: if (channel == 'B')
! 7679: i += 8;
! 7680: maxtarget = i + 1;
! 7681: }
! 7682:
! 7683: if (lun == CAM_LUN_WILDCARD) {
! 7684: minlun = 0;
! 7685: maxlun = AHD_NUM_LUNS_NONPKT;
! 7686: } else if (lun >= AHD_NUM_LUNS_NONPKT) {
! 7687: minlun = maxlun = 0;
! 7688: } else {
! 7689: minlun = lun;
! 7690: maxlun = lun + 1;
! 7691: }
! 7692:
! 7693: if (role != ROLE_TARGET) {
! 7694: for (;i < maxtarget; i++) {
! 7695: for (j = minlun;j < maxlun; j++) {
! 7696: u_int scbid;
! 7697: u_int tcl;
! 7698:
! 7699: tcl = BUILD_TCL_RAW(i, 'A', j);
! 7700: scbid = ahd_find_busy_tcl(ahd, tcl);
! 7701: scbp = ahd_lookup_scb(ahd, scbid);
! 7702: if (scbp == NULL
! 7703: || ahd_match_scb(ahd, scbp, target, channel,
! 7704: lun, tag, role) == 0)
! 7705: continue;
! 7706: ahd_unbusy_tcl(ahd, BUILD_TCL_RAW(i, 'A', j));
! 7707: }
! 7708: }
! 7709: }
! 7710:
! 7711: /*
! 7712: * Don't abort commands that have already completed,
! 7713: * but haven't quite made it up to the host yet.
! 7714: */
! 7715: ahd_flush_qoutfifo(ahd);
! 7716:
! 7717: /*
! 7718: * Go through the pending CCB list and look for
! 7719: * commands for this target that are still active.
! 7720: * These are other tagged commands that were
! 7721: * disconnected when the reset occurred.
! 7722: */
! 7723: scbp_next = LIST_FIRST(&ahd->pending_scbs);
! 7724: while (scbp_next != NULL) {
! 7725: scbp = scbp_next;
! 7726: scbp_next = LIST_NEXT(scbp, pending_links);
! 7727: if (ahd_match_scb(ahd, scbp, target, channel, lun, tag, role)) {
! 7728: cam_status ostat;
! 7729:
! 7730: ostat = aic_get_transaction_status(scbp);
! 7731: if (ostat == CAM_REQ_INPROG)
! 7732: aic_set_transaction_status(scbp, status);
! 7733: if (aic_get_transaction_status(scbp) != CAM_REQ_CMP)
! 7734: aic_freeze_scb(scbp);
! 7735: if ((scbp->flags & SCB_ACTIVE) == 0)
! 7736: printf("Inactive SCB on pending list\n");
! 7737: ahd_done(ahd, scbp);
! 7738: found++;
! 7739: }
! 7740: }
! 7741: ahd_restore_modes(ahd, saved_modes);
! 7742: ahd_platform_abort_scbs(ahd, target, channel, lun, tag, role, status);
! 7743: ahd->flags |= AHD_UPDATE_PEND_CMDS;
! 7744: return found;
! 7745: }
! 7746:
! 7747: void
! 7748: ahd_reset_current_bus(struct ahd_softc *ahd)
! 7749: {
! 7750: uint8_t scsiseq;
! 7751:
! 7752: AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
! 7753: ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) & ~ENSCSIRST);
! 7754: scsiseq = ahd_inb(ahd, SCSISEQ0) & ~(ENSELO|ENARBO|SCSIRSTO);
! 7755: ahd_outb(ahd, SCSISEQ0, scsiseq | SCSIRSTO);
! 7756: ahd_flush_device_writes(ahd);
! 7757: aic_delay(AHD_BUSRESET_DELAY);
! 7758: /* Turn off the bus reset */
! 7759: ahd_outb(ahd, SCSISEQ0, scsiseq);
! 7760: ahd_flush_device_writes(ahd);
! 7761: aic_delay(AHD_BUSRESET_DELAY);
! 7762: if ((ahd->bugs & AHD_SCSIRST_BUG) != 0) {
! 7763: /*
! 7764: * 2A Razor #474
! 7765: * Certain chip state is not cleared for
! 7766: * SCSI bus resets that we initiate, so
! 7767: * we must reset the chip.
! 7768: */
! 7769: ahd_reset(ahd, /*reinit*/TRUE);
! 7770: ahd_intr_enable(ahd, /*enable*/TRUE);
! 7771: AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
! 7772: }
! 7773:
! 7774: ahd_clear_intstat(ahd);
! 7775: }
! 7776:
! 7777: int
! 7778: ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)
! 7779: {
! 7780: struct ahd_devinfo devinfo;
! 7781: u_int initiator;
! 7782: u_int target;
! 7783: u_int max_scsiid;
! 7784: int found;
! 7785: u_int fifo;
! 7786: u_int next_fifo;
! 7787:
! 7788: ahd->pending_device = NULL;
! 7789:
! 7790: ahd_compile_devinfo(&devinfo,
! 7791: CAM_TARGET_WILDCARD,
! 7792: CAM_TARGET_WILDCARD,
! 7793: CAM_LUN_WILDCARD,
! 7794: channel, ROLE_UNKNOWN);
! 7795: ahd_pause(ahd);
! 7796:
! 7797: /* Make sure the sequencer is in a safe location. */
! 7798: ahd_clear_critical_section(ahd);
! 7799:
! 7800: #if AHD_TARGET_MODE
! 7801: if ((ahd->flags & AHD_TARGETROLE) != 0) {
! 7802: ahd_run_tqinfifo(ahd, /*paused*/TRUE);
! 7803: }
! 7804: #endif
! 7805: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 7806:
! 7807: /*
! 7808: * Disable selections so no automatic hardware
! 7809: * functions will modify chip state.
! 7810: */
! 7811: ahd_outb(ahd, SCSISEQ0, 0);
! 7812: ahd_outb(ahd, SCSISEQ1, 0);
! 7813:
! 7814: /*
! 7815: * Safely shut down our DMA engines. Always start with
! 7816: * the FIFO that is not currently active (if any are
! 7817: * actively connected).
! 7818: */
! 7819: next_fifo = fifo = ahd_inb(ahd, DFFSTAT) & CURRFIFO;
! 7820: if (next_fifo > CURRFIFO_1)
! 7821: /* If disconneced, arbitrarily start with FIFO1. */
! 7822: next_fifo = fifo = 0;
! 7823: do {
! 7824: next_fifo ^= CURRFIFO_1;
! 7825: ahd_set_modes(ahd, next_fifo, next_fifo);
! 7826: ahd_outb(ahd, DFCNTRL,
! 7827: ahd_inb(ahd, DFCNTRL) & ~(SCSIEN|HDMAEN));
! 7828: while ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0)
! 7829: aic_delay(10);
! 7830: /*
! 7831: * Set CURRFIFO to the now inactive channel.
! 7832: */
! 7833: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 7834: ahd_outb(ahd, DFFSTAT, next_fifo);
! 7835: } while (next_fifo != fifo);
! 7836:
! 7837: /*
! 7838: * Reset the bus if we are initiating this reset
! 7839: */
! 7840: ahd_clear_msg_state(ahd);
! 7841: ahd_outb(ahd, SIMODE1,
! 7842: ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST));
! 7843:
! 7844: if (initiate_reset)
! 7845: ahd_reset_current_bus(ahd);
! 7846:
! 7847: ahd_clear_intstat(ahd);
! 7848:
! 7849: /*
! 7850: * Clean up all the state information for the
! 7851: * pending transactions on this bus.
! 7852: */
! 7853: found = ahd_abort_scbs(ahd, CAM_TARGET_WILDCARD, channel,
! 7854: CAM_LUN_WILDCARD, SCB_LIST_NULL,
! 7855: ROLE_UNKNOWN, CAM_SCSI_BUS_RESET);
! 7856:
! 7857: /*
! 7858: * Cleanup anything left in the FIFOs.
! 7859: */
! 7860: ahd_clear_fifo(ahd, 0);
! 7861: ahd_clear_fifo(ahd, 1);
! 7862:
! 7863: /*
! 7864: * Revert to async/narrow transfers until we renegotiate.
! 7865: */
! 7866: max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7;
! 7867: for (target = 0; target <= max_scsiid; target++) {
! 7868:
! 7869: if (ahd->enabled_targets[target] == NULL)
! 7870: continue;
! 7871: for (initiator = 0; initiator <= max_scsiid; initiator++) {
! 7872: struct ahd_devinfo devinfo;
! 7873:
! 7874: ahd_compile_devinfo(&devinfo, target, initiator,
! 7875: CAM_LUN_WILDCARD,
! 7876: 'A', ROLE_UNKNOWN);
! 7877: ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
! 7878: AHD_TRANS_CUR, /*paused*/TRUE);
! 7879: ahd_set_syncrate(ahd, &devinfo, /*period*/0,
! 7880: /*offset*/0, /*ppr_options*/0,
! 7881: AHD_TRANS_CUR, /*paused*/TRUE);
! 7882: }
! 7883: }
! 7884:
! 7885: #ifdef AHD_TARGET_MODE
! 7886: max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7;
! 7887:
! 7888: /*
! 7889: * Send an immediate notify ccb to all target more peripheral
! 7890: * drivers affected by this action.
! 7891: */
! 7892: for (target = 0; target <= max_scsiid; target++) {
! 7893: struct ahd_tmode_tstate* tstate;
! 7894: u_int lun;
! 7895:
! 7896: tstate = ahd->enabled_targets[target];
! 7897: if (tstate == NULL)
! 7898: continue;
! 7899: for (lun = 0; lun < AHD_NUM_LUNS; lun++) {
! 7900: struct ahd_tmode_lstate* lstate;
! 7901:
! 7902: lstate = tstate->enabled_luns[lun];
! 7903: if (lstate == NULL)
! 7904: continue;
! 7905:
! 7906: ahd_queue_lstate_event(ahd, lstate, CAM_TARGET_WILDCARD,
! 7907: EVENT_TYPE_BUS_RESET, /*arg*/0);
! 7908: ahd_send_lstate_events(ahd, lstate);
! 7909: }
! 7910: }
! 7911: #endif
! 7912: #if 0
! 7913: /* Notify the XPT that a bus reset occurred */
! 7914: ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD,
! 7915: CAM_LUN_WILDCARD, AC_BUS_RESET, NULL);
! 7916: #endif
! 7917: ahd_restart(ahd);
! 7918: /*
! 7919: * Freeze the SIMQ until our poller can determine that
! 7920: * the bus reset has really gone away. We set the initial
! 7921: * timer to 0 to have the check performed as soon as possible
! 7922: * from the timer context.
! 7923: */
! 7924: if ((ahd->flags & AHD_RESET_POLL_ACTIVE) == 0) {
! 7925: ahd->flags |= AHD_RESET_POLL_ACTIVE;
! 7926: aic_freeze_simq(ahd);
! 7927: aic_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd);
! 7928: }
! 7929: return (found);
! 7930: }
! 7931:
! 7932:
! 7933: #define AHD_RESET_POLL_MS 1
! 7934: void
! 7935: ahd_reset_poll(void *arg)
! 7936: {
! 7937: struct ahd_softc *ahd;
! 7938: u_int scsiseq1;
! 7939: int l;
! 7940: int s;
! 7941:
! 7942: ahd_list_lock(&l);
! 7943: ahd = ahd_find_softc((struct ahd_softc *)arg);
! 7944: if (ahd == NULL) {
! 7945: printf("ahd_reset_poll: Instance %p no longer exists\n", arg);
! 7946: ahd_list_unlock(&l);
! 7947: return;
! 7948: }
! 7949: ahd_lock(ahd, &s);
! 7950: ahd_pause(ahd);
! 7951: ahd_update_modes(ahd);
! 7952: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 7953: ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI);
! 7954: if ((ahd_inb(ahd, SSTAT1) & SCSIRSTI) != 0) {
! 7955: aic_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_MS,
! 7956: ahd_reset_poll, ahd);
! 7957: ahd_unpause(ahd);
! 7958: ahd_unlock(ahd, &s);
! 7959: ahd_list_unlock(&l);
! 7960: return;
! 7961: }
! 7962:
! 7963: /* Reset is now low. Complete chip reinitialization. */
! 7964: ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST);
! 7965: scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE);
! 7966: ahd_outb(ahd, SCSISEQ1, scsiseq1 & (ENSELI|ENRSELI|ENAUTOATNP));
! 7967: ahd_unpause(ahd);
! 7968: ahd->flags &= ~AHD_RESET_POLL_ACTIVE;
! 7969: ahd_unlock(ahd, &s);
! 7970: aic_release_simq(ahd);
! 7971: ahd_list_unlock(&l);
! 7972: }
! 7973:
! 7974: /**************************** Statistics Processing ***************************/
! 7975: void
! 7976: ahd_stat_timer(void *arg)
! 7977: {
! 7978: struct ahd_softc *ahd;
! 7979: int l;
! 7980: int s;
! 7981: int enint_coal;
! 7982:
! 7983: ahd_list_lock(&l);
! 7984: ahd = ahd_find_softc((struct ahd_softc *)arg);
! 7985: if (ahd == NULL) {
! 7986: printf("ahd_stat_timer: Instance %p no longer exists\n", arg);
! 7987: ahd_list_unlock(&l);
! 7988: return;
! 7989: }
! 7990: ahd_lock(ahd, &s);
! 7991:
! 7992: enint_coal = ahd->hs_mailbox & ENINT_COALESCE;
! 7993: if (ahd->cmdcmplt_total > ahd->int_coalescing_threshold)
! 7994: enint_coal |= ENINT_COALESCE;
! 7995: else if (ahd->cmdcmplt_total < ahd->int_coalescing_stop_threshold)
! 7996: enint_coal &= ~ENINT_COALESCE;
! 7997:
! 7998: if (enint_coal != (ahd->hs_mailbox & ENINT_COALESCE)) {
! 7999: ahd_enable_coalescing(ahd, enint_coal);
! 8000: #ifdef AHD_DEBUG
! 8001: if ((ahd_debug & AHD_SHOW_INT_COALESCING) != 0)
! 8002: printf("%s: Interrupt coalescing "
! 8003: "now %sabled. Cmds %d\n",
! 8004: ahd_name(ahd),
! 8005: (enint_coal & ENINT_COALESCE) ? "en" : "dis",
! 8006: ahd->cmdcmplt_total);
! 8007: #endif
! 8008: }
! 8009:
! 8010: ahd->cmdcmplt_bucket = (ahd->cmdcmplt_bucket+1) & (AHD_STAT_BUCKETS-1);
! 8011: ahd->cmdcmplt_total -= ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket];
! 8012: ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket] = 0;
! 8013: aic_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_MS,
! 8014: ahd_stat_timer, ahd);
! 8015: ahd_unlock(ahd, &s);
! 8016: ahd_list_unlock(&l);
! 8017: }
! 8018:
! 8019: /****************************** Status Processing *****************************/
! 8020: void
! 8021: ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb)
! 8022: {
! 8023: if (scb->hscb->shared_data.istatus.scsi_status != 0) {
! 8024: ahd_handle_scsi_status(ahd, scb);
! 8025: } else {
! 8026: ahd_calc_residual(ahd, scb);
! 8027: ahd_done(ahd, scb);
! 8028: }
! 8029: }
! 8030:
! 8031: void
! 8032: ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
! 8033: {
! 8034: struct hardware_scb *hscb;
! 8035: int paused;
! 8036:
! 8037: /*
! 8038: * The sequencer freezes its select-out queue
! 8039: * anytime a SCSI status error occurs. We must
! 8040: * handle the error and increment our qfreeze count
! 8041: * to allow the sequencer to continue. We don't
! 8042: * bother clearing critical sections here since all
! 8043: * operations are on data structures that the sequencer
! 8044: * is not touching once the queue is frozen.
! 8045: */
! 8046: hscb = scb->hscb;
! 8047:
! 8048: if (ahd_is_paused(ahd)) {
! 8049: paused = 1;
! 8050: } else {
! 8051: paused = 0;
! 8052: ahd_pause(ahd);
! 8053: }
! 8054:
! 8055: /* Freeze the queue until the client sees the error. */
! 8056: ahd_freeze_devq(ahd, scb);
! 8057: aic_freeze_scb(scb);
! 8058: ahd->qfreeze_cnt++;
! 8059: ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
! 8060:
! 8061: if (paused == 0)
! 8062: ahd_unpause(ahd);
! 8063:
! 8064: /* Don't want to clobber the original sense code */
! 8065: if ((scb->flags & SCB_SENSE) != 0) {
! 8066: /*
! 8067: * Clear the SCB_SENSE Flag and perform
! 8068: * a normal command completion.
! 8069: */
! 8070: scb->flags &= ~SCB_SENSE;
! 8071: aic_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
! 8072: ahd_done(ahd, scb);
! 8073: return;
! 8074: }
! 8075: aic_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR);
! 8076: aic_set_scsi_status(scb, hscb->shared_data.istatus.scsi_status);
! 8077: switch (hscb->shared_data.istatus.scsi_status) {
! 8078: case STATUS_PKT_SENSE:
! 8079: {
! 8080: struct scsi_status_iu_header *siu;
! 8081:
! 8082: ahd_sync_sense(ahd, scb, BUS_DMASYNC_POSTREAD);
! 8083: siu = (struct scsi_status_iu_header *)scb->sense_data;
! 8084: aic_set_scsi_status(scb, siu->status);
! 8085: #ifdef AHD_DEBUG
! 8086: if ((ahd_debug & AHD_SHOW_SENSE) != 0) {
! 8087: ahd_print_path(ahd, scb);
! 8088: printf("SCB 0x%x Received PKT Status of 0x%x\n",
! 8089: SCB_GET_TAG(scb), siu->status);
! 8090: printf("\tflags = 0x%x, sense len = 0x%x, "
! 8091: "pktfail = 0x%x\n",
! 8092: siu->flags, scsi_4btoul(siu->sense_length),
! 8093: scsi_4btoul(siu->pkt_failures_length));
! 8094: }
! 8095: #endif
! 8096: if ((siu->flags & SIU_RSPVALID) != 0) {
! 8097: ahd_print_path(ahd, scb);
! 8098: if (scsi_4btoul(siu->pkt_failures_length) < 4) {
! 8099: printf("Unable to parse pkt_failures\n");
! 8100: } else {
! 8101:
! 8102: switch (SIU_PKTFAIL_CODE(siu)) {
! 8103: case SIU_PFC_NONE:
! 8104: printf("No packet failure found\n");
! 8105: break;
! 8106: case SIU_PFC_CIU_FIELDS_INVALID:
! 8107: printf("Invalid Command IU Field\n");
! 8108: break;
! 8109: case SIU_PFC_TMF_NOT_SUPPORTED:
! 8110: printf("TMF not supportd\n");
! 8111: break;
! 8112: case SIU_PFC_TMF_FAILED:
! 8113: printf("TMF failed\n");
! 8114: break;
! 8115: case SIU_PFC_INVALID_TYPE_CODE:
! 8116: printf("Invalid L_Q Type code\n");
! 8117: break;
! 8118: case SIU_PFC_ILLEGAL_REQUEST:
! 8119: printf("Illegal request\n");
! 8120: default:
! 8121: break;
! 8122: }
! 8123: }
! 8124: if (siu->status == SCSI_STATUS_OK)
! 8125: aic_set_transaction_status(scb,
! 8126: CAM_REQ_CMP_ERR);
! 8127: }
! 8128: if ((siu->flags & SIU_SNSVALID) != 0) {
! 8129: scb->flags |= SCB_PKT_SENSE;
! 8130: #ifdef AHD_DEBUG
! 8131: if ((ahd_debug & AHD_SHOW_SENSE) != 0)
! 8132: printf("Sense data available\n");
! 8133: #endif
! 8134: }
! 8135: ahd_done(ahd, scb);
! 8136: break;
! 8137: }
! 8138: case SCSI_STATUS_CMD_TERMINATED:
! 8139: case SCSI_STATUS_CHECK_COND:
! 8140: {
! 8141: struct ahd_devinfo devinfo;
! 8142: struct ahd_dma_seg *sg;
! 8143: struct scsi_sense *sc;
! 8144: struct ahd_initiator_tinfo *targ_info;
! 8145: struct ahd_tmode_tstate *tstate;
! 8146: struct ahd_transinfo *tinfo;
! 8147: #ifdef AHD_DEBUG
! 8148: if (ahd_debug & AHD_SHOW_SENSE) {
! 8149: ahd_print_path(ahd, scb);
! 8150: printf("SCB %d: requests Check Status\n",
! 8151: SCB_GET_TAG(scb));
! 8152: }
! 8153: #endif
! 8154:
! 8155: if (aic_perform_autosense(scb) == 0)
! 8156: break;
! 8157:
! 8158: ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb),
! 8159: SCB_GET_TARGET(ahd, scb),
! 8160: SCB_GET_LUN(scb),
! 8161: SCB_GET_CHANNEL(ahd, scb),
! 8162: ROLE_INITIATOR);
! 8163: targ_info = ahd_fetch_transinfo(ahd,
! 8164: devinfo.channel,
! 8165: devinfo.our_scsiid,
! 8166: devinfo.target,
! 8167: &tstate);
! 8168: tinfo = &targ_info->curr;
! 8169: sg = scb->sg_list;
! 8170: sc = (struct scsi_sense *)hscb->shared_data.idata.cdb;
! 8171: /*
! 8172: * Save off the residual if there is one.
! 8173: */
! 8174: ahd_update_residual(ahd, scb);
! 8175: #ifdef AHD_DEBUG
! 8176: if (ahd_debug & AHD_SHOW_SENSE) {
! 8177: ahd_print_path(ahd, scb);
! 8178: printf("Sending Sense\n");
! 8179: }
! 8180: #endif
! 8181: scb->sg_count = 0;
! 8182: sg = ahd_sg_setup(ahd, scb, sg, ahd_get_sense_bufaddr(ahd, scb),
! 8183: aic_get_sense_bufsize(ahd, scb),
! 8184: /*last*/TRUE);
! 8185: sc->opcode = REQUEST_SENSE;
! 8186: sc->byte2 = 0;
! 8187: if (tinfo->protocol_version <= SCSI_REV_2
! 8188: && SCB_GET_LUN(scb) < 8)
! 8189: sc->byte2 = SCB_GET_LUN(scb) << 5;
! 8190: sc->unused[0] = 0;
! 8191: sc->unused[1] = 0;
! 8192: sc->length = aic_get_sense_bufsize(ahd, scb);
! 8193: sc->control = 0;
! 8194:
! 8195: /*
! 8196: * We can't allow the target to disconnect.
! 8197: * This will be an untagged transaction and
! 8198: * having the target disconnect will make this
! 8199: * transaction indestinguishable from outstanding
! 8200: * tagged transactions.
! 8201: */
! 8202: hscb->control = 0;
! 8203:
! 8204: /*
! 8205: * This request sense could be because the
! 8206: * the device lost power or in some other
! 8207: * way has lost our transfer negotiations.
! 8208: * Renegotiate if appropriate. Unit attention
! 8209: * errors will be reported before any data
! 8210: * phases occur.
! 8211: */
! 8212: if (aic_get_residual(scb) == aic_get_transfer_length(scb)) {
! 8213: ahd_update_neg_request(ahd, &devinfo,
! 8214: tstate, targ_info,
! 8215: AHD_NEG_IF_NON_ASYNC);
! 8216: }
! 8217: if (tstate->auto_negotiate & devinfo.target_mask) {
! 8218: hscb->control |= MK_MESSAGE;
! 8219: scb->flags &=
! 8220: ~(SCB_NEGOTIATE|SCB_ABORT|SCB_DEVICE_RESET);
! 8221: scb->flags |= SCB_AUTO_NEGOTIATE;
! 8222: }
! 8223: hscb->cdb_len = sizeof(*sc);
! 8224: ahd_setup_data_scb(ahd, scb);
! 8225: scb->flags |= SCB_SENSE;
! 8226: ahd_queue_scb(ahd, scb);
! 8227: /*
! 8228: * Ensure we have enough time to actually
! 8229: * retrieve the sense, but only schedule
! 8230: * the timer if we are not in recovery or
! 8231: * this is a recovery SCB that is allowed
! 8232: * to have an active timer.
! 8233: */
! 8234: aic_scb_timer_reset(scb, 5 * 1000);
! 8235: break;
! 8236: }
! 8237: case SCSI_STATUS_OK:
! 8238: printf("%s: Interrupted for staus of 0???\n",
! 8239: ahd_name(ahd));
! 8240: /* FALLTHROUGH */
! 8241: default:
! 8242: ahd_done(ahd, scb);
! 8243: break;
! 8244: }
! 8245: }
! 8246:
! 8247: /*
! 8248: * Calculate the residual for a just completed SCB.
! 8249: */
! 8250: void
! 8251: ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb)
! 8252: {
! 8253: struct hardware_scb *hscb;
! 8254: struct initiator_status *spkt;
! 8255: uint32_t sgptr;
! 8256: uint32_t resid_sgptr;
! 8257: uint32_t resid;
! 8258:
! 8259: /*
! 8260: * 5 cases.
! 8261: * 1) No residual.
! 8262: * SG_STATUS_VALID clear in sgptr.
! 8263: * 2) Transferless command
! 8264: * 3) Never performed any transfers.
! 8265: * sgptr has SG_FULL_RESID set.
! 8266: * 4) No residual but target did not
! 8267: * save data pointers after the
! 8268: * last transfer, so sgptr was
! 8269: * never updated.
! 8270: * 5) We have a partial residual.
! 8271: * Use residual_sgptr to determine
! 8272: * where we are.
! 8273: */
! 8274:
! 8275: hscb = scb->hscb;
! 8276: sgptr = aic_le32toh(hscb->sgptr);
! 8277: if ((sgptr & SG_STATUS_VALID) == 0)
! 8278: /* Case 1 */
! 8279: return;
! 8280: sgptr &= ~SG_STATUS_VALID;
! 8281:
! 8282: if ((sgptr & SG_LIST_NULL) != 0)
! 8283: /* Case 2 */
! 8284: return;
! 8285:
! 8286: /*
! 8287: * Residual fields are the same in both
! 8288: * target and initiator status packets,
! 8289: * so we can always use the initiator fields
! 8290: * regardless of the role for this SCB.
! 8291: */
! 8292: spkt = &hscb->shared_data.istatus;
! 8293: resid_sgptr = aic_le32toh(spkt->residual_sgptr);
! 8294: if ((sgptr & SG_FULL_RESID) != 0) {
! 8295: /* Case 3 */
! 8296: resid = aic_get_transfer_length(scb);
! 8297: } else if ((resid_sgptr & SG_LIST_NULL) != 0) {
! 8298: /* Case 4 */
! 8299: return;
! 8300: } else if ((resid_sgptr & SG_OVERRUN_RESID) != 0) {
! 8301: ahd_print_path(ahd, scb);
! 8302: printf("data overrun detected Tag == 0x%x.\n",
! 8303: SCB_GET_TAG(scb));
! 8304: ahd_freeze_devq(ahd, scb);
! 8305: aic_set_transaction_status(scb, CAM_DATA_RUN_ERR);
! 8306: aic_freeze_scb(scb);
! 8307: return;
! 8308: } else if ((resid_sgptr & ~SG_PTR_MASK) != 0) {
! 8309: panic("Bogus resid sgptr value 0x%x", resid_sgptr);
! 8310: /* NOTREACHED */
! 8311: } else {
! 8312: struct ahd_dma_seg *sg;
! 8313:
! 8314: /*
! 8315: * Remainder of the SG where the transfer
! 8316: * stopped.
! 8317: */
! 8318: resid = aic_le32toh(spkt->residual_datacnt) & AHD_SG_LEN_MASK;
! 8319: sg = ahd_sg_bus_to_virt(ahd, scb, resid_sgptr & SG_PTR_MASK);
! 8320:
! 8321: /* The residual sg_ptr always points to the next sg */
! 8322: sg--;
! 8323:
! 8324: /*
! 8325: * Add up the contents of all residual
! 8326: * SG segments that are after the SG where
! 8327: * the transfer stopped.
! 8328: */
! 8329: while ((aic_le32toh(sg->len) & AHD_DMA_LAST_SEG) == 0) {
! 8330: sg++;
! 8331: resid += aic_le32toh(sg->len) & AHD_SG_LEN_MASK;
! 8332: }
! 8333: }
! 8334: if ((scb->flags & SCB_SENSE) == 0)
! 8335: aic_set_residual(scb, resid);
! 8336: else
! 8337: aic_set_sense_residual(scb, resid);
! 8338:
! 8339: #ifdef AHD_DEBUG
! 8340: if ((ahd_debug & AHD_SHOW_MISC) != 0) {
! 8341: ahd_print_path(ahd, scb);
! 8342: printf("Handled %sResidual of %d bytes\n",
! 8343: (scb->flags & SCB_SENSE) ? "Sense " : "", resid);
! 8344: }
! 8345: #endif
! 8346: }
! 8347:
! 8348: /******************************* Target Mode **********************************/
! 8349: #ifdef AHD_TARGET_MODE
! 8350: /*
! 8351: * Add a target mode event to this lun's queue
! 8352: */
! 8353: void
! 8354: ahd_queue_lstate_event(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate,
! 8355: u_int initiator_id, u_int event_type, u_int event_arg)
! 8356: {
! 8357: struct ahd_tmode_event *event;
! 8358: int pending;
! 8359:
! 8360: xpt_freeze_devq(lstate->path, /*count*/1);
! 8361: if (lstate->event_w_idx >= lstate->event_r_idx)
! 8362: pending = lstate->event_w_idx - lstate->event_r_idx;
! 8363: else
! 8364: pending = AHD_TMODE_EVENT_BUFFER_SIZE + 1
! 8365: - (lstate->event_r_idx - lstate->event_w_idx);
! 8366:
! 8367: if (event_type == EVENT_TYPE_BUS_RESET
! 8368: || event_type == MSG_BUS_DEV_RESET) {
! 8369: /*
! 8370: * Any earlier events are irrelevant, so reset our buffer.
! 8371: * This has the effect of allowing us to deal with reset
! 8372: * floods (an external device holding down the reset line)
! 8373: * without losing the event that is really interesting.
! 8374: */
! 8375: lstate->event_r_idx = 0;
! 8376: lstate->event_w_idx = 0;
! 8377: xpt_release_devq(lstate->path, pending, /*runqueue*/FALSE);
! 8378: }
! 8379:
! 8380: if (pending == AHD_TMODE_EVENT_BUFFER_SIZE) {
! 8381: xpt_print_path(lstate->path);
! 8382: printf("immediate event %x:%x lost\n",
! 8383: lstate->event_buffer[lstate->event_r_idx].event_type,
! 8384: lstate->event_buffer[lstate->event_r_idx].event_arg);
! 8385: lstate->event_r_idx++;
! 8386: if (lstate->event_r_idx == AHD_TMODE_EVENT_BUFFER_SIZE)
! 8387: lstate->event_r_idx = 0;
! 8388: xpt_release_devq(lstate->path, /*count*/1, /*runqueue*/FALSE);
! 8389: }
! 8390:
! 8391: event = &lstate->event_buffer[lstate->event_w_idx];
! 8392: event->initiator_id = initiator_id;
! 8393: event->event_type = event_type;
! 8394: event->event_arg = event_arg;
! 8395: lstate->event_w_idx++;
! 8396: if (lstate->event_w_idx == AHD_TMODE_EVENT_BUFFER_SIZE)
! 8397: lstate->event_w_idx = 0;
! 8398: }
! 8399:
! 8400: /*
! 8401: * Send any target mode events queued up waiting
! 8402: * for immediate notify resources.
! 8403: */
! 8404: void
! 8405: ahd_send_lstate_events(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate)
! 8406: {
! 8407: struct ccb_hdr *ccbh;
! 8408: struct ccb_immed_notify *inot;
! 8409:
! 8410: while (lstate->event_r_idx != lstate->event_w_idx
! 8411: && (ccbh = SLIST_FIRST(&lstate->immed_notifies)) != NULL) {
! 8412: struct ahd_tmode_event *event;
! 8413:
! 8414: event = &lstate->event_buffer[lstate->event_r_idx];
! 8415: SLIST_REMOVE_HEAD(&lstate->immed_notifies, sim_links.sle);
! 8416: inot = (struct ccb_immed_notify *)ccbh;
! 8417: switch (event->event_type) {
! 8418: case EVENT_TYPE_BUS_RESET:
! 8419: ccbh->status = CAM_SCSI_BUS_RESET|CAM_DEV_QFRZN;
! 8420: break;
! 8421: default:
! 8422: ccbh->status = CAM_MESSAGE_RECV|CAM_DEV_QFRZN;
! 8423: inot->message_args[0] = event->event_type;
! 8424: inot->message_args[1] = event->event_arg;
! 8425: break;
! 8426: }
! 8427: inot->initiator_id = event->initiator_id;
! 8428: inot->sense_len = 0;
! 8429: xpt_done((union ccb *)inot);
! 8430: lstate->event_r_idx++;
! 8431: if (lstate->event_r_idx == AHD_TMODE_EVENT_BUFFER_SIZE)
! 8432: lstate->event_r_idx = 0;
! 8433: }
! 8434: }
! 8435: #endif
! 8436:
! 8437: /******************** Sequencer Program Patching/Download *********************/
! 8438:
! 8439: #ifdef AHD_DUMP_SEQ
! 8440: void
! 8441: ahd_dumpseq(struct ahd_softc* ahd)
! 8442: {
! 8443: int i;
! 8444: int max_prog;
! 8445:
! 8446: max_prog = 2048;
! 8447:
! 8448: ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
! 8449: ahd_outw(ahd, PRGMCNT, 0);
! 8450: for (i = 0; i < max_prog; i++) {
! 8451: uint8_t ins_bytes[4];
! 8452:
! 8453: ahd_insb(ahd, SEQRAM, ins_bytes, 4);
! 8454: printf("0x%08x\n", ins_bytes[0] << 24
! 8455: | ins_bytes[1] << 16
! 8456: | ins_bytes[2] << 8
! 8457: | ins_bytes[3]);
! 8458: }
! 8459: }
! 8460: #endif
! 8461:
! 8462: void
! 8463: ahd_loadseq(struct ahd_softc *ahd)
! 8464: {
! 8465: struct cs cs_table[NUM_CRITICAL_SECTIONS];
! 8466: u_int begin_set[NUM_CRITICAL_SECTIONS];
! 8467: u_int end_set[NUM_CRITICAL_SECTIONS];
! 8468: const struct patch *cur_patch;
! 8469: u_int cs_count;
! 8470: u_int cur_cs;
! 8471: u_int i;
! 8472: int downloaded;
! 8473: u_int skip_addr;
! 8474: u_int sg_prefetch_cnt;
! 8475: u_int sg_prefetch_cnt_limit;
! 8476: u_int sg_prefetch_align;
! 8477: u_int sg_size;
! 8478: u_int cacheline_mask;
! 8479: uint8_t download_consts[DOWNLOAD_CONST_COUNT];
! 8480:
! 8481: if (bootverbose)
! 8482: printf("%s: Downloading Sequencer Program...",
! 8483: ahd_name(ahd));
! 8484:
! 8485: #if DOWNLOAD_CONST_COUNT != 8
! 8486: #error "Download Const Mismatch"
! 8487: #endif
! 8488: /*
! 8489: * Start out with 0 critical sections
! 8490: * that apply to this firmware load.
! 8491: */
! 8492: cs_count = 0;
! 8493: cur_cs = 0;
! 8494: memset(begin_set, 0, sizeof(begin_set));
! 8495: memset(end_set, 0, sizeof(end_set));
! 8496:
! 8497: /*
! 8498: * Setup downloadable constant table.
! 8499: *
! 8500: * The computation for the S/G prefetch variables is
! 8501: * a bit complicated. We would like to always fetch
! 8502: * in terms of cachelined sized increments. However,
! 8503: * if the cacheline is not an even multiple of the
! 8504: * SG element size or is larger than our SG RAM, using
! 8505: * just the cache size might leave us with only a portion
! 8506: * of an SG element at the tail of a prefetch. If the
! 8507: * cacheline is larger than our S/G prefetch buffer less
! 8508: * the size of an SG element, we may round down to a cacheline
! 8509: * that doesn't contain any or all of the S/G of interest
! 8510: * within the bounds of our S/G ram. Provide variables to
! 8511: * the sequencer that will allow it to handle these edge
! 8512: * cases.
! 8513: */
! 8514: /* Start by aligning to the nearest cacheline. */
! 8515: sg_prefetch_align = ahd->pci_cachesize;
! 8516: if (sg_prefetch_align == 0)
! 8517: sg_prefetch_align = 8;
! 8518: /* Round down to the nearest power of 2. */
! 8519: while (powerof2(sg_prefetch_align) == 0)
! 8520: sg_prefetch_align--;
! 8521:
! 8522: cacheline_mask = sg_prefetch_align - 1;
! 8523:
! 8524: /*
! 8525: * If the cacheline boundary is greater than half our prefetch RAM
! 8526: * we risk not being able to fetch even a single complete S/G
! 8527: * segment if we align to that boundary.
! 8528: */
! 8529: if (sg_prefetch_align > CCSGADDR_MAX/2)
! 8530: sg_prefetch_align = CCSGADDR_MAX/2;
! 8531: /* Start by fetching a single cacheline. */
! 8532: sg_prefetch_cnt = sg_prefetch_align;
! 8533: /*
! 8534: * Increment the prefetch count by cachelines until
! 8535: * at least one S/G element will fit.
! 8536: */
! 8537: sg_size = sizeof(struct ahd_dma_seg);
! 8538: if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)
! 8539: sg_size = sizeof(struct ahd_dma64_seg);
! 8540: while (sg_prefetch_cnt < sg_size)
! 8541: sg_prefetch_cnt += sg_prefetch_align;
! 8542: /*
! 8543: * If the cacheline is not an even multiple of
! 8544: * the S/G size, we may only get a partial S/G when
! 8545: * we align. Add a cacheline if this is the case.
! 8546: */
! 8547: if ((sg_prefetch_align % sg_size) != 0
! 8548: && (sg_prefetch_cnt < CCSGADDR_MAX))
! 8549: sg_prefetch_cnt += sg_prefetch_align;
! 8550: /*
! 8551: * Lastly, compute a value that the sequencer can use
! 8552: * to determine if the remainder of the CCSGRAM buffer
! 8553: * has a full S/G element in it.
! 8554: */
! 8555: sg_prefetch_cnt_limit = -(sg_prefetch_cnt - sg_size + 1);
! 8556: download_consts[SG_PREFETCH_CNT] = sg_prefetch_cnt;
! 8557: download_consts[SG_PREFETCH_CNT_LIMIT] = sg_prefetch_cnt_limit;
! 8558: download_consts[SG_PREFETCH_ALIGN_MASK] = ~(sg_prefetch_align - 1);
! 8559: download_consts[SG_PREFETCH_ADDR_MASK] = (sg_prefetch_align - 1);
! 8560: download_consts[SG_SIZEOF] = sg_size;
! 8561: download_consts[PKT_OVERRUN_BUFOFFSET] =
! 8562: (ahd->overrun_buf - (uint8_t *)ahd->qoutfifo) / 256;
! 8563: download_consts[SCB_TRANSFER_SIZE] = SCB_TRANSFER_SIZE_1BYTE_LUN;
! 8564: download_consts[CACHELINE_MASK] = cacheline_mask;
! 8565: cur_patch = patches;
! 8566: downloaded = 0;
! 8567: skip_addr = 0;
! 8568: ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);
! 8569: ahd_outw(ahd, PRGMCNT, 0);
! 8570:
! 8571: for (i = 0; i < sizeof(seqprog)/4; i++) {
! 8572: if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) {
! 8573: /*
! 8574: * Don't download this instruction as it
! 8575: * is in a patch that was removed.
! 8576: */
! 8577: continue;
! 8578: }
! 8579: /*
! 8580: * Move through the CS table until we find a CS
! 8581: * that might apply to this instruction.
! 8582: */
! 8583: for (; cur_cs < NUM_CRITICAL_SECTIONS; cur_cs++) {
! 8584: if (critical_sections[cur_cs].end <= i) {
! 8585: if (begin_set[cs_count] == TRUE
! 8586: && end_set[cs_count] == FALSE) {
! 8587: cs_table[cs_count].end = downloaded;
! 8588: end_set[cs_count] = TRUE;
! 8589: cs_count++;
! 8590: }
! 8591: continue;
! 8592: }
! 8593: if (critical_sections[cur_cs].begin <= i
! 8594: && begin_set[cs_count] == FALSE) {
! 8595: cs_table[cs_count].begin = downloaded;
! 8596: begin_set[cs_count] = TRUE;
! 8597: }
! 8598: break;
! 8599: }
! 8600: ahd_download_instr(ahd, i, download_consts);
! 8601: downloaded++;
! 8602: }
! 8603:
! 8604: ahd->num_critical_sections = cs_count;
! 8605: if (cs_count != 0) {
! 8606:
! 8607: cs_count *= sizeof(struct cs);
! 8608: ahd->critical_sections = malloc(cs_count, M_DEVBUF, M_NOWAIT);
! 8609: if (ahd->critical_sections == NULL)
! 8610: panic("ahd_loadseq: Could not malloc");
! 8611: memcpy(ahd->critical_sections, cs_table, cs_count);
! 8612: }
! 8613: ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE);
! 8614:
! 8615: if (bootverbose) {
! 8616: printf(" %d instructions downloaded\n", downloaded);
! 8617: printf("%s: Features 0x%x, Bugs 0x%x, Flags 0x%x\n",
! 8618: ahd_name(ahd), ahd->features, ahd->bugs, ahd->flags);
! 8619: }
! 8620: }
! 8621:
! 8622: int
! 8623: ahd_check_patch(struct ahd_softc *ahd, const struct patch **start_patch,
! 8624: u_int start_instr, u_int *skip_addr)
! 8625: {
! 8626: const struct patch *cur_patch;
! 8627: const struct patch *last_patch;
! 8628: u_int num_patches;
! 8629:
! 8630: num_patches = sizeof(patches)/sizeof(struct patch);
! 8631: last_patch = &patches[num_patches];
! 8632: cur_patch = *start_patch;
! 8633:
! 8634: while (cur_patch < last_patch && start_instr == cur_patch->begin) {
! 8635:
! 8636: if (cur_patch->patch_func(ahd) == 0) {
! 8637:
! 8638: /* Start rejecting code */
! 8639: *skip_addr = start_instr + cur_patch->skip_instr;
! 8640: cur_patch += cur_patch->skip_patch;
! 8641: } else {
! 8642: /* Accepted this patch. Advance to the next
! 8643: * one and wait for our intruction pointer to
! 8644: * hit this point.
! 8645: */
! 8646: cur_patch++;
! 8647: }
! 8648: }
! 8649:
! 8650: *start_patch = cur_patch;
! 8651: if (start_instr < *skip_addr)
! 8652: /* Still skipping */
! 8653: return (0);
! 8654:
! 8655: return (1);
! 8656: }
! 8657:
! 8658: u_int
! 8659: ahd_resolve_seqaddr(struct ahd_softc *ahd, u_int address)
! 8660: {
! 8661: const struct patch *cur_patch;
! 8662: int address_offset;
! 8663: u_int skip_addr;
! 8664: u_int i;
! 8665:
! 8666: address_offset = 0;
! 8667: cur_patch = patches;
! 8668: skip_addr = 0;
! 8669:
! 8670: for (i = 0; i < address;) {
! 8671:
! 8672: ahd_check_patch(ahd, &cur_patch, i, &skip_addr);
! 8673:
! 8674: if (skip_addr > i) {
! 8675: int end_addr;
! 8676:
! 8677: end_addr = MIN(address, skip_addr);
! 8678: address_offset += end_addr - i;
! 8679: i = skip_addr;
! 8680: } else {
! 8681: i++;
! 8682: }
! 8683: }
! 8684: return (address - address_offset);
! 8685: }
! 8686:
! 8687: void
! 8688: ahd_download_instr(struct ahd_softc *ahd, u_int instrptr, uint8_t *dconsts)
! 8689: {
! 8690: union ins_formats instr;
! 8691: struct ins_format1 *fmt1_ins;
! 8692: struct ins_format3 *fmt3_ins;
! 8693: u_int opcode;
! 8694:
! 8695: /*
! 8696: * The firmware is always compiled into a little endian format.
! 8697: */
! 8698: instr.integer = aic_le32toh(*(uint32_t*)&seqprog[instrptr * 4]);
! 8699:
! 8700: fmt1_ins = &instr.format1;
! 8701: fmt3_ins = NULL;
! 8702:
! 8703: /* Pull the opcode */
! 8704: opcode = instr.format1.opcode;
! 8705: switch (opcode) {
! 8706: case AIC_OP_JMP:
! 8707: case AIC_OP_JC:
! 8708: case AIC_OP_JNC:
! 8709: case AIC_OP_CALL:
! 8710: case AIC_OP_JNE:
! 8711: case AIC_OP_JNZ:
! 8712: case AIC_OP_JE:
! 8713: case AIC_OP_JZ:
! 8714: {
! 8715: fmt3_ins = &instr.format3;
! 8716: fmt3_ins->address = ahd_resolve_seqaddr(ahd, fmt3_ins->address);
! 8717: /* FALLTHROUGH */
! 8718: }
! 8719: case AIC_OP_OR:
! 8720: case AIC_OP_AND:
! 8721: case AIC_OP_XOR:
! 8722: case AIC_OP_ADD:
! 8723: case AIC_OP_ADC:
! 8724: case AIC_OP_BMOV:
! 8725: if (fmt1_ins->parity != 0) {
! 8726: fmt1_ins->immediate = dconsts[fmt1_ins->immediate];
! 8727: }
! 8728: fmt1_ins->parity = 0;
! 8729: /* FALLTHROUGH */
! 8730: case AIC_OP_ROL:
! 8731: {
! 8732: int i, count;
! 8733:
! 8734: /* Calculate odd parity for the instruction */
! 8735: for (i = 0, count = 0; i < 31; i++) {
! 8736: uint32_t mask;
! 8737:
! 8738: mask = 0x01 << i;
! 8739: if ((instr.integer & mask) != 0)
! 8740: count++;
! 8741: }
! 8742: if ((count & 0x01) == 0)
! 8743: instr.format1.parity = 1;
! 8744:
! 8745: /* The sequencer is a little endian cpu */
! 8746: instr.integer = aic_htole32(instr.integer);
! 8747: ahd_outsb(ahd, SEQRAM, instr.bytes, 4);
! 8748: break;
! 8749: }
! 8750: default:
! 8751: panic("Unknown opcode encountered in seq program");
! 8752: break;
! 8753: }
! 8754: }
! 8755:
! 8756: int
! 8757: ahd_probe_stack_size(struct ahd_softc *ahd)
! 8758: {
! 8759: int last_probe;
! 8760:
! 8761: last_probe = 0;
! 8762: while (1) {
! 8763: int i;
! 8764:
! 8765: /*
! 8766: * We avoid using 0 as a pattern to avoid
! 8767: * confusion if the stack implementation
! 8768: * "back-fills" with zeros when "poping'
! 8769: * entries.
! 8770: */
! 8771: for (i = 1; i <= last_probe+1; i++) {
! 8772: ahd_outb(ahd, STACK, i & 0xFF);
! 8773: ahd_outb(ahd, STACK, (i >> 8) & 0xFF);
! 8774: }
! 8775:
! 8776: /* Verify */
! 8777: for (i = last_probe+1; i > 0; i--) {
! 8778: u_int stack_entry;
! 8779:
! 8780: stack_entry = ahd_inb(ahd, STACK)
! 8781: |(ahd_inb(ahd, STACK) << 8);
! 8782: if (stack_entry != i)
! 8783: goto sized;
! 8784: }
! 8785: last_probe++;
! 8786: }
! 8787: sized:
! 8788: return (last_probe);
! 8789: }
! 8790:
! 8791: void
! 8792: ahd_dump_all_cards_state(void)
! 8793: {
! 8794: struct ahd_softc *list_ahd;
! 8795:
! 8796: TAILQ_FOREACH(list_ahd, &ahd_tailq, links) {
! 8797: ahd_dump_card_state(list_ahd);
! 8798: }
! 8799: }
! 8800:
! 8801: int
! 8802: ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries,
! 8803: const char *name, u_int address, u_int value,
! 8804: u_int *cur_column, u_int wrap_point)
! 8805: {
! 8806: u_int printed_mask;
! 8807: int entry, printed;
! 8808:
! 8809: if (cur_column != NULL && *cur_column >= wrap_point) {
! 8810: printf("\n");
! 8811: *cur_column = 0;
! 8812: }
! 8813: printed = printf("%s[0x%x]", name, value);
! 8814: if (table == NULL) {
! 8815: printed += printf(" ");
! 8816: if (cur_column != NULL)
! 8817: *cur_column += printed;
! 8818: return (printed);
! 8819: }
! 8820:
! 8821: printed_mask = 0;
! 8822: while (printed_mask != 0xFF) {
! 8823: for (entry = 0; entry < num_entries; entry++) {
! 8824: if (((value & table[entry].mask) != table[entry].value)
! 8825: || ((printed_mask & table[entry].mask) ==
! 8826: table[entry].mask))
! 8827: continue;
! 8828:
! 8829: printed += printf("%s%s",
! 8830: printed_mask == 0 ? ":(" : "|",
! 8831: table[entry].name);
! 8832: printed_mask |= table[entry].mask;
! 8833:
! 8834: break;
! 8835: }
! 8836: if (entry >= num_entries)
! 8837: break;
! 8838: }
! 8839:
! 8840: printed += printf("%s", printed_mask == 0 ? " " : ") ");
! 8841: if (cur_column != NULL)
! 8842: *cur_column += printed;
! 8843:
! 8844: return (printed);
! 8845: }
! 8846:
! 8847: void
! 8848: ahd_dump_card_state(struct ahd_softc *ahd)
! 8849: {
! 8850: struct scb *scb;
! 8851: ahd_mode_state saved_modes;
! 8852: u_int dffstat;
! 8853: int paused;
! 8854: u_int scb_index;
! 8855: u_int saved_scb_index;
! 8856: u_int cur_col;
! 8857: int i;
! 8858:
! 8859: if (ahd_is_paused(ahd)) {
! 8860: paused = 1;
! 8861: } else {
! 8862: paused = 0;
! 8863: ahd_pause(ahd);
! 8864: }
! 8865: saved_modes = ahd_save_modes(ahd);
! 8866: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 8867: printf("================== Dump Card State Begins =================\n"
! 8868: "%s: Dumping Card State at program address 0x%x Mode 0x%x\n",
! 8869: ahd_name(ahd),
! 8870: ahd_inw(ahd, CURADDR),
! 8871: ahd_build_mode_state(ahd, ahd->saved_src_mode,
! 8872: ahd->saved_dst_mode));
! 8873: if (paused)
! 8874: printf("Card was paused\n");
! 8875:
! 8876: if (ahd_check_cmdcmpltqueues(ahd))
! 8877: printf("Completions are pending\n");
! 8878:
! 8879: /*
! 8880: * Mode independent registers.
! 8881: */
! 8882: cur_col = 0;
! 8883: ahd_intstat_print(ahd_inb(ahd, INTSTAT), &cur_col, 50);
! 8884: ahd_seloid_print(ahd_inb(ahd, SELOID), &cur_col, 50);
! 8885: ahd_selid_print(ahd_inb(ahd, SELID), &cur_col, 50);
! 8886: ahd_hs_mailbox_print(ahd_inb(ahd, LOCAL_HS_MAILBOX), &cur_col, 50);
! 8887: ahd_intctl_print(ahd_inb(ahd, INTCTL), &cur_col, 50);
! 8888: ahd_seqintstat_print(ahd_inb(ahd, SEQINTSTAT), &cur_col, 50);
! 8889: ahd_saved_mode_print(ahd_inb(ahd, SAVED_MODE), &cur_col, 50);
! 8890: ahd_dffstat_print(ahd_inb(ahd, DFFSTAT), &cur_col, 50);
! 8891: ahd_scsisigi_print(ahd_inb(ahd, SCSISIGI), &cur_col, 50);
! 8892: ahd_scsiphase_print(ahd_inb(ahd, SCSIPHASE), &cur_col, 50);
! 8893: ahd_scsibus_print(ahd_inb(ahd, SCSIBUS), &cur_col, 50);
! 8894: ahd_lastphase_print(ahd_inb(ahd, LASTPHASE), &cur_col, 50);
! 8895: ahd_scsiseq0_print(ahd_inb(ahd, SCSISEQ0), &cur_col, 50);
! 8896: ahd_scsiseq1_print(ahd_inb(ahd, SCSISEQ1), &cur_col, 50);
! 8897: ahd_seqctl0_print(ahd_inb(ahd, SEQCTL0), &cur_col, 50);
! 8898: ahd_seqintctl_print(ahd_inb(ahd, SEQINTCTL), &cur_col, 50);
! 8899: ahd_seq_flags_print(ahd_inb(ahd, SEQ_FLAGS), &cur_col, 50);
! 8900: ahd_seq_flags2_print(ahd_inb(ahd, SEQ_FLAGS2), &cur_col, 50);
! 8901: ahd_qfreeze_count_print(ahd_inw(ahd, QFREEZE_COUNT), &cur_col, 50);
! 8902: ahd_kernel_qfreeze_count_print(ahd_inw(ahd, KERNEL_QFREEZE_COUNT),
! 8903: &cur_col, 50);
! 8904: ahd_mk_message_scb_print(ahd_inw(ahd, MK_MESSAGE_SCB), &cur_col, 50);
! 8905: ahd_mk_message_scsiid_print(ahd_inb(ahd, MK_MESSAGE_SCSIID),
! 8906: &cur_col, 50);
! 8907: ahd_sstat0_print(ahd_inb(ahd, SSTAT0), &cur_col, 50);
! 8908: ahd_sstat1_print(ahd_inb(ahd, SSTAT1), &cur_col, 50);
! 8909: ahd_sstat2_print(ahd_inb(ahd, SSTAT2), &cur_col, 50);
! 8910: ahd_sstat3_print(ahd_inb(ahd, SSTAT3), &cur_col, 50);
! 8911: ahd_perrdiag_print(ahd_inb(ahd, PERRDIAG), &cur_col, 50);
! 8912: ahd_simode1_print(ahd_inb(ahd, SIMODE1), &cur_col, 50);
! 8913: ahd_lqistat0_print(ahd_inb(ahd, LQISTAT0), &cur_col, 50);
! 8914: ahd_lqistat1_print(ahd_inb(ahd, LQISTAT1), &cur_col, 50);
! 8915: ahd_lqistat2_print(ahd_inb(ahd, LQISTAT2), &cur_col, 50);
! 8916: ahd_lqostat0_print(ahd_inb(ahd, LQOSTAT0), &cur_col, 50);
! 8917: ahd_lqostat1_print(ahd_inb(ahd, LQOSTAT1), &cur_col, 50);
! 8918: ahd_lqostat2_print(ahd_inb(ahd, LQOSTAT2), &cur_col, 50);
! 8919: printf("\n");
! 8920: printf("\nSCB Count = %d CMDS_PENDING = %d LASTSCB 0x%x "
! 8921: "CURRSCB 0x%x NEXTSCB 0x%x\n",
! 8922: ahd->scb_data.numscbs, ahd_inw(ahd, CMDS_PENDING),
! 8923: ahd_inw(ahd, LASTSCB), ahd_inw(ahd, CURRSCB),
! 8924: ahd_inw(ahd, NEXTSCB));
! 8925: cur_col = 0;
! 8926: /* QINFIFO */
! 8927: ahd_search_qinfifo(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,
! 8928: CAM_LUN_WILDCARD, SCB_LIST_NULL,
! 8929: ROLE_UNKNOWN, /*status*/0, SEARCH_PRINT);
! 8930: saved_scb_index = ahd_get_scbptr(ahd);
! 8931: printf("Pending list:");
! 8932: i = 0;
! 8933: LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
! 8934: if (i++ > AHD_SCB_MAX)
! 8935: break;
! 8936: cur_col = printf("\n%3d FIFO_USE[0x%x] ", SCB_GET_TAG(scb),
! 8937: ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT));
! 8938: ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
! 8939: ahd_scb_control_print(ahd_inb_scbram(ahd, SCB_CONTROL),
! 8940: &cur_col, 60);
! 8941: ahd_scb_scsiid_print(ahd_inb_scbram(ahd, SCB_SCSIID),
! 8942: &cur_col, 60);
! 8943: }
! 8944: printf("\nTotal %d\n", i);
! 8945:
! 8946: printf("Kernel Free SCB list: ");
! 8947: i = 0;
! 8948: TAILQ_FOREACH(scb, &ahd->scb_data.free_scbs, links.tqe) {
! 8949: struct scb *list_scb;
! 8950:
! 8951: list_scb = scb;
! 8952: do {
! 8953: printf("%d ", SCB_GET_TAG(list_scb));
! 8954: list_scb = LIST_NEXT(list_scb, collision_links);
! 8955: } while (list_scb && i++ < AHD_SCB_MAX);
! 8956: }
! 8957:
! 8958: LIST_FOREACH(scb, &ahd->scb_data.any_dev_free_scb_list, links.le) {
! 8959: if (i++ > AHD_SCB_MAX)
! 8960: break;
! 8961: printf("%d ", SCB_GET_TAG(scb));
! 8962: }
! 8963: printf("\n");
! 8964:
! 8965: printf("Sequencer Complete DMA-inprog list: ");
! 8966: scb_index = ahd_inw(ahd, COMPLETE_SCB_DMAINPROG_HEAD);
! 8967: i = 0;
! 8968: while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
! 8969: ahd_set_scbptr(ahd, scb_index);
! 8970: printf("%d ", scb_index);
! 8971: scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
! 8972: }
! 8973: printf("\n");
! 8974:
! 8975: printf("Sequencer Complete list: ");
! 8976: scb_index = ahd_inw(ahd, COMPLETE_SCB_HEAD);
! 8977: i = 0;
! 8978: while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
! 8979: ahd_set_scbptr(ahd, scb_index);
! 8980: printf("%d ", scb_index);
! 8981: scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
! 8982: }
! 8983: printf("\n");
! 8984:
! 8985:
! 8986: printf("Sequencer DMA-Up and Complete list: ");
! 8987: scb_index = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
! 8988: i = 0;
! 8989: while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
! 8990: ahd_set_scbptr(ahd, scb_index);
! 8991: printf("%d ", scb_index);
! 8992: scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
! 8993: }
! 8994: printf("\n");
! 8995: printf("Sequencer On QFreeze and Complete list: ");
! 8996: scb_index = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);
! 8997: i = 0;
! 8998: while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {
! 8999: ahd_set_scbptr(ahd, scb_index);
! 9000: printf("%d ", scb_index);
! 9001: scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
! 9002: }
! 9003: printf("\n");
! 9004: ahd_set_scbptr(ahd, saved_scb_index);
! 9005: dffstat = ahd_inb(ahd, DFFSTAT);
! 9006: for (i = 0; i < 2; i++) {
! 9007: #ifdef AHD_DEBUG
! 9008: struct scb *fifo_scb;
! 9009: #endif
! 9010: u_int fifo_scbptr;
! 9011:
! 9012: ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i);
! 9013: fifo_scbptr = ahd_get_scbptr(ahd);
! 9014: printf("\n\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n",
! 9015: ahd_name(ahd), i,
! 9016: (dffstat & (FIFO0FREE << i)) ? "Free" : "Active",
! 9017: ahd_inw(ahd, LONGJMP_ADDR), fifo_scbptr);
! 9018: cur_col = 0;
! 9019: ahd_seqimode_print(ahd_inb(ahd, SEQIMODE), &cur_col, 50);
! 9020: ahd_seqintsrc_print(ahd_inb(ahd, SEQINTSRC), &cur_col, 50);
! 9021: ahd_dfcntrl_print(ahd_inb(ahd, DFCNTRL), &cur_col, 50);
! 9022: ahd_dfstatus_print(ahd_inb(ahd, DFSTATUS), &cur_col, 50);
! 9023: ahd_sg_cache_shadow_print(ahd_inb(ahd, SG_CACHE_SHADOW),
! 9024: &cur_col, 50);
! 9025: ahd_sg_state_print(ahd_inb(ahd, SG_STATE), &cur_col, 50);
! 9026: ahd_dffsxfrctl_print(ahd_inb(ahd, DFFSXFRCTL), &cur_col, 50);
! 9027: ahd_soffcnt_print(ahd_inb(ahd, SOFFCNT), &cur_col, 50);
! 9028: ahd_mdffstat_print(ahd_inb(ahd, MDFFSTAT), &cur_col, 50);
! 9029: if (cur_col > 50) {
! 9030: printf("\n");
! 9031: cur_col = 0;
! 9032: }
! 9033: cur_col += printf("SHADDR = 0x%x%x, SHCNT = 0x%x ",
! 9034: ahd_inl(ahd, SHADDR+4),
! 9035: ahd_inl(ahd, SHADDR),
! 9036: (ahd_inb(ahd, SHCNT)
! 9037: | (ahd_inb(ahd, SHCNT + 1) << 8)
! 9038: | (ahd_inb(ahd, SHCNT + 2) << 16)));
! 9039: if (cur_col > 50) {
! 9040: printf("\n");
! 9041: cur_col = 0;
! 9042: }
! 9043: cur_col += printf("HADDR = 0x%x%x, HCNT = 0x%x ",
! 9044: ahd_inl(ahd, HADDR+4),
! 9045: ahd_inl(ahd, HADDR),
! 9046: (ahd_inb(ahd, HCNT)
! 9047: | (ahd_inb(ahd, HCNT + 1) << 8)
! 9048: | (ahd_inb(ahd, HCNT + 2) << 16)));
! 9049: ahd_ccsgctl_print(ahd_inb(ahd, CCSGCTL), &cur_col, 50);
! 9050: #ifdef AHD_DEBUG
! 9051: if ((ahd_debug & AHD_SHOW_SG) != 0) {
! 9052: fifo_scb = ahd_lookup_scb(ahd, fifo_scbptr);
! 9053: if (fifo_scb != NULL)
! 9054: ahd_dump_sglist(fifo_scb);
! 9055: }
! 9056: #endif
! 9057: }
! 9058: printf("\nLQIN: ");
! 9059: for (i = 0; i < 20; i++)
! 9060: printf("0x%x ", ahd_inb(ahd, LQIN + i));
! 9061: printf("\n");
! 9062: ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
! 9063: printf("%s: LQISTATE = 0x%x, LQOSTATE = 0x%x, OPTIONMODE = 0x%x\n",
! 9064: ahd_name(ahd), ahd_inb(ahd, LQISTATE), ahd_inb(ahd, LQOSTATE),
! 9065: ahd_inb(ahd, OPTIONMODE));
! 9066: printf("%s: OS_SPACE_CNT = 0x%x MAXCMDCNT = 0x%x\n",
! 9067: ahd_name(ahd), ahd_inb(ahd, OS_SPACE_CNT),
! 9068: ahd_inb(ahd, MAXCMDCNT));
! 9069: printf("%s: SAVED_SCSIID = 0x%x SAVED_LUN = 0x%x\n",
! 9070: ahd_name(ahd), ahd_inb(ahd, SAVED_SCSIID),
! 9071: ahd_inb(ahd, SAVED_LUN));
! 9072: ahd_simode0_print(ahd_inb(ahd, SIMODE0), &cur_col, 50);
! 9073: printf("\n");
! 9074: ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
! 9075: cur_col = 0;
! 9076: ahd_ccscbctl_print(ahd_inb(ahd, CCSCBCTL), &cur_col, 50);
! 9077: printf("\n");
! 9078: ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
! 9079: printf("%s: REG0 == 0x%x, SINDEX = 0x%x, DINDEX = 0x%x\n",
! 9080: ahd_name(ahd), ahd_inw(ahd, REG0), ahd_inw(ahd, SINDEX),
! 9081: ahd_inw(ahd, DINDEX));
! 9082: printf("%s: SCBPTR == 0x%x, SCB_NEXT == 0x%x, SCB_NEXT2 == 0x%x\n",
! 9083: ahd_name(ahd), ahd_get_scbptr(ahd),
! 9084: ahd_inw_scbram(ahd, SCB_NEXT),
! 9085: ahd_inw_scbram(ahd, SCB_NEXT2));
! 9086: printf("CDB %x %x %x %x %x %x\n",
! 9087: ahd_inb_scbram(ahd, SCB_CDB_STORE),
! 9088: ahd_inb_scbram(ahd, SCB_CDB_STORE+1),
! 9089: ahd_inb_scbram(ahd, SCB_CDB_STORE+2),
! 9090: ahd_inb_scbram(ahd, SCB_CDB_STORE+3),
! 9091: ahd_inb_scbram(ahd, SCB_CDB_STORE+4),
! 9092: ahd_inb_scbram(ahd, SCB_CDB_STORE+5));
! 9093: printf("STACK:");
! 9094: for (i = 0; i < ahd->stack_size; i++) {
! 9095: ahd->saved_stack[i] =
! 9096: ahd_inb(ahd, STACK)|(ahd_inb(ahd, STACK) << 8);
! 9097: printf(" 0x%x", ahd->saved_stack[i]);
! 9098: }
! 9099: for (i = ahd->stack_size-1; i >= 0; i--) {
! 9100: ahd_outb(ahd, STACK, ahd->saved_stack[i] & 0xFF);
! 9101: ahd_outb(ahd, STACK, (ahd->saved_stack[i] >> 8) & 0xFF);
! 9102: }
! 9103: printf("\n================= Dump Card State Ends ==================\n");
! 9104: ahd_platform_dump_card_state(ahd);
! 9105: ahd_restore_modes(ahd, saved_modes);
! 9106: if (paused == 0)
! 9107: ahd_unpause(ahd);
! 9108: }
! 9109:
! 9110: void
! 9111: ahd_dump_scbs(struct ahd_softc *ahd)
! 9112: {
! 9113: ahd_mode_state saved_modes;
! 9114: u_int saved_scb_index;
! 9115: int i;
! 9116:
! 9117: saved_modes = ahd_save_modes(ahd);
! 9118: ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
! 9119: saved_scb_index = ahd_get_scbptr(ahd);
! 9120: for (i = 0; i < AHD_SCB_MAX; i++) {
! 9121: ahd_set_scbptr(ahd, i);
! 9122: printf("%3d", i);
! 9123: printf("(CTRL 0x%x ID 0x%x N 0x%x N2 0x%x SG 0x%x, RSG 0x%x)\n",
! 9124: ahd_inb_scbram(ahd, SCB_CONTROL),
! 9125: ahd_inb_scbram(ahd, SCB_SCSIID),
! 9126: ahd_inw_scbram(ahd, SCB_NEXT),
! 9127: ahd_inw_scbram(ahd, SCB_NEXT2),
! 9128: ahd_inl_scbram(ahd, SCB_SGPTR),
! 9129: ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR));
! 9130: }
! 9131: printf("\n");
! 9132: ahd_set_scbptr(ahd, saved_scb_index);
! 9133: ahd_restore_modes(ahd, saved_modes);
! 9134: }
! 9135:
! 9136:
! 9137: /*************************** Timeout Handling *********************************/
! 9138: void
! 9139: ahd_timeout(void *arg)
! 9140: {
! 9141: struct scb *scb, *list_scb;
! 9142: struct ahd_softc *ahd;
! 9143: char channel;
! 9144: long s;
! 9145: int found;
! 9146: #ifdef AHD_DEBUG
! 9147: int was_paused;
! 9148: #endif
! 9149:
! 9150: scb = (struct scb *)arg;
! 9151: ahd = scb->ahd_softc;
! 9152:
! 9153: ahd_lock(ahd, &s);
! 9154:
! 9155: #ifdef AHD_DEBUG
! 9156: was_paused = ahd_is_paused(ahd);
! 9157: printf("%s: SCB %d timed out - Card was %spaused\n", ahd_name(ahd),
! 9158: SCB_GET_TAG(scb), was_paused ? "" : "not ");
! 9159: ahd_dump_card_state(ahd);
! 9160: #endif
! 9161:
! 9162: ahd_pause(ahd);
! 9163:
! 9164: if (scb->flags & SCB_ACTIVE) {
! 9165: aic_set_transaction_status(scb, CAM_CMD_TIMEOUT);
! 9166: /*
! 9167: * Go through all of our pending SCBs and remove any scheduled
! 9168: * timeouts for them. They're about to be aborted so no need
! 9169: * for them to timeout.
! 9170: */
! 9171: LIST_FOREACH(list_scb, &ahd->pending_scbs, pending_links) {
! 9172: if (list_scb->xs)
! 9173: timeout_del(&list_scb->xs->stimeout);
! 9174: }
! 9175: channel = SCB_GET_CHANNEL(ahd, scb);
! 9176: found = ahd_reset_channel(ahd, channel, /*Initiate Reset*/TRUE);
! 9177: #ifdef AHD_DEBUG
! 9178: printf("%s: Issued Channel %c Bus Reset. %d SCBs aborted\n",
! 9179: ahd_name(ahd), channel, found);
! 9180: #endif
! 9181: }
! 9182:
! 9183: ahd_unpause(ahd);
! 9184: ahd_unlock(ahd, &s);
! 9185: }
! 9186:
! 9187: /**************************** Flexport Logic **********************************/
! 9188: /*
! 9189: * Read count 16bit words from 16bit word address start_addr from the
! 9190: * SEEPROM attached to the controller, into buf, using the controller's
! 9191: * SEEPROM reading state machine. Optionally treat the data as a byte
! 9192: * stream in terms of byte order.
! 9193: */
! 9194: int
! 9195: ahd_read_seeprom(struct ahd_softc *ahd, uint16_t *buf,
! 9196: u_int start_addr, u_int count, int bytestream)
! 9197: {
! 9198: u_int cur_addr;
! 9199: u_int end_addr;
! 9200: int error;
! 9201:
! 9202: /*
! 9203: * If we never make it through the loop even once,
! 9204: * we were passed invalid arguments.
! 9205: */
! 9206: error = EINVAL;
! 9207: AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
! 9208: end_addr = start_addr + count;
! 9209: for (cur_addr = start_addr; cur_addr < end_addr; cur_addr++) {
! 9210:
! 9211: ahd_outb(ahd, SEEADR, cur_addr);
! 9212: ahd_outb(ahd, SEECTL, SEEOP_READ | SEESTART);
! 9213:
! 9214: error = ahd_wait_seeprom(ahd);
! 9215: if (error) {
! 9216: printf("%s: ahd_wait_seeprom timed out\n", ahd_name(ahd));
! 9217: break;
! 9218: }
! 9219: if (bytestream != 0) {
! 9220: uint8_t *bytestream_ptr;
! 9221:
! 9222: bytestream_ptr = (uint8_t *)buf;
! 9223: *bytestream_ptr++ = ahd_inb(ahd, SEEDAT);
! 9224: *bytestream_ptr = ahd_inb(ahd, SEEDAT+1);
! 9225: } else {
! 9226: /*
! 9227: * ahd_inw() already handles machine byte order.
! 9228: */
! 9229: *buf = ahd_inw(ahd, SEEDAT);
! 9230: }
! 9231: buf++;
! 9232: }
! 9233: return (error);
! 9234: }
! 9235:
! 9236: /*
! 9237: * Write count 16bit words from buf, into SEEPROM attache to the
! 9238: * controller starting at 16bit word address start_addr, using the
! 9239: * controller's SEEPROM writing state machine.
! 9240: */
! 9241: int
! 9242: ahd_write_seeprom(struct ahd_softc *ahd, uint16_t *buf,
! 9243: u_int start_addr, u_int count)
! 9244: {
! 9245: u_int cur_addr;
! 9246: u_int end_addr;
! 9247: int error;
! 9248: int retval;
! 9249:
! 9250: AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
! 9251: error = ENOENT;
! 9252:
! 9253: /* Place the chip into write-enable mode */
! 9254: ahd_outb(ahd, SEEADR, SEEOP_EWEN_ADDR);
! 9255: ahd_outb(ahd, SEECTL, SEEOP_EWEN | SEESTART);
! 9256: error = ahd_wait_seeprom(ahd);
! 9257: if (error)
! 9258: return (error);
! 9259:
! 9260: /*
! 9261: * Write the data. If we don't get throught the loop at
! 9262: * least once, the arguments were invalid.
! 9263: */
! 9264: retval = EINVAL;
! 9265: end_addr = start_addr + count;
! 9266: for (cur_addr = start_addr; cur_addr < end_addr; cur_addr++) {
! 9267: ahd_outw(ahd, SEEDAT, *buf++);
! 9268: ahd_outb(ahd, SEEADR, cur_addr);
! 9269: ahd_outb(ahd, SEECTL, SEEOP_WRITE | SEESTART);
! 9270:
! 9271: retval = ahd_wait_seeprom(ahd);
! 9272: if (retval)
! 9273: break;
! 9274: }
! 9275:
! 9276: /*
! 9277: * Disable writes.
! 9278: */
! 9279: ahd_outb(ahd, SEEADR, SEEOP_EWDS_ADDR);
! 9280: ahd_outb(ahd, SEECTL, SEEOP_EWDS | SEESTART);
! 9281: error = ahd_wait_seeprom(ahd);
! 9282: if (error)
! 9283: return (error);
! 9284: return (retval);
! 9285: }
! 9286:
! 9287: /*
! 9288: * Wait ~100us for the serial eeprom to satisfy our request.
! 9289: */
! 9290: int
! 9291: ahd_wait_seeprom(struct ahd_softc *ahd)
! 9292: {
! 9293: int cnt;
! 9294:
! 9295: cnt = 5000;
! 9296: while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt)
! 9297: aic_delay(5);
! 9298:
! 9299: if (cnt == 0)
! 9300: return (ETIMEDOUT);
! 9301: return (0);
! 9302: }
! 9303:
! 9304: /*
! 9305: * Validate the two checksums in the per_channel
! 9306: * vital product data struct.
! 9307: */
! 9308: int
! 9309: ahd_verify_vpd_cksum(struct vpd_config *vpd)
! 9310: {
! 9311: int i;
! 9312: int maxaddr;
! 9313: uint32_t checksum;
! 9314: uint8_t *vpdarray;
! 9315:
! 9316: vpdarray = (uint8_t *)vpd;
! 9317: maxaddr = offsetof(struct vpd_config, vpd_checksum);
! 9318: checksum = 0;
! 9319: for (i = offsetof(struct vpd_config, resource_type); i < maxaddr; i++)
! 9320: checksum = checksum + vpdarray[i];
! 9321: if (checksum == 0
! 9322: || (-checksum & 0xFF) != vpd->vpd_checksum)
! 9323: return (0);
! 9324:
! 9325: checksum = 0;
! 9326: maxaddr = offsetof(struct vpd_config, checksum);
! 9327: for (i = offsetof(struct vpd_config, default_target_flags);
! 9328: i < maxaddr; i++)
! 9329: checksum = checksum + vpdarray[i];
! 9330: if (checksum == 0
! 9331: || (-checksum & 0xFF) != vpd->checksum)
! 9332: return (0);
! 9333: return (1);
! 9334: }
! 9335:
! 9336: int
! 9337: ahd_verify_cksum(struct seeprom_config *sc)
! 9338: {
! 9339: int i;
! 9340: int maxaddr;
! 9341: uint32_t checksum;
! 9342: uint16_t *scarray;
! 9343:
! 9344: maxaddr = (sizeof(*sc)/2) - 1;
! 9345: checksum = 0;
! 9346: scarray = (uint16_t *)sc;
! 9347:
! 9348: for (i = 0; i < maxaddr; i++)
! 9349: checksum = checksum + scarray[i];
! 9350: if (checksum == 0
! 9351: || (checksum & 0xFFFF) != sc->checksum) {
! 9352: return (0);
! 9353: } else {
! 9354: return (1);
! 9355: }
! 9356: }
! 9357:
! 9358: int
! 9359: ahd_acquire_seeprom(struct ahd_softc *ahd)
! 9360: {
! 9361: /*
! 9362: * We should be able to determine the SEEPROM type
! 9363: * from the flexport logic, but unfortunately not
! 9364: * all implementations have this logic and there is
! 9365: * no programatic method for determining if the logic
! 9366: * is present.
! 9367: */
! 9368: return (1);
! 9369: #if 0
! 9370: uint8_t seetype;
! 9371: int error;
! 9372:
! 9373: error = ahd_read_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, &seetype);
! 9374: if (error != 0
! 9375: || ((seetype & FLX_ROMSTAT_SEECFG) == FLX_ROMSTAT_SEE_NONE))
! 9376: return (0);
! 9377: return (1);
! 9378: #endif
! 9379: }
! 9380:
! 9381: void
! 9382: ahd_release_seeprom(struct ahd_softc *ahd)
! 9383: {
! 9384: /* Currently a no-op */
! 9385: }
! 9386:
! 9387: int
! 9388: ahd_write_flexport(struct ahd_softc *ahd, u_int addr, u_int value)
! 9389: {
! 9390: int error;
! 9391:
! 9392: AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
! 9393: if (addr > 7)
! 9394: panic("ahd_write_flexport: address out of range");
! 9395: ahd_outb(ahd, BRDCTL, BRDEN|(addr << 3));
! 9396: error = ahd_wait_flexport(ahd);
! 9397: if (error != 0)
! 9398: return (error);
! 9399: ahd_outb(ahd, BRDDAT, value);
! 9400: ahd_flush_device_writes(ahd);
! 9401: ahd_outb(ahd, BRDCTL, BRDSTB|BRDEN|(addr << 3));
! 9402: ahd_flush_device_writes(ahd);
! 9403: ahd_outb(ahd, BRDCTL, BRDEN|(addr << 3));
! 9404: ahd_flush_device_writes(ahd);
! 9405: ahd_outb(ahd, BRDCTL, 0);
! 9406: ahd_flush_device_writes(ahd);
! 9407: return (0);
! 9408: }
! 9409:
! 9410: int
! 9411: ahd_read_flexport(struct ahd_softc *ahd, u_int addr, uint8_t *value)
! 9412: {
! 9413: int error;
! 9414:
! 9415: AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
! 9416: if (addr > 7)
! 9417: panic("ahd_read_flexport: address out of range");
! 9418: ahd_outb(ahd, BRDCTL, BRDRW|BRDEN|(addr << 3));
! 9419: error = ahd_wait_flexport(ahd);
! 9420: if (error != 0)
! 9421: return (error);
! 9422: *value = ahd_inb(ahd, BRDDAT);
! 9423: ahd_outb(ahd, BRDCTL, 0);
! 9424: ahd_flush_device_writes(ahd);
! 9425: return (0);
! 9426: }
! 9427:
! 9428: /*
! 9429: * Wait at most 2 seconds for flexport arbitration to succeed.
! 9430: */
! 9431: int
! 9432: ahd_wait_flexport(struct ahd_softc *ahd)
! 9433: {
! 9434: int cnt;
! 9435:
! 9436: AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
! 9437: cnt = 1000000 * 2 / 5;
! 9438: while ((ahd_inb(ahd, BRDCTL) & FLXARBACK) == 0 && --cnt)
! 9439: aic_delay(5);
! 9440:
! 9441: if (cnt == 0)
! 9442: return (ETIMEDOUT);
! 9443: return (0);
! 9444: }
! 9445:
! 9446: /************************* Target Mode ****************************************/
! 9447: #ifdef AHD_TARGET_MODE
! 9448: cam_status
! 9449: ahd_find_tmode_devs(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb,
! 9450: struct ahd_tmode_tstate **tstate,
! 9451: struct ahd_tmode_lstate **lstate,
! 9452: int notfound_failure)
! 9453: {
! 9454:
! 9455: if ((ahd->features & AHD_TARGETMODE) == 0)
! 9456: return (CAM_REQ_INVALID);
! 9457:
! 9458: /*
! 9459: * Handle the 'black hole' device that sucks up
! 9460: * requests to unattached luns on enabled targets.
! 9461: */
! 9462: if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD
! 9463: && ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) {
! 9464: *tstate = NULL;
! 9465: *lstate = ahd->black_hole;
! 9466: } else {
! 9467: u_int max_id;
! 9468:
! 9469: max_id = (ahd->features & AHD_WIDE) ? 15 : 7;
! 9470: if (ccb->ccb_h.target_id > max_id)
! 9471: return (CAM_TID_INVALID);
! 9472:
! 9473: if (ccb->ccb_h.target_lun >= AHD_NUM_LUNS)
! 9474: return (CAM_LUN_INVALID);
! 9475:
! 9476: *tstate = ahd->enabled_targets[ccb->ccb_h.target_id];
! 9477: *lstate = NULL;
! 9478: if (*tstate != NULL)
! 9479: *lstate =
! 9480: (*tstate)->enabled_luns[ccb->ccb_h.target_lun];
! 9481: }
! 9482:
! 9483: if (notfound_failure != 0 && *lstate == NULL)
! 9484: return (CAM_PATH_INVALID);
! 9485:
! 9486: return (CAM_REQ_CMP);
! 9487: }
! 9488:
! 9489: void
! 9490: ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
! 9491: {
! 9492: #if NOT_YET
! 9493: struct ahd_tmode_tstate *tstate;
! 9494: struct ahd_tmode_lstate *lstate;
! 9495: struct ccb_en_lun *cel;
! 9496: cam_status status;
! 9497: u_int target;
! 9498: u_int lun;
! 9499: u_int target_mask;
! 9500: int s;
! 9501: char channel;
! 9502:
! 9503: status = ahd_find_tmode_devs(ahd, sim, ccb, &tstate, &lstate,
! 9504: /*notfound_failure*/FALSE);
! 9505:
! 9506: if (status != CAM_REQ_CMP) {
! 9507: ccb->ccb_h.status = status;
! 9508: return;
! 9509: }
! 9510:
! 9511: if ((ahd->features & AHD_MULTIROLE) != 0) {
! 9512: u_int our_id;
! 9513:
! 9514: our_id = ahd->our_id;
! 9515: if (ccb->ccb_h.target_id != our_id) {
! 9516: if ((ahd->features & AHD_MULTI_TID) != 0
! 9517: && (ahd->flags & AHD_INITIATORROLE) != 0) {
! 9518: /*
! 9519: * Only allow additional targets if
! 9520: * the initiator role is disabled.
! 9521: * The hardware cannot handle a re-select-in
! 9522: * on the initiator id during a re-select-out
! 9523: * on a different target id.
! 9524: */
! 9525: status = CAM_TID_INVALID;
! 9526: } else if ((ahd->flags & AHD_INITIATORROLE) != 0
! 9527: || ahd->enabled_luns > 0) {
! 9528: /*
! 9529: * Only allow our target id to change
! 9530: * if the initiator role is not configured
! 9531: * and there are no enabled luns which
! 9532: * are attached to the currently registered
! 9533: * scsi id.
! 9534: */
! 9535: status = CAM_TID_INVALID;
! 9536: }
! 9537: }
! 9538: }
! 9539:
! 9540: if (status != CAM_REQ_CMP) {
! 9541: ccb->ccb_h.status = status;
! 9542: return;
! 9543: }
! 9544:
! 9545: /*
! 9546: * We now have an id that is valid.
! 9547: * If we aren't in target mode, switch modes.
! 9548: */
! 9549: if ((ahd->flags & AHD_TARGETROLE) == 0
! 9550: && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) {
! 9551: int s;
! 9552:
! 9553: printf("Configuring Target Mode\n");
! 9554: ahd_lock(ahd, &s);
! 9555: if (LIST_FIRST(&ahd->pending_scbs) != NULL) {
! 9556: ccb->ccb_h.status = CAM_BUSY;
! 9557: ahd_unlock(ahd, &s);
! 9558: return;
! 9559: }
! 9560: ahd->flags |= AHD_TARGETROLE;
! 9561: if ((ahd->features & AHD_MULTIROLE) == 0)
! 9562: ahd->flags &= ~AHD_INITIATORROLE;
! 9563: ahd_pause(ahd);
! 9564: ahd_loadseq(ahd);
! 9565: ahd_restart(ahd);
! 9566: ahd_unlock(ahd, &s);
! 9567: }
! 9568: cel = &ccb->cel;
! 9569: target = ccb->ccb_h.target_id;
! 9570: lun = ccb->ccb_h.target_lun;
! 9571: channel = SCSI_CHANNEL(ahd, sim);
! 9572: target_mask = 0x01 << target;
! 9573: if (channel == 'B')
! 9574: target_mask <<= 8;
! 9575:
! 9576: if (cel->enable != 0) {
! 9577: u_int scsiseq1;
! 9578:
! 9579: /* Are we already enabled?? */
! 9580: if (lstate != NULL) {
! 9581: xpt_print_path(ccb->ccb_h.path);
! 9582: printf("Lun already enabled\n");
! 9583: ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
! 9584: return;
! 9585: }
! 9586:
! 9587: if (cel->grp6_len != 0
! 9588: || cel->grp7_len != 0) {
! 9589: /*
! 9590: * Don't (yet?) support vendor
! 9591: * specific commands.
! 9592: */
! 9593: ccb->ccb_h.status = CAM_REQ_INVALID;
! 9594: printf("Non-zero Group Codes\n");
! 9595: return;
! 9596: }
! 9597:
! 9598: /*
! 9599: * Seems to be okay.
! 9600: * Setup our data structures.
! 9601: */
! 9602: if (target != CAM_TARGET_WILDCARD && tstate == NULL) {
! 9603: tstate = ahd_alloc_tstate(ahd, target, channel);
! 9604: if (tstate == NULL) {
! 9605: xpt_print_path(ccb->ccb_h.path);
! 9606: printf("Couldn't allocate tstate\n");
! 9607: ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
! 9608: return;
! 9609: }
! 9610: }
! 9611: lstate = malloc(sizeof(*lstate), M_DEVBUF, M_NOWAIT);
! 9612: if (lstate == NULL) {
! 9613: xpt_print_path(ccb->ccb_h.path);
! 9614: printf("Couldn't allocate lstate\n");
! 9615: ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
! 9616: return;
! 9617: }
! 9618: memset(lstate, 0, sizeof(*lstate));
! 9619: status = xpt_create_path(&lstate->path, /*periph*/NULL,
! 9620: xpt_path_path_id(ccb->ccb_h.path),
! 9621: xpt_path_target_id(ccb->ccb_h.path),
! 9622: xpt_path_lun_id(ccb->ccb_h.path));
! 9623: if (status != CAM_REQ_CMP) {
! 9624: free(lstate, M_DEVBUF);
! 9625: xpt_print_path(ccb->ccb_h.path);
! 9626: printf("Couldn't allocate path\n");
! 9627: ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
! 9628: return;
! 9629: }
! 9630: SLIST_INIT(&lstate->accept_tios);
! 9631: SLIST_INIT(&lstate->immed_notifies);
! 9632: ahd_lock(ahd, &s);
! 9633: ahd_pause(ahd);
! 9634: if (target != CAM_TARGET_WILDCARD) {
! 9635: tstate->enabled_luns[lun] = lstate;
! 9636: ahd->enabled_luns++;
! 9637:
! 9638: if ((ahd->features & AHD_MULTI_TID) != 0) {
! 9639: u_int targid_mask;
! 9640:
! 9641: targid_mask = ahd_inw(ahd, TARGID);
! 9642: targid_mask |= target_mask;
! 9643: ahd_outw(ahd, TARGID, targid_mask);
! 9644: ahd_update_scsiid(ahd, targid_mask);
! 9645: } else {
! 9646: u_int our_id;
! 9647: char channel;
! 9648:
! 9649: channel = SCSI_CHANNEL(ahd, sim);
! 9650: our_id = SCSI_SCSI_ID(ahd, sim);
! 9651:
! 9652: /*
! 9653: * This can only happen if selections
! 9654: * are not enabled
! 9655: */
! 9656: if (target != our_id) {
! 9657: u_int sblkctl;
! 9658: char cur_channel;
! 9659: int swap;
! 9660:
! 9661: sblkctl = ahd_inb(ahd, SBLKCTL);
! 9662: cur_channel = (sblkctl & SELBUSB)
! 9663: ? 'B' : 'A';
! 9664: if ((ahd->features & AHD_TWIN) == 0)
! 9665: cur_channel = 'A';
! 9666: swap = cur_channel != channel;
! 9667: ahd->our_id = target;
! 9668:
! 9669: if (swap)
! 9670: ahd_outb(ahd, SBLKCTL,
! 9671: sblkctl ^ SELBUSB);
! 9672:
! 9673: ahd_outb(ahd, SCSIID, target);
! 9674:
! 9675: if (swap)
! 9676: ahd_outb(ahd, SBLKCTL, sblkctl);
! 9677: }
! 9678: }
! 9679: } else
! 9680: ahd->black_hole = lstate;
! 9681: /* Allow select-in operations */
! 9682: if (ahd->black_hole != NULL && ahd->enabled_luns > 0) {
! 9683: scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE);
! 9684: scsiseq1 |= ENSELI;
! 9685: ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq1);
! 9686: scsiseq1 = ahd_inb(ahd, SCSISEQ1);
! 9687: scsiseq1 |= ENSELI;
! 9688: ahd_outb(ahd, SCSISEQ1, scsiseq1);
! 9689: }
! 9690: ahd_unpause(ahd);
! 9691: ahd_unlock(ahd, &s);
! 9692: ccb->ccb_h.status = CAM_REQ_CMP;
! 9693: xpt_print_path(ccb->ccb_h.path);
! 9694: printf("Lun now enabled for target mode\n");
! 9695: } else {
! 9696: struct scb *scb;
! 9697: int i, empty;
! 9698:
! 9699: if (lstate == NULL) {
! 9700: ccb->ccb_h.status = CAM_LUN_INVALID;
! 9701: return;
! 9702: }
! 9703:
! 9704: ahd_lock(ahd, &s);
! 9705:
! 9706: ccb->ccb_h.status = CAM_REQ_CMP;
! 9707: LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {
! 9708: struct ccb_hdr *ccbh;
! 9709:
! 9710: ccbh = &scb->io_ctx->ccb_h;
! 9711: if (ccbh->func_code == XPT_CONT_TARGET_IO
! 9712: && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){
! 9713: printf("CTIO pending\n");
! 9714: ccb->ccb_h.status = CAM_REQ_INVALID;
! 9715: ahd_unlock(ahd, &s);
! 9716: return;
! 9717: }
! 9718: }
! 9719:
! 9720: if (SLIST_FIRST(&lstate->accept_tios) != NULL) {
! 9721: printf("ATIOs pending\n");
! 9722: ccb->ccb_h.status = CAM_REQ_INVALID;
! 9723: }
! 9724:
! 9725: if (SLIST_FIRST(&lstate->immed_notifies) != NULL) {
! 9726: printf("INOTs pending\n");
! 9727: ccb->ccb_h.status = CAM_REQ_INVALID;
! 9728: }
! 9729:
! 9730: if (ccb->ccb_h.status != CAM_REQ_CMP) {
! 9731: ahd_unlock(ahd, &s);
! 9732: return;
! 9733: }
! 9734:
! 9735: xpt_print_path(ccb->ccb_h.path);
! 9736: printf("Target mode disabled\n");
! 9737: xpt_free_path(lstate->path);
! 9738: free(lstate, M_DEVBUF);
! 9739:
! 9740: ahd_pause(ahd);
! 9741: /* Can we clean up the target too? */
! 9742: if (target != CAM_TARGET_WILDCARD) {
! 9743: tstate->enabled_luns[lun] = NULL;
! 9744: ahd->enabled_luns--;
! 9745: for (empty = 1, i = 0; i < 8; i++)
! 9746: if (tstate->enabled_luns[i] != NULL) {
! 9747: empty = 0;
! 9748: break;
! 9749: }
! 9750:
! 9751: if (empty) {
! 9752: ahd_free_tstate(ahd, target, channel,
! 9753: /*force*/FALSE);
! 9754: if (ahd->features & AHD_MULTI_TID) {
! 9755: u_int targid_mask;
! 9756:
! 9757: targid_mask = ahd_inw(ahd, TARGID);
! 9758: targid_mask &= ~target_mask;
! 9759: ahd_outw(ahd, TARGID, targid_mask);
! 9760: ahd_update_scsiid(ahd, targid_mask);
! 9761: }
! 9762: }
! 9763: } else {
! 9764:
! 9765: ahd->black_hole = NULL;
! 9766:
! 9767: /*
! 9768: * We can't allow selections without
! 9769: * our black hole device.
! 9770: */
! 9771: empty = TRUE;
! 9772: }
! 9773: if (ahd->enabled_luns == 0) {
! 9774: /* Disallow select-in */
! 9775: u_int scsiseq1;
! 9776:
! 9777: scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE);
! 9778: scsiseq1 &= ~ENSELI;
! 9779: ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq1);
! 9780: scsiseq1 = ahd_inb(ahd, SCSISEQ1);
! 9781: scsiseq1 &= ~ENSELI;
! 9782: ahd_outb(ahd, SCSISEQ1, scsiseq1);
! 9783:
! 9784: if ((ahd->features & AHD_MULTIROLE) == 0) {
! 9785: printf("Configuring Initiator Mode\n");
! 9786: ahd->flags &= ~AHD_TARGETROLE;
! 9787: ahd->flags |= AHD_INITIATORROLE;
! 9788: ahd_pause(ahd);
! 9789: ahd_loadseq(ahd);
! 9790: ahd_restart(ahd);
! 9791: /*
! 9792: * Unpaused. The extra unpause
! 9793: * that follows is harmless.
! 9794: */
! 9795: }
! 9796: }
! 9797: ahd_unpause(ahd);
! 9798: ahd_unlock(ahd, &s);
! 9799: }
! 9800: #endif
! 9801: }
! 9802:
! 9803: void
! 9804: ahd_update_scsiid(struct ahd_softc *ahd, u_int targid_mask)
! 9805: {
! 9806: #if NOT_YET
! 9807: u_int scsiid_mask;
! 9808: u_int scsiid;
! 9809:
! 9810: if ((ahd->features & AHD_MULTI_TID) == 0)
! 9811: panic("ahd_update_scsiid called on non-multitid unit");
! 9812:
! 9813: /*
! 9814: * Since we will rely on the TARGID mask
! 9815: * for selection enables, ensure that OID
! 9816: * in SCSIID is not set to some other ID
! 9817: * that we don't want to allow selections on.
! 9818: */
! 9819: if ((ahd->features & AHD_ULTRA2) != 0)
! 9820: scsiid = ahd_inb(ahd, SCSIID_ULTRA2);
! 9821: else
! 9822: scsiid = ahd_inb(ahd, SCSIID);
! 9823: scsiid_mask = 0x1 << (scsiid & OID);
! 9824: if ((targid_mask & scsiid_mask) == 0) {
! 9825: u_int our_id;
! 9826:
! 9827: /* ffs counts from 1 */
! 9828: our_id = ffs(targid_mask);
! 9829: if (our_id == 0)
! 9830: our_id = ahd->our_id;
! 9831: else
! 9832: our_id--;
! 9833: scsiid &= TID;
! 9834: scsiid |= our_id;
! 9835: }
! 9836: if ((ahd->features & AHD_ULTRA2) != 0)
! 9837: ahd_outb(ahd, SCSIID_ULTRA2, scsiid);
! 9838: else
! 9839: ahd_outb(ahd, SCSIID, scsiid);
! 9840: #endif
! 9841: }
! 9842:
! 9843: void
! 9844: ahd_run_tqinfifo(struct ahd_softc *ahd, int paused)
! 9845: {
! 9846: struct target_cmd *cmd;
! 9847:
! 9848: ahd_sync_tqinfifo(ahd, BUS_DMASYNC_POSTREAD);
! 9849: while ((cmd = &ahd->targetcmds[ahd->tqinfifonext])->cmd_valid != 0) {
! 9850:
! 9851: /*
! 9852: * Only advance through the queue if we
! 9853: * have the resources to process the command.
! 9854: */
! 9855: if (ahd_handle_target_cmd(ahd, cmd) != 0)
! 9856: break;
! 9857:
! 9858: cmd->cmd_valid = 0;
! 9859: ahd_dmamap_sync(ahd, ahd->parent_dmat /*shared_data_dmat*/,
! 9860: ahd->shared_data_dmamap,
! 9861: ahd_targetcmd_offset(ahd, ahd->tqinfifonext),
! 9862: sizeof(struct target_cmd),
! 9863: BUS_DMASYNC_PREREAD);
! 9864: ahd->tqinfifonext++;
! 9865:
! 9866: /*
! 9867: * Lazily update our position in the target mode incoming
! 9868: * command queue as seen by the sequencer.
! 9869: */
! 9870: if ((ahd->tqinfifonext & (HOST_TQINPOS - 1)) == 1) {
! 9871: u_int hs_mailbox;
! 9872:
! 9873: hs_mailbox = ahd_inb(ahd, HS_MAILBOX);
! 9874: hs_mailbox &= ~HOST_TQINPOS;
! 9875: hs_mailbox |= ahd->tqinfifonext & HOST_TQINPOS;
! 9876: ahd_outb(ahd, HS_MAILBOX, hs_mailbox);
! 9877: }
! 9878: }
! 9879: }
! 9880:
! 9881: int
! 9882: ahd_handle_target_cmd(struct ahd_softc *ahd, struct target_cmd *cmd)
! 9883: {
! 9884: struct ahd_tmode_tstate *tstate;
! 9885: struct ahd_tmode_lstate *lstate;
! 9886: struct ccb_accept_tio *atio;
! 9887: uint8_t *byte;
! 9888: int initiator;
! 9889: int target;
! 9890: int lun;
! 9891:
! 9892: initiator = SCSIID_TARGET(ahd, cmd->scsiid);
! 9893: target = SCSIID_OUR_ID(cmd->scsiid);
! 9894: lun = (cmd->identify & MSG_IDENTIFY_LUNMASK);
! 9895:
! 9896: byte = cmd->bytes;
! 9897: tstate = ahd->enabled_targets[target];
! 9898: lstate = NULL;
! 9899: if (tstate != NULL)
! 9900: lstate = tstate->enabled_luns[lun];
! 9901:
! 9902: /*
! 9903: * Commands for disabled luns go to the black hole driver.
! 9904: */
! 9905: if (lstate == NULL)
! 9906: lstate = ahd->black_hole;
! 9907:
! 9908: atio = (struct ccb_accept_tio*)SLIST_FIRST(&lstate->accept_tios);
! 9909: if (atio == NULL) {
! 9910: ahd->flags |= AHD_TQINFIFO_BLOCKED;
! 9911: /*
! 9912: * Wait for more ATIOs from the peripheral driver for this lun.
! 9913: */
! 9914: return (1);
! 9915: } else
! 9916: ahd->flags &= ~AHD_TQINFIFO_BLOCKED;
! 9917: #ifdef AHD_DEBUG
! 9918: if ((ahd_debug & AHD_SHOW_TQIN) != 0)
! 9919: printf("Incoming command from %d for %d:%d%s\n",
! 9920: initiator, target, lun,
! 9921: lstate == ahd->black_hole ? "(Black Holed)" : "");
! 9922: #endif
! 9923: SLIST_REMOVE_HEAD(&lstate->accept_tios, sim_links.sle);
! 9924:
! 9925: if (lstate == ahd->black_hole) {
! 9926: /* Fill in the wildcards */
! 9927: atio->ccb_h.target_id = target;
! 9928: atio->ccb_h.target_lun = lun;
! 9929: }
! 9930:
! 9931: /*
! 9932: * Package it up and send it off to
! 9933: * whomever has this lun enabled.
! 9934: */
! 9935: atio->sense_len = 0;
! 9936: atio->init_id = initiator;
! 9937: if (byte[0] != 0xFF) {
! 9938: /* Tag was included */
! 9939: atio->tag_action = *byte++;
! 9940: atio->tag_id = *byte++;
! 9941: atio->ccb_h.flags = CAM_TAG_ACTION_VALID;
! 9942: } else {
! 9943: atio->ccb_h.flags = 0;
! 9944: }
! 9945: byte++;
! 9946:
! 9947: /* Okay. Now determine the cdb size based on the command code */
! 9948: switch (*byte >> CMD_GROUP_CODE_SHIFT) {
! 9949: case 0:
! 9950: atio->cdb_len = 6;
! 9951: break;
! 9952: case 1:
! 9953: case 2:
! 9954: atio->cdb_len = 10;
! 9955: break;
! 9956: case 4:
! 9957: atio->cdb_len = 16;
! 9958: break;
! 9959: case 5:
! 9960: atio->cdb_len = 12;
! 9961: break;
! 9962: case 3:
! 9963: default:
! 9964: /* Only copy the opcode. */
! 9965: atio->cdb_len = 1;
! 9966: printf("Reserved or VU command code type encountered\n");
! 9967: break;
! 9968: }
! 9969:
! 9970: memcpy(atio->cdb_io.cdb_bytes, byte, atio->cdb_len);
! 9971:
! 9972: atio->ccb_h.status |= CAM_CDB_RECVD;
! 9973:
! 9974: if ((cmd->identify & MSG_IDENTIFY_DISCFLAG) == 0) {
! 9975: /*
! 9976: * We weren't allowed to disconnect.
! 9977: * We're hanging on the bus until a
! 9978: * continue target I/O comes in response
! 9979: * to this accept tio.
! 9980: */
! 9981: #ifdef AHD_DEBUG
! 9982: if ((ahd_debug & AHD_SHOW_TQIN) != 0)
! 9983: printf("Received Immediate Command %d:%d:%d - %p\n",
! 9984: initiator, target, lun, ahd->pending_device);
! 9985: #endif
! 9986: ahd->pending_device = lstate;
! 9987: ahd_freeze_ccb((union ccb *)atio);
! 9988: atio->ccb_h.flags |= CAM_DIS_DISCONNECT;
! 9989: }
! 9990: xpt_done((union ccb*)atio);
! 9991: return (0);
! 9992: }
! 9993:
! 9994: #endif
! 9995:
! 9996: int
! 9997: ahd_createdmamem(struct ahd_softc *ahd, size_t size, struct map_node *map,
! 9998: const char *what)
! 9999: {
! 10000: bus_dma_tag_t tag = ahd->parent_dmat;
! 10001: int nseg, error;
! 10002:
! 10003: bzero(map, sizeof(*map));
! 10004:
! 10005: if ((error = bus_dmamap_create(tag, size, 1, size, 0, BUS_DMA_NOWAIT,
! 10006: &map->dmamap)) != 0) {
! 10007: printf("%s: failed to create DMA map for %s, error = %d\n",
! 10008: ahd_name(ahd), what, error);
! 10009: return (error);
! 10010: }
! 10011:
! 10012: if ((error = bus_dmamem_alloc(tag, size, PAGE_SIZE, 0, &map->dmaseg,
! 10013: 1, &nseg, BUS_DMA_NOWAIT)) != 0) {
! 10014: printf("%s: failed to allocate DMA mem for %s, error = %d\n",
! 10015: ahd_name(ahd), what, error);
! 10016: goto destroy;
! 10017: }
! 10018:
! 10019: if ((error = bus_dmamem_map(tag, &map->dmaseg, nseg, size,
! 10020: (caddr_t *)&map->vaddr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
! 10021: printf("%s: failed to map DMA mem for %s, error = %d\n",
! 10022: ahd_name(ahd), what, error);
! 10023: goto free;
! 10024: }
! 10025:
! 10026: if ((error = bus_dmamap_load(tag, map->dmamap, map->vaddr, size, NULL,
! 10027: BUS_DMA_NOWAIT)) != 0) {
! 10028: printf("%s: failed to load DMA map for %s, error = %d\n",
! 10029: ahd_name(ahd), what, error);
! 10030: goto unmap;
! 10031: }
! 10032:
! 10033: map->size = size;
! 10034: map->busaddr = map->dmamap->dm_segs[0].ds_addr;
! 10035: return (0);
! 10036:
! 10037: unmap:
! 10038: bus_dmamem_unmap(tag, map->vaddr, size);
! 10039: free:
! 10040: bus_dmamem_free(tag, &map->dmaseg, 1);
! 10041: destroy:
! 10042: bus_dmamap_destroy(tag, map->dmamap);
! 10043:
! 10044: bzero(map, sizeof(*map));
! 10045: return (error);
! 10046: }
! 10047:
! 10048: void
! 10049: ahd_freedmamem(struct ahd_softc* ahd, struct map_node *map)
! 10050: {
! 10051: bus_dma_tag_t tag = ahd->parent_dmat;
! 10052:
! 10053: bus_dmamap_unload(tag, map->dmamap);
! 10054: bus_dmamem_unmap(tag, map->vaddr, map->size);
! 10055: bus_dmamem_free(tag, &map->dmaseg, 1);
! 10056: bus_dmamap_destroy(tag, map->dmamap);
! 10057: }
! 10058:
! 10059: char *
! 10060: ahd_name(struct ahd_softc *ahd)
! 10061: {
! 10062: return (ahd->name);
! 10063: }
! 10064:
! 10065: void
! 10066: ahd_known_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
! 10067: {
! 10068: ahd->src_mode = src;
! 10069: ahd->dst_mode = dst;
! 10070: ahd->saved_src_mode = src;
! 10071: ahd->saved_dst_mode = dst;
! 10072: }
! 10073:
! 10074: ahd_mode_state
! 10075: ahd_build_mode_state(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
! 10076: {
! 10077: return ((src << SRC_MODE_SHIFT) | (dst << DST_MODE_SHIFT));
! 10078: }
! 10079:
! 10080: void
! 10081: ahd_extract_mode_state(struct ahd_softc *ahd, ahd_mode_state state,
! 10082: ahd_mode *src, ahd_mode *dst)
! 10083: {
! 10084: *src = (state & SRC_MODE) >> SRC_MODE_SHIFT;
! 10085: *dst = (state & DST_MODE) >> DST_MODE_SHIFT;
! 10086: }
! 10087:
! 10088: void
! 10089: ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
! 10090: {
! 10091: if (ahd->src_mode == src && ahd->dst_mode == dst)
! 10092: return;
! 10093: #ifdef AHD_DEBUG
! 10094: if (ahd->src_mode == AHD_MODE_UNKNOWN
! 10095: || ahd->dst_mode == AHD_MODE_UNKNOWN)
! 10096: panic("Setting mode prior to saving it.");
! 10097: if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
! 10098: printf("%s: Setting mode 0x%x\n", ahd_name(ahd),
! 10099: ahd_build_mode_state(ahd, src, dst));
! 10100: #endif
! 10101: ahd_outb(ahd, MODE_PTR, ahd_build_mode_state(ahd, src, dst));
! 10102: ahd->src_mode = src;
! 10103: ahd->dst_mode = dst;
! 10104: }
! 10105:
! 10106: void
! 10107: ahd_update_modes(struct ahd_softc *ahd)
! 10108: {
! 10109: ahd_mode_state mode_ptr;
! 10110: ahd_mode src;
! 10111: ahd_mode dst;
! 10112:
! 10113: mode_ptr = ahd_inb(ahd, MODE_PTR);
! 10114: #ifdef AHD_DEBUG
! 10115: if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)
! 10116: printf("Reading mode 0x%x\n", mode_ptr);
! 10117: #endif
! 10118: ahd_extract_mode_state(ahd, mode_ptr, &src, &dst);
! 10119: ahd_known_modes(ahd, src, dst);
! 10120: }
! 10121:
! 10122: void
! 10123: ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode,
! 10124: ahd_mode dstmode, const char *file, int line)
! 10125: {
! 10126: #ifdef AHD_DEBUG
! 10127: if ((srcmode & AHD_MK_MSK(ahd->src_mode)) == 0
! 10128: || (dstmode & AHD_MK_MSK(ahd->dst_mode)) == 0) {
! 10129: panic("%s:%s:%d: Mode assertion failed.",
! 10130: ahd_name(ahd), file, line);
! 10131: }
! 10132: #endif
! 10133: }
! 10134:
! 10135: ahd_mode_state
! 10136: ahd_save_modes(struct ahd_softc *ahd)
! 10137: {
! 10138: if (ahd->src_mode == AHD_MODE_UNKNOWN
! 10139: || ahd->dst_mode == AHD_MODE_UNKNOWN)
! 10140: ahd_update_modes(ahd);
! 10141:
! 10142: return (ahd_build_mode_state(ahd, ahd->src_mode, ahd->dst_mode));
! 10143: }
! 10144:
! 10145: void
! 10146: ahd_restore_modes(struct ahd_softc *ahd, ahd_mode_state state)
! 10147: {
! 10148: ahd_mode src;
! 10149: ahd_mode dst;
! 10150:
! 10151: ahd_extract_mode_state(ahd, state, &src, &dst);
! 10152: ahd_set_modes(ahd, src, dst);
! 10153: }
! 10154:
! 10155: /*
! 10156: * Determine whether the sequencer has halted code execution.
! 10157: * Returns non-zero status if the sequencer is stopped.
! 10158: */
! 10159: int
! 10160: ahd_is_paused(struct ahd_softc *ahd)
! 10161: {
! 10162: return ((ahd_inb(ahd, HCNTRL) & PAUSE) != 0);
! 10163: }
! 10164:
! 10165: /*
! 10166: * Request that the sequencer stop and wait, indefinitely, for it
! 10167: * to stop. The sequencer will only acknowledge that it is paused
! 10168: * once it has reached an instruction boundary and PAUSEDIS is
! 10169: * cleared in the SEQCTL register. The sequencer may use PAUSEDIS
! 10170: * for critical sections.
! 10171: */
! 10172: void
! 10173: ahd_pause(struct ahd_softc *ahd)
! 10174: {
! 10175: ahd_outb(ahd, HCNTRL, ahd->pause);
! 10176:
! 10177: /*
! 10178: * Since the sequencer can disable pausing in a critical section, we
! 10179: * must loop until it actually stops.
! 10180: */
! 10181: while (ahd_is_paused(ahd) == 0)
! 10182: ;
! 10183: }
! 10184:
! 10185: /*
! 10186: * Allow the sequencer to continue program execution.
! 10187: * We check here to ensure that no additional interrupt
! 10188: * sources that would cause the sequencer to halt have been
! 10189: * asserted. If, for example, a SCSI bus reset is detected
! 10190: * while we are fielding a different, pausing, interrupt type,
! 10191: * we don't want to release the sequencer before going back
! 10192: * into our interrupt handler and dealing with this new
! 10193: * condition.
! 10194: */
! 10195: void
! 10196: ahd_unpause(struct ahd_softc *ahd)
! 10197: {
! 10198: /*
! 10199: * Automatically restore our modes to those saved
! 10200: * prior to the first change of the mode.
! 10201: */
! 10202: if (ahd->saved_src_mode != AHD_MODE_UNKNOWN
! 10203: && ahd->saved_dst_mode != AHD_MODE_UNKNOWN) {
! 10204: if ((ahd->flags & AHD_UPDATE_PEND_CMDS) != 0)
! 10205: ahd_reset_cmds_pending(ahd);
! 10206: ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);
! 10207: }
! 10208:
! 10209: if ((ahd_inb(ahd, INTSTAT) & ~CMDCMPLT) == 0)
! 10210: ahd_outb(ahd, HCNTRL, ahd->unpause);
! 10211:
! 10212: ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN);
! 10213: }
! 10214:
! 10215: void *
! 10216: ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
! 10217: void *sgptr, bus_addr_t addr, bus_size_t len, int last)
! 10218: {
! 10219: scb->sg_count++;
! 10220: if (sizeof(bus_addr_t) > 4
! 10221: && (ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
! 10222: struct ahd_dma64_seg *sg;
! 10223:
! 10224: sg = (struct ahd_dma64_seg *)sgptr;
! 10225: sg->addr = aic_htole64(addr);
! 10226: sg->len = aic_htole32(len | (last ? AHD_DMA_LAST_SEG : 0));
! 10227: return (sg + 1);
! 10228: } else {
! 10229: struct ahd_dma_seg *sg;
! 10230:
! 10231: sg = (struct ahd_dma_seg *)sgptr;
! 10232: sg->addr = aic_htole32(addr & 0xFFFFFFFF);
! 10233: sg->len = aic_htole32(len | ((addr >> 8) & 0x7F000000)
! 10234: | (last ? AHD_DMA_LAST_SEG : 0));
! 10235: return (sg + 1);
! 10236: }
! 10237: }
! 10238:
! 10239: void
! 10240: ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb)
! 10241: {
! 10242: /* XXX Handle target mode SCBs. */
! 10243: scb->crc_retry_count = 0;
! 10244: if ((scb->flags & SCB_PACKETIZED) != 0) {
! 10245: /* XXX what about ACA?? It is type 4, but TAG_TYPE == 0x3. */
! 10246: scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE;
! 10247: } else {
! 10248: if (aic_get_transfer_length(scb) & 0x01)
! 10249: scb->hscb->task_attribute = SCB_XFERLEN_ODD;
! 10250: else
! 10251: scb->hscb->task_attribute = 0;
! 10252: }
! 10253:
! 10254: if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR
! 10255: || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0)
! 10256: scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr =
! 10257: aic_htole32(scb->sense_busaddr);
! 10258: }
! 10259:
! 10260: void
! 10261: ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb)
! 10262: {
! 10263: /*
! 10264: * Copy the first SG into the "current" data pointer area.
! 10265: */
! 10266: if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {
! 10267: struct ahd_dma64_seg *sg;
! 10268:
! 10269: sg = (struct ahd_dma64_seg *)scb->sg_list;
! 10270: scb->hscb->dataptr = sg->addr;
! 10271: scb->hscb->datacnt = sg->len;
! 10272: } else {
! 10273: struct ahd_dma_seg *sg;
! 10274: uint32_t *dataptr_words;
! 10275:
! 10276: sg = (struct ahd_dma_seg *)scb->sg_list;
! 10277: dataptr_words = (uint32_t*)&scb->hscb->dataptr;
! 10278: dataptr_words[0] = sg->addr;
! 10279: dataptr_words[1] = 0;
! 10280: if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) {
! 10281: uint64_t high_addr;
! 10282:
! 10283: high_addr = aic_le32toh(sg->len) & 0x7F000000;
! 10284: scb->hscb->dataptr |= aic_htole64(high_addr << 8);
! 10285: }
! 10286: scb->hscb->datacnt = sg->len;
! 10287: }
! 10288: /*
! 10289: * Note where to find the SG entries in bus space.
! 10290: * We also set the full residual flag which the
! 10291: * sequencer will clear as soon as a data transfer
! 10292: * occurs.
! 10293: */
! 10294: scb->hscb->sgptr = aic_htole32(scb->sg_list_busaddr|SG_FULL_RESID);
! 10295: }
! 10296:
! 10297: void
! 10298: ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb)
! 10299: {
! 10300: scb->hscb->sgptr = aic_htole32(SG_LIST_NULL);
! 10301: scb->hscb->dataptr = 0;
! 10302: scb->hscb->datacnt = 0;
! 10303: }
! 10304:
! 10305: size_t
! 10306: ahd_sg_size(struct ahd_softc *ahd)
! 10307: {
! 10308: if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)
! 10309: return (sizeof(struct ahd_dma64_seg));
! 10310: return (sizeof(struct ahd_dma_seg));
! 10311: }
! 10312:
! 10313: void *
! 10314: ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr)
! 10315: {
! 10316: bus_addr_t sg_offset;
! 10317:
! 10318: /* sg_list_phys points to entry 1, not 0 */
! 10319: sg_offset = sg_busaddr - (scb->sg_list_busaddr - ahd_sg_size(ahd));
! 10320: return ((uint8_t *)scb->sg_list + sg_offset);
! 10321: }
! 10322:
! 10323: uint32_t
! 10324: ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg)
! 10325: {
! 10326: bus_addr_t sg_offset;
! 10327:
! 10328: /* sg_list_phys points to entry 1, not 0 */
! 10329: sg_offset = ((uint8_t *)sg - (uint8_t *)scb->sg_list)
! 10330: - ahd_sg_size(ahd);
! 10331:
! 10332: return (scb->sg_list_busaddr + sg_offset);
! 10333: }
! 10334:
! 10335: void
! 10336: ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op)
! 10337: {
! 10338: ahd_dmamap_sync(ahd, ahd->parent_dmat, scb->hscb_map->dmamap,
! 10339: /*offset*/(uint8_t*)scb->hscb - scb->hscb_map->vaddr,
! 10340: /*len*/sizeof(*scb->hscb), op);
! 10341: }
! 10342:
! 10343: void
! 10344: ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op)
! 10345: {
! 10346: if (scb->sg_count == 0)
! 10347: return;
! 10348:
! 10349: ahd_dmamap_sync(ahd, ahd->parent_dmat,
! 10350: scb->sense_map->dmamap,
! 10351: /*offset*/scb->sg_list_busaddr - ahd_sg_size(ahd),
! 10352: /*len*/ahd_sg_size(ahd) * scb->sg_count, op);
! 10353: }
! 10354:
! 10355: void
! 10356: ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op)
! 10357: {
! 10358: ahd_dmamap_sync(ahd, ahd->parent_dmat,
! 10359: scb->sense_map->dmamap,
! 10360: /*offset*/scb->sense_busaddr,
! 10361: /*len*/AHD_SENSE_BUFSIZE, op);
! 10362: }
! 10363:
! 10364: uint32_t
! 10365: ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index)
! 10366: {
! 10367: return (((uint8_t *)&ahd->targetcmds[index])
! 10368: - (uint8_t *)ahd->qoutfifo);
! 10369: }
! 10370:
! 10371: void
! 10372: ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb)
! 10373: {
! 10374: uint32_t sgptr;
! 10375:
! 10376: sgptr = aic_le32toh(scb->hscb->sgptr);
! 10377: if ((sgptr & SG_STATUS_VALID) != 0)
! 10378: ahd_handle_scb_status(ahd, scb);
! 10379: else
! 10380: ahd_done(ahd, scb);
! 10381: }
! 10382:
! 10383: /*
! 10384: * Determine whether the sequencer reported a residual
! 10385: * for this SCB/transaction.
! 10386: */
! 10387: void
! 10388: ahd_update_residual(struct ahd_softc *ahd, struct scb *scb)
! 10389: {
! 10390: uint32_t sgptr;
! 10391:
! 10392: sgptr = aic_le32toh(scb->hscb->sgptr);
! 10393: if ((sgptr & SG_STATUS_VALID) != 0)
! 10394: ahd_calc_residual(ahd, scb);
! 10395: }
! 10396:
! 10397: /*
! 10398: * Return pointers to the transfer negotiation information
! 10399: * for the specified our_id/remote_id pair.
! 10400: */
! 10401: struct ahd_initiator_tinfo *
! 10402: ahd_fetch_transinfo(struct ahd_softc *ahd, char channel, u_int our_id,
! 10403: u_int remote_id, struct ahd_tmode_tstate **tstate)
! 10404: {
! 10405: /*
! 10406: * Transfer data structures are stored from the perspective
! 10407: * of the target role. Since the parameters for a connection
! 10408: * in the initiator role to a given target are the same as
! 10409: * when the roles are reversed, we pretend we are the target.
! 10410: */
! 10411: if (channel == 'B')
! 10412: our_id += 8;
! 10413: *tstate = ahd->enabled_targets[our_id];
! 10414: return (&(*tstate)->transinfo[remote_id]);
! 10415: }
! 10416:
! 10417: #define AHD_COPY_COL_IDX(dst, src) \
! 10418: do { \
! 10419: dst->hscb->scsiid = src->hscb->scsiid; \
! 10420: dst->hscb->lun = src->hscb->lun; \
! 10421: } while (0)
! 10422:
! 10423: uint16_t
! 10424: ahd_inw(struct ahd_softc *ahd, u_int port)
! 10425: {
! 10426: /*
! 10427: * Read high byte first as some registers increment
! 10428: * or have other side effects when the low byte is
! 10429: * read.
! 10430: */
! 10431: return ((ahd_inb(ahd, port+1) << 8) | ahd_inb(ahd, port));
! 10432: }
! 10433:
! 10434: void
! 10435: ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)
! 10436: {
! 10437: /*
! 10438: * Write low byte first to accomodate registers
! 10439: * such as PRGMCNT where the order maters.
! 10440: */
! 10441: ahd_outb(ahd, port, value & 0xFF);
! 10442: ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
! 10443: }
! 10444:
! 10445: uint32_t
! 10446: ahd_inl(struct ahd_softc *ahd, u_int port)
! 10447: {
! 10448: return ((ahd_inb(ahd, port))
! 10449: | (ahd_inb(ahd, port+1) << 8)
! 10450: | (ahd_inb(ahd, port+2) << 16)
! 10451: | (ahd_inb(ahd, port+3) << 24));
! 10452: }
! 10453:
! 10454: void
! 10455: ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value)
! 10456: {
! 10457: ahd_outb(ahd, port, (value) & 0xFF);
! 10458: ahd_outb(ahd, port+1, ((value) >> 8) & 0xFF);
! 10459: ahd_outb(ahd, port+2, ((value) >> 16) & 0xFF);
! 10460: ahd_outb(ahd, port+3, ((value) >> 24) & 0xFF);
! 10461: }
! 10462:
! 10463: uint64_t
! 10464: ahd_inq(struct ahd_softc *ahd, u_int port)
! 10465: {
! 10466: return ((ahd_inb(ahd, port))
! 10467: | (ahd_inb(ahd, port+1) << 8)
! 10468: | (ahd_inb(ahd, port+2) << 16)
! 10469: | (ahd_inb(ahd, port+3) << 24)
! 10470: | (((uint64_t)ahd_inb(ahd, port+4)) << 32)
! 10471: | (((uint64_t)ahd_inb(ahd, port+5)) << 40)
! 10472: | (((uint64_t)ahd_inb(ahd, port+6)) << 48)
! 10473: | (((uint64_t)ahd_inb(ahd, port+7)) << 56));
! 10474: }
! 10475:
! 10476: void
! 10477: ahd_outq(struct ahd_softc *ahd, u_int port, uint64_t value)
! 10478: {
! 10479: ahd_outb(ahd, port, value & 0xFF);
! 10480: ahd_outb(ahd, port+1, (value >> 8) & 0xFF);
! 10481: ahd_outb(ahd, port+2, (value >> 16) & 0xFF);
! 10482: ahd_outb(ahd, port+3, (value >> 24) & 0xFF);
! 10483: ahd_outb(ahd, port+4, (value >> 32) & 0xFF);
! 10484: ahd_outb(ahd, port+5, (value >> 40) & 0xFF);
! 10485: ahd_outb(ahd, port+6, (value >> 48) & 0xFF);
! 10486: ahd_outb(ahd, port+7, (value >> 56) & 0xFF);
! 10487: }
! 10488:
! 10489: u_int
! 10490: ahd_get_scbptr(struct ahd_softc *ahd)
! 10491: {
! 10492: AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
! 10493: ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
! 10494: return (ahd_inb(ahd, SCBPTR) | (ahd_inb(ahd, SCBPTR + 1) << 8));
! 10495: }
! 10496:
! 10497: void
! 10498: ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr)
! 10499: {
! 10500: AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),
! 10501: ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));
! 10502: ahd_outb(ahd, SCBPTR, scbptr & 0xFF);
! 10503: ahd_outb(ahd, SCBPTR+1, (scbptr >> 8) & 0xFF);
! 10504: }
! 10505:
! 10506: u_int
! 10507: ahd_get_hnscb_qoff(struct ahd_softc *ahd)
! 10508: {
! 10509: return (ahd_inw_atomic(ahd, HNSCB_QOFF));
! 10510: }
! 10511:
! 10512: void
! 10513: ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value)
! 10514: {
! 10515: ahd_outw_atomic(ahd, HNSCB_QOFF, value);
! 10516: }
! 10517:
! 10518: u_int
! 10519: ahd_get_hescb_qoff(struct ahd_softc *ahd)
! 10520: {
! 10521: return (ahd_inb(ahd, HESCB_QOFF));
! 10522: }
! 10523:
! 10524: void
! 10525: ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value)
! 10526: {
! 10527: ahd_outb(ahd, HESCB_QOFF, value);
! 10528: }
! 10529:
! 10530: u_int
! 10531: ahd_get_snscb_qoff(struct ahd_softc *ahd)
! 10532: {
! 10533: u_int oldvalue;
! 10534:
! 10535: AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
! 10536: oldvalue = ahd_inw(ahd, SNSCB_QOFF);
! 10537: ahd_outw(ahd, SNSCB_QOFF, oldvalue);
! 10538: return (oldvalue);
! 10539: }
! 10540:
! 10541: void
! 10542: ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value)
! 10543: {
! 10544: AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
! 10545: ahd_outw(ahd, SNSCB_QOFF, value);
! 10546: }
! 10547:
! 10548: u_int
! 10549: ahd_get_sescb_qoff(struct ahd_softc *ahd)
! 10550: {
! 10551: AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
! 10552: return (ahd_inb(ahd, SESCB_QOFF));
! 10553: }
! 10554:
! 10555: void
! 10556: ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value)
! 10557: {
! 10558: AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
! 10559: ahd_outb(ahd, SESCB_QOFF, value);
! 10560: }
! 10561:
! 10562: u_int
! 10563: ahd_get_sdscb_qoff(struct ahd_softc *ahd)
! 10564: {
! 10565: AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
! 10566: return (ahd_inb(ahd, SDSCB_QOFF) | (ahd_inb(ahd, SDSCB_QOFF + 1) << 8));
! 10567: }
! 10568:
! 10569: void
! 10570: ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value)
! 10571: {
! 10572: AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);
! 10573: ahd_outb(ahd, SDSCB_QOFF, value & 0xFF);
! 10574: ahd_outb(ahd, SDSCB_QOFF+1, (value >> 8) & 0xFF);
! 10575: }
! 10576:
! 10577: u_int
! 10578: ahd_inb_scbram(struct ahd_softc *ahd, u_int offset)
! 10579: {
! 10580: u_int value;
! 10581:
! 10582: /*
! 10583: * Workaround PCI-X Rev A. hardware bug.
! 10584: * After a host read of SCB memory, the chip
! 10585: * may become confused into thinking prefetch
! 10586: * was required. This starts the discard timer
! 10587: * running and can cause an unexpected discard
! 10588: * timer interrupt. The work around is to read
! 10589: * a normal register prior to the exhaustion of
! 10590: * the discard timer. The mode pointer register
! 10591: * has no side effects and so serves well for
! 10592: * this purpose.
! 10593: *
! 10594: * Razor #528
! 10595: */
! 10596: value = ahd_inb(ahd, offset);
! 10597: if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0)
! 10598: ahd_inb(ahd, MODE_PTR);
! 10599: return (value);
! 10600: }
! 10601:
! 10602: u_int
! 10603: ahd_inw_scbram(struct ahd_softc *ahd, u_int offset)
! 10604: {
! 10605: return (ahd_inb_scbram(ahd, offset)
! 10606: | (ahd_inb_scbram(ahd, offset+1) << 8));
! 10607: }
! 10608:
! 10609: uint32_t
! 10610: ahd_inl_scbram(struct ahd_softc *ahd, u_int offset)
! 10611: {
! 10612: return (ahd_inw_scbram(ahd, offset)
! 10613: | (ahd_inw_scbram(ahd, offset+2) << 16));
! 10614: }
! 10615:
! 10616: uint64_t
! 10617: ahd_inq_scbram(struct ahd_softc *ahd, u_int offset)
! 10618: {
! 10619: return (ahd_inl_scbram(ahd, offset)
! 10620: | ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32);
! 10621: }
! 10622:
! 10623: struct scb *
! 10624: ahd_lookup_scb(struct ahd_softc *ahd, u_int tag)
! 10625: {
! 10626: struct scb* scb;
! 10627:
! 10628: if (tag >= AHD_SCB_MAX)
! 10629: return (NULL);
! 10630: scb = ahd->scb_data.scbindex[tag];
! 10631: if (scb != NULL)
! 10632: ahd_sync_scb(ahd, scb,
! 10633: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
! 10634: return (scb);
! 10635: }
! 10636:
! 10637: void
! 10638: ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)
! 10639: {
! 10640: struct hardware_scb *q_hscb;
! 10641: struct map_node *q_hscb_map;
! 10642: uint32_t saved_hscb_busaddr;
! 10643:
! 10644: /*
! 10645: * Our queuing method is a bit tricky. The card
! 10646: * knows in advance which HSCB (by address) to download,
! 10647: * and we can't disappoint it. To achieve this, the next
! 10648: * HSCB to download is saved off in ahd->next_queued_hscb.
! 10649: * When we are called to queue "an arbitrary scb",
! 10650: * we copy the contents of the incoming HSCB to the one
! 10651: * the sequencer knows about, swap HSCB pointers and
! 10652: * finally assign the SCB to the tag indexed location
! 10653: * in the scb_array. This makes sure that we can still
! 10654: * locate the correct SCB by SCB_TAG.
! 10655: */
! 10656: q_hscb = ahd->next_queued_hscb;
! 10657: q_hscb_map = ahd->next_queued_hscb_map;
! 10658: saved_hscb_busaddr = q_hscb->hscb_busaddr;
! 10659: memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
! 10660: q_hscb->hscb_busaddr = saved_hscb_busaddr;
! 10661: q_hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;
! 10662:
! 10663: /* Now swap HSCB pointers. */
! 10664: ahd->next_queued_hscb = scb->hscb;
! 10665: ahd->next_queued_hscb_map = scb->hscb_map;
! 10666: scb->hscb = q_hscb;
! 10667: scb->hscb_map = q_hscb_map;
! 10668:
! 10669: /* Now define the mapping from tag to SCB in the scbindex */
! 10670: ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
! 10671: }
! 10672:
! 10673: /*
! 10674: * Tell the sequencer about a new transaction to execute.
! 10675: */
! 10676: void
! 10677: ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb)
! 10678: {
! 10679: ahd_swap_with_next_hscb(ahd, scb);
! 10680:
! 10681: if (SCBID_IS_NULL(SCB_GET_TAG(scb)))
! 10682: panic("Attempt to queue invalid SCB tag %x",
! 10683: SCB_GET_TAG(scb));
! 10684:
! 10685: /*
! 10686: * Keep a history of SCBs we've downloaded in the qinfifo.
! 10687: */
! 10688: ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb);
! 10689: ahd->qinfifonext++;
! 10690:
! 10691: if (scb->sg_count != 0)
! 10692: ahd_setup_data_scb(ahd, scb);
! 10693: else
! 10694: ahd_setup_noxfer_scb(ahd, scb);
! 10695: ahd_setup_scb_common(ahd, scb);
! 10696:
! 10697: /*
! 10698: * Make sure our data is consistent from the
! 10699: * perspective of the adapter.
! 10700: */
! 10701: ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
! 10702:
! 10703: #ifdef AHD_DEBUG
! 10704: if ((ahd_debug & AHD_SHOW_QUEUE) != 0) {
! 10705: uint64_t host_dataptr;
! 10706:
! 10707: host_dataptr = aic_le64toh(scb->hscb->dataptr);
! 10708: printf("%s: Queueing SCB %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n",
! 10709: ahd_name(ahd),
! 10710: SCB_GET_TAG(scb), scb->hscb->scsiid,
! 10711: aic_le32toh(scb->hscb->hscb_busaddr),
! 10712: (u_int)((host_dataptr >> 32) & 0xFFFFFFFF),
! 10713: (u_int)(host_dataptr & 0xFFFFFFFF),
! 10714: aic_le32toh(scb->hscb->datacnt));
! 10715: }
! 10716: #endif
! 10717: /* Tell the adapter about the newly queued SCB */
! 10718: ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);
! 10719: }
! 10720:
! 10721: uint8_t *
! 10722: ahd_get_sense_buf(struct ahd_softc *ahd, struct scb *scb)
! 10723: {
! 10724: return (scb->sense_data);
! 10725: }
! 10726:
! 10727: uint32_t
! 10728: ahd_get_sense_bufaddr(struct ahd_softc *ahd, struct scb *scb)
! 10729: {
! 10730: return (scb->sense_busaddr);
! 10731: }
! 10732:
! 10733: void
! 10734: ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)
! 10735: {
! 10736: ahd_dmamap_sync(ahd, ahd->parent_dmat, ahd->shared_data_map.dmamap,
! 10737: /*offset*/0,
! 10738: /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op);
! 10739: }
! 10740:
! 10741: void
! 10742: ahd_sync_tqinfifo(struct ahd_softc *ahd, int op)
! 10743: {
! 10744: #ifdef AHD_TARGET_MODE
! 10745: if ((ahd->flags & AHD_TARGETROLE) != 0) {
! 10746: ahd_dmamap_sync(ahd, ahd->parent_dmat,
! 10747: ahd->shared_data_map.dmamap,
! 10748: ahd_targetcmd_offset(ahd, 0),
! 10749: sizeof(struct target_cmd) * AHD_TMODE_CMDS,
! 10750: op);
! 10751: }
! 10752: #endif
! 10753: }
! 10754:
! 10755: /*
! 10756: * See if the firmware has posted any completed commands
! 10757: * into our in-core command complete fifos.
! 10758: */
! 10759: #define AHD_RUN_QOUTFIFO 0x1
! 10760: #define AHD_RUN_TQINFIFO 0x2
! 10761: u_int
! 10762: ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)
! 10763: {
! 10764: u_int retval;
! 10765:
! 10766: retval = 0;
! 10767: ahd_dmamap_sync(ahd, ahd->parent_dmat, ahd->shared_data_map.dmamap,
! 10768: /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo),
! 10769: /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD);
! 10770: if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag
! 10771: == ahd->qoutfifonext_valid_tag)
! 10772: retval |= AHD_RUN_QOUTFIFO;
! 10773: #ifdef AHD_TARGET_MODE
! 10774: if ((ahd->flags & AHD_TARGETROLE) != 0
! 10775: && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {
! 10776: ahd_dmamap_sync(ahd, ahd->parent_dmat
! 10777: ahd->shared_data_map.dmamap,
! 10778: ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),
! 10779: /*len*/sizeof(struct target_cmd),
! 10780: BUS_DMASYNC_POSTREAD);
! 10781: if (ahd->targetcmds[ahd->tqinfifonext].cmd_valid != 0)
! 10782: retval |= AHD_RUN_TQINFIFO;
! 10783: }
! 10784: #endif
! 10785: return (retval);
! 10786: }
! 10787:
! 10788: /*
! 10789: * Catch an interrupt from the adapter
! 10790: */
! 10791: int
! 10792: ahd_intr(struct ahd_softc *ahd)
! 10793: {
! 10794: u_int intstat;
! 10795:
! 10796: if ((ahd->pause & INTEN) == 0) {
! 10797: /*
! 10798: * Our interrupt is not enabled on the chip
! 10799: * and may be disabled for re-entrancy reasons,
! 10800: * so just return. This is likely just a shared
! 10801: * interrupt.
! 10802: */
! 10803: return (0);
! 10804: }
! 10805:
! 10806: /*
! 10807: * Instead of directly reading the interrupt status register,
! 10808: * infer the cause of the interrupt by checking our in-core
! 10809: * completion queues. This avoids a costly PCI bus read in
! 10810: * most cases.
! 10811: */
! 10812: if ((ahd->flags & AHD_ALL_INTERRUPTS) == 0
! 10813: && (ahd_check_cmdcmpltqueues(ahd) != 0))
! 10814: intstat = CMDCMPLT;
! 10815: else
! 10816: intstat = ahd_inb(ahd, INTSTAT);
! 10817:
! 10818: if ((intstat & INT_PEND) == 0)
! 10819: return (0);
! 10820:
! 10821: if (intstat & CMDCMPLT) {
! 10822: ahd_outb(ahd, CLRINT, CLRCMDINT);
! 10823:
! 10824: /*
! 10825: * Ensure that the chip sees that we've cleared
! 10826: * this interrupt before we walk the output fifo.
! 10827: * Otherwise, we may, due to posted bus writes,
! 10828: * clear the interrupt after we finish the scan,
! 10829: * and after the sequencer has added new entries
! 10830: * and asserted the interrupt again.
! 10831: */
! 10832: if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {
! 10833: if (ahd_is_paused(ahd)) {
! 10834: /*
! 10835: * Potentially lost SEQINT.
! 10836: * If SEQINTCODE is non-zero,
! 10837: * simulate the SEQINT.
! 10838: */
! 10839: if (ahd_inb(ahd, SEQINTCODE) != NO_SEQINT)
! 10840: intstat |= SEQINT;
! 10841: }
! 10842: } else {
! 10843: ahd_flush_device_writes(ahd);
! 10844: }
! 10845: ahd_run_qoutfifo(ahd);
! 10846: ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]++;
! 10847: ahd->cmdcmplt_total++;
! 10848: #ifdef AHD_TARGET_MODE
! 10849: if ((ahd->flags & AHD_TARGETROLE) != 0)
! 10850: ahd_run_tqinfifo(ahd, /*paused*/FALSE);
! 10851: #endif
! 10852: }
! 10853:
! 10854: /*
! 10855: * Handle statuses that may invalidate our cached
! 10856: * copy of INTSTAT separately.
! 10857: */
! 10858: if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) {
! 10859: /* Hot eject. Do nothing */
! 10860: } else if (intstat & HWERRINT) {
! 10861: ahd_handle_hwerrint(ahd);
! 10862: } else if ((intstat & (PCIINT|SPLTINT)) != 0) {
! 10863: ahd->bus_intr(ahd);
! 10864: } else {
! 10865:
! 10866: if ((intstat & SEQINT) != 0)
! 10867: ahd_handle_seqint(ahd, intstat);
! 10868:
! 10869: if ((intstat & SCSIINT) != 0)
! 10870: ahd_handle_scsiint(ahd, intstat);
! 10871: }
! 10872: return (1);
! 10873: }
! 10874:
! 10875: void
! 10876: ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl)
! 10877: {
! 10878: ahd_busy_tcl(ahd, tcl, SCB_LIST_NULL);
! 10879: }
CVSweb