10725 lines · c
1/*2 * Core routines and tables shareable across OS platforms.3 *4 * Copyright (c) 1994-2002 Justin T. Gibbs.5 * Copyright (c) 2000-2003 Adaptec Inc.6 * All rights reserved.7 *8 * Redistribution and use in source and binary forms, with or without9 * modification, are permitted provided that the following conditions10 * are met:11 * 1. Redistributions of source code must retain the above copyright12 * notice, this list of conditions, and the following disclaimer,13 * without modification.14 * 2. Redistributions in binary form must reproduce at minimum a disclaimer15 * substantially similar to the "NO WARRANTY" disclaimer below16 * ("Disclaimer") and any redistribution must be conditioned upon17 * including a substantially similar Disclaimer requirement for further18 * binary redistribution.19 * 3. Neither the names of the above-listed copyright holders nor the names20 * of any contributors may be used to endorse or promote products derived21 * from this software without specific prior written permission.22 *23 * Alternatively, this software may be distributed under the terms of the24 * GNU General Public License ("GPL") version 2 as published by the Free25 * Software Foundation.26 *27 * NO WARRANTY28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT32 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING37 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE38 * POSSIBILITY OF SUCH DAMAGES.39 *40 * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#250 $41 */42 43#include "aic79xx_osm.h"44#include "aic79xx_inline.h"45#include "aicasm/aicasm_insformat.h"46 47/***************************** Lookup Tables **********************************/48static const char *const ahd_chip_names[] =49{50 "NONE",51 "aic7901",52 "aic7902",53 "aic7901A"54};55 56/*57 * Hardware error codes.58 */59struct ahd_hard_error_entry {60 uint8_t errno;61 const char *errmesg;62};63 64static const struct ahd_hard_error_entry ahd_hard_errors[] = {65 { DSCTMOUT, "Discard Timer has timed out" },66 { ILLOPCODE, "Illegal Opcode in sequencer program" },67 { SQPARERR, "Sequencer Parity Error" },68 { DPARERR, "Data-path Parity Error" },69 { MPARERR, "Scratch or SCB Memory Parity Error" },70 { CIOPARERR, "CIOBUS Parity Error" },71};72static const u_int num_errors = ARRAY_SIZE(ahd_hard_errors);73 74static const struct ahd_phase_table_entry ahd_phase_table[] =75{76 { P_DATAOUT, NOP, "in Data-out phase" },77 { P_DATAIN, INITIATOR_ERROR, "in Data-in phase" },78 { P_DATAOUT_DT, NOP, "in DT Data-out phase" },79 { P_DATAIN_DT, INITIATOR_ERROR, "in DT Data-in phase" },80 { P_COMMAND, NOP, "in Command phase" },81 { P_MESGOUT, NOP, "in Message-out phase" },82 { P_STATUS, INITIATOR_ERROR, "in Status phase" },83 { P_MESGIN, MSG_PARITY_ERROR, "in Message-in phase" },84 { P_BUSFREE, NOP, "while idle" },85 { 0, NOP, "in unknown phase" }86};87 88/*89 * In most cases we only wish to itterate over real phases, so90 * exclude the last element from the count.91 */92static const u_int num_phases = ARRAY_SIZE(ahd_phase_table) - 1;93 94/* Our Sequencer Program */95#include "aic79xx_seq.h"96 97/**************************** Function Declarations ***************************/98static void ahd_handle_transmission_error(struct ahd_softc *ahd);99static void ahd_handle_lqiphase_error(struct ahd_softc *ahd,100 u_int lqistat1);101static int ahd_handle_pkt_busfree(struct ahd_softc *ahd,102 u_int busfreetime);103static int ahd_handle_nonpkt_busfree(struct ahd_softc *ahd);104static void ahd_handle_proto_violation(struct ahd_softc *ahd);105static void ahd_force_renegotiation(struct ahd_softc *ahd,106 struct ahd_devinfo *devinfo);107 108static struct ahd_tmode_tstate*109 ahd_alloc_tstate(struct ahd_softc *ahd,110 u_int scsi_id, char channel);111#ifdef AHD_TARGET_MODE112static void ahd_free_tstate(struct ahd_softc *ahd,113 u_int scsi_id, char channel, int force);114#endif115static void ahd_devlimited_syncrate(struct ahd_softc *ahd,116 struct ahd_initiator_tinfo *,117 u_int *period,118 u_int *ppr_options,119 role_t role);120static void ahd_update_neg_table(struct ahd_softc *ahd,121 struct ahd_devinfo *devinfo,122 struct ahd_transinfo *tinfo);123static void ahd_update_pending_scbs(struct ahd_softc *ahd);124static void ahd_fetch_devinfo(struct ahd_softc *ahd,125 struct ahd_devinfo *devinfo);126static void ahd_scb_devinfo(struct ahd_softc *ahd,127 struct ahd_devinfo *devinfo,128 struct scb *scb);129static void ahd_setup_initiator_msgout(struct ahd_softc *ahd,130 struct ahd_devinfo *devinfo,131 struct scb *scb);132static void ahd_build_transfer_msg(struct ahd_softc *ahd,133 struct ahd_devinfo *devinfo);134static void ahd_construct_sdtr(struct ahd_softc *ahd,135 struct ahd_devinfo *devinfo,136 u_int period, u_int offset);137static void ahd_construct_wdtr(struct ahd_softc *ahd,138 struct ahd_devinfo *devinfo,139 u_int bus_width);140static void ahd_construct_ppr(struct ahd_softc *ahd,141 struct ahd_devinfo *devinfo,142 u_int period, u_int offset,143 u_int bus_width, u_int ppr_options);144static void ahd_clear_msg_state(struct ahd_softc *ahd);145static void ahd_handle_message_phase(struct ahd_softc *ahd);146typedef enum {147 AHDMSG_1B,148 AHDMSG_2B,149 AHDMSG_EXT150} ahd_msgtype;151static int ahd_sent_msg(struct ahd_softc *ahd, ahd_msgtype type,152 u_int msgval, int full);153static int ahd_parse_msg(struct ahd_softc *ahd,154 struct ahd_devinfo *devinfo);155static int ahd_handle_msg_reject(struct ahd_softc *ahd,156 struct ahd_devinfo *devinfo);157static void ahd_handle_ign_wide_residue(struct ahd_softc *ahd,158 struct ahd_devinfo *devinfo);159static void ahd_reinitialize_dataptrs(struct ahd_softc *ahd);160static void ahd_handle_devreset(struct ahd_softc *ahd,161 struct ahd_devinfo *devinfo,162 u_int lun, cam_status status,163 char *message, int verbose_level);164#ifdef AHD_TARGET_MODE165static void ahd_setup_target_msgin(struct ahd_softc *ahd,166 struct ahd_devinfo *devinfo,167 struct scb *scb);168#endif169 170static u_int ahd_sglist_size(struct ahd_softc *ahd);171static u_int ahd_sglist_allocsize(struct ahd_softc *ahd);172static bus_dmamap_callback_t173 ahd_dmamap_cb;174static void ahd_initialize_hscbs(struct ahd_softc *ahd);175static int ahd_init_scbdata(struct ahd_softc *ahd);176static void ahd_fini_scbdata(struct ahd_softc *ahd);177static void ahd_setup_iocell_workaround(struct ahd_softc *ahd);178static void ahd_iocell_first_selection(struct ahd_softc *ahd);179static void ahd_add_col_list(struct ahd_softc *ahd,180 struct scb *scb, u_int col_idx);181static void ahd_rem_col_list(struct ahd_softc *ahd,182 struct scb *scb);183static void ahd_chip_init(struct ahd_softc *ahd);184static void ahd_qinfifo_requeue(struct ahd_softc *ahd,185 struct scb *prev_scb,186 struct scb *scb);187static int ahd_qinfifo_count(struct ahd_softc *ahd);188static int ahd_search_scb_list(struct ahd_softc *ahd, int target,189 char channel, int lun, u_int tag,190 role_t role, uint32_t status,191 ahd_search_action action,192 u_int *list_head, u_int *list_tail,193 u_int tid);194static void ahd_stitch_tid_list(struct ahd_softc *ahd,195 u_int tid_prev, u_int tid_cur,196 u_int tid_next);197static void ahd_add_scb_to_free_list(struct ahd_softc *ahd,198 u_int scbid);199static u_int ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid,200 u_int prev, u_int next, u_int tid);201static void ahd_reset_current_bus(struct ahd_softc *ahd);202static void ahd_stat_timer(struct timer_list *t);203#ifdef AHD_DUMP_SEQ204static void ahd_dumpseq(struct ahd_softc *ahd);205#endif206static void ahd_loadseq(struct ahd_softc *ahd);207static int ahd_check_patch(struct ahd_softc *ahd,208 const struct patch **start_patch,209 u_int start_instr, u_int *skip_addr);210static u_int ahd_resolve_seqaddr(struct ahd_softc *ahd,211 u_int address);212static void ahd_download_instr(struct ahd_softc *ahd,213 u_int instrptr, uint8_t *dconsts);214static int ahd_probe_stack_size(struct ahd_softc *ahd);215static int ahd_scb_active_in_fifo(struct ahd_softc *ahd,216 struct scb *scb);217static void ahd_run_data_fifo(struct ahd_softc *ahd,218 struct scb *scb);219 220#ifdef AHD_TARGET_MODE221static void ahd_queue_lstate_event(struct ahd_softc *ahd,222 struct ahd_tmode_lstate *lstate,223 u_int initiator_id,224 u_int event_type,225 u_int event_arg);226static void ahd_update_scsiid(struct ahd_softc *ahd,227 u_int targid_mask);228static int ahd_handle_target_cmd(struct ahd_softc *ahd,229 struct target_cmd *cmd);230#endif231 232static int ahd_abort_scbs(struct ahd_softc *ahd, int target,233 char channel, int lun, u_int tag,234 role_t role, uint32_t status);235static void ahd_alloc_scbs(struct ahd_softc *ahd);236static void ahd_busy_tcl(struct ahd_softc *ahd, u_int tcl,237 u_int scbid);238static void ahd_calc_residual(struct ahd_softc *ahd,239 struct scb *scb);240static void ahd_clear_critical_section(struct ahd_softc *ahd);241static void ahd_clear_intstat(struct ahd_softc *ahd);242static void ahd_enable_coalescing(struct ahd_softc *ahd,243 int enable);244static u_int ahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl);245static void ahd_freeze_devq(struct ahd_softc *ahd,246 struct scb *scb);247static void ahd_handle_scb_status(struct ahd_softc *ahd,248 struct scb *scb);249static const struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase);250static void ahd_shutdown(void *arg);251static void ahd_update_coalescing_values(struct ahd_softc *ahd,252 u_int timer,253 u_int maxcmds,254 u_int mincmds);255static int ahd_verify_vpd_cksum(struct vpd_config *vpd);256static int ahd_wait_seeprom(struct ahd_softc *ahd);257static int ahd_match_scb(struct ahd_softc *ahd, struct scb *scb,258 int target, char channel, int lun,259 u_int tag, role_t role);260 261static void ahd_reset_cmds_pending(struct ahd_softc *ahd);262 263/*************************** Interrupt Services *******************************/264static void ahd_run_qoutfifo(struct ahd_softc *ahd);265#ifdef AHD_TARGET_MODE266static void ahd_run_tqinfifo(struct ahd_softc *ahd, int paused);267#endif268static void ahd_handle_hwerrint(struct ahd_softc *ahd);269static void ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat);270static void ahd_handle_scsiint(struct ahd_softc *ahd,271 u_int intstat);272 273/************************ Sequencer Execution Control *************************/274void275ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)276{277 if (ahd->src_mode == src && ahd->dst_mode == dst)278 return;279#ifdef AHD_DEBUG280 if (ahd->src_mode == AHD_MODE_UNKNOWN281 || ahd->dst_mode == AHD_MODE_UNKNOWN)282 panic("Setting mode prior to saving it.\n");283 if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)284 printk("%s: Setting mode 0x%x\n", ahd_name(ahd),285 ahd_build_mode_state(ahd, src, dst));286#endif287 ahd_outb(ahd, MODE_PTR, ahd_build_mode_state(ahd, src, dst));288 ahd->src_mode = src;289 ahd->dst_mode = dst;290}291 292static void293ahd_update_modes(struct ahd_softc *ahd)294{295 ahd_mode_state mode_ptr;296 ahd_mode src;297 ahd_mode dst;298 299 mode_ptr = ahd_inb(ahd, MODE_PTR);300#ifdef AHD_DEBUG301 if ((ahd_debug & AHD_SHOW_MODEPTR) != 0)302 printk("Reading mode 0x%x\n", mode_ptr);303#endif304 ahd_extract_mode_state(ahd, mode_ptr, &src, &dst);305 ahd_known_modes(ahd, src, dst);306}307 308static void309ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode,310 ahd_mode dstmode, const char *file, int line)311{312#ifdef AHD_DEBUG313 if ((srcmode & AHD_MK_MSK(ahd->src_mode)) == 0314 || (dstmode & AHD_MK_MSK(ahd->dst_mode)) == 0) {315 panic("%s:%s:%d: Mode assertion failed.\n",316 ahd_name(ahd), file, line);317 }318#endif319}320 321#define AHD_ASSERT_MODES(ahd, source, dest) \322 ahd_assert_modes(ahd, source, dest, __FILE__, __LINE__);323 324ahd_mode_state325ahd_save_modes(struct ahd_softc *ahd)326{327 if (ahd->src_mode == AHD_MODE_UNKNOWN328 || ahd->dst_mode == AHD_MODE_UNKNOWN)329 ahd_update_modes(ahd);330 331 return (ahd_build_mode_state(ahd, ahd->src_mode, ahd->dst_mode));332}333 334void335ahd_restore_modes(struct ahd_softc *ahd, ahd_mode_state state)336{337 ahd_mode src;338 ahd_mode dst;339 340 ahd_extract_mode_state(ahd, state, &src, &dst);341 ahd_set_modes(ahd, src, dst);342}343 344/*345 * Determine whether the sequencer has halted code execution.346 * Returns non-zero status if the sequencer is stopped.347 */348int349ahd_is_paused(struct ahd_softc *ahd)350{351 return ((ahd_inb(ahd, HCNTRL) & PAUSE) != 0);352}353 354/*355 * Request that the sequencer stop and wait, indefinitely, for it356 * to stop. The sequencer will only acknowledge that it is paused357 * once it has reached an instruction boundary and PAUSEDIS is358 * cleared in the SEQCTL register. The sequencer may use PAUSEDIS359 * for critical sections.360 */361void362ahd_pause(struct ahd_softc *ahd)363{364 ahd_outb(ahd, HCNTRL, ahd->pause);365 366 /*367 * Since the sequencer can disable pausing in a critical section, we368 * must loop until it actually stops.369 */370 while (ahd_is_paused(ahd) == 0)371 ;372}373 374/*375 * Allow the sequencer to continue program execution.376 * We check here to ensure that no additional interrupt377 * sources that would cause the sequencer to halt have been378 * asserted. If, for example, a SCSI bus reset is detected379 * while we are fielding a different, pausing, interrupt type,380 * we don't want to release the sequencer before going back381 * into our interrupt handler and dealing with this new382 * condition.383 */384void385ahd_unpause(struct ahd_softc *ahd)386{387 /*388 * Automatically restore our modes to those saved389 * prior to the first change of the mode.390 */391 if (ahd->saved_src_mode != AHD_MODE_UNKNOWN392 && ahd->saved_dst_mode != AHD_MODE_UNKNOWN) {393 if ((ahd->flags & AHD_UPDATE_PEND_CMDS) != 0)394 ahd_reset_cmds_pending(ahd);395 ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);396 }397 398 if ((ahd_inb(ahd, INTSTAT) & ~CMDCMPLT) == 0)399 ahd_outb(ahd, HCNTRL, ahd->unpause);400 401 ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN);402}403 404/*********************** Scatter Gather List Handling *************************/405void *406ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,407 void *sgptr, dma_addr_t addr, bus_size_t len, int last)408{409 scb->sg_count++;410 if (sizeof(dma_addr_t) > 4411 && (ahd->flags & AHD_64BIT_ADDRESSING) != 0) {412 struct ahd_dma64_seg *sg;413 414 sg = (struct ahd_dma64_seg *)sgptr;415 sg->addr = ahd_htole64(addr);416 sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0));417 return (sg + 1);418 } else {419 struct ahd_dma_seg *sg;420 421 sg = (struct ahd_dma_seg *)sgptr;422 sg->addr = ahd_htole32(addr & 0xFFFFFFFF);423 sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000)424 | (last ? AHD_DMA_LAST_SEG : 0));425 return (sg + 1);426 }427}428 429static void430ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb)431{432 /* XXX Handle target mode SCBs. */433 scb->crc_retry_count = 0;434 if ((scb->flags & SCB_PACKETIZED) != 0) {435 /* XXX what about ACA?? It is type 4, but TAG_TYPE == 0x3. */436 scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE;437 } else {438 if (ahd_get_transfer_length(scb) & 0x01)439 scb->hscb->task_attribute = SCB_XFERLEN_ODD;440 else441 scb->hscb->task_attribute = 0;442 }443 444 if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR445 || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0)446 scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr =447 ahd_htole32(scb->sense_busaddr);448}449 450static void451ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb)452{453 /*454 * Copy the first SG into the "current" data ponter area.455 */456 if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {457 struct ahd_dma64_seg *sg;458 459 sg = (struct ahd_dma64_seg *)scb->sg_list;460 scb->hscb->dataptr = sg->addr;461 scb->hscb->datacnt = sg->len;462 } else {463 struct ahd_dma_seg *sg;464 uint32_t *dataptr_words;465 466 sg = (struct ahd_dma_seg *)scb->sg_list;467 dataptr_words = (uint32_t*)&scb->hscb->dataptr;468 dataptr_words[0] = sg->addr;469 dataptr_words[1] = 0;470 if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) {471 uint64_t high_addr;472 473 high_addr = ahd_le32toh(sg->len) & 0x7F000000;474 scb->hscb->dataptr |= ahd_htole64(high_addr << 8);475 }476 scb->hscb->datacnt = sg->len;477 }478 /*479 * Note where to find the SG entries in bus space.480 * We also set the full residual flag which the481 * sequencer will clear as soon as a data transfer482 * occurs.483 */484 scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID);485}486 487static void488ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb)489{490 scb->hscb->sgptr = ahd_htole32(SG_LIST_NULL);491 scb->hscb->dataptr = 0;492 scb->hscb->datacnt = 0;493}494 495/************************** Memory mapping routines ***************************/496static void *497ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr)498{499 dma_addr_t sg_offset;500 501 /* sg_list_phys points to entry 1, not 0 */502 sg_offset = sg_busaddr - (scb->sg_list_busaddr - ahd_sg_size(ahd));503 return ((uint8_t *)scb->sg_list + sg_offset);504}505 506static uint32_t507ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg)508{509 dma_addr_t sg_offset;510 511 /* sg_list_phys points to entry 1, not 0 */512 sg_offset = ((uint8_t *)sg - (uint8_t *)scb->sg_list)513 - ahd_sg_size(ahd);514 515 return (scb->sg_list_busaddr + sg_offset);516}517 518static void519ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op)520{521 ahd_dmamap_sync(ahd, ahd->scb_data.hscb_dmat,522 scb->hscb_map->dmamap,523 /*offset*/(uint8_t*)scb->hscb - scb->hscb_map->vaddr,524 /*len*/sizeof(*scb->hscb), op);525}526 527void528ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op)529{530 if (scb->sg_count == 0)531 return;532 533 ahd_dmamap_sync(ahd, ahd->scb_data.sg_dmat,534 scb->sg_map->dmamap,535 /*offset*/scb->sg_list_busaddr - ahd_sg_size(ahd),536 /*len*/ahd_sg_size(ahd) * scb->sg_count, op);537}538 539static void540ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op)541{542 ahd_dmamap_sync(ahd, ahd->scb_data.sense_dmat,543 scb->sense_map->dmamap,544 /*offset*/scb->sense_busaddr,545 /*len*/AHD_SENSE_BUFSIZE, op);546}547 548#ifdef AHD_TARGET_MODE549static uint32_t550ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index)551{552 return (((uint8_t *)&ahd->targetcmds[index])553 - (uint8_t *)ahd->qoutfifo);554}555#endif556 557/*********************** Miscellaneous Support Functions ***********************/558/*559 * Return pointers to the transfer negotiation information560 * for the specified our_id/remote_id pair.561 */562struct ahd_initiator_tinfo *563ahd_fetch_transinfo(struct ahd_softc *ahd, char channel, u_int our_id,564 u_int remote_id, struct ahd_tmode_tstate **tstate)565{566 /*567 * Transfer data structures are stored from the perspective568 * of the target role. Since the parameters for a connection569 * in the initiator role to a given target are the same as570 * when the roles are reversed, we pretend we are the target.571 */572 if (channel == 'B')573 our_id += 8;574 *tstate = ahd->enabled_targets[our_id];575 return (&(*tstate)->transinfo[remote_id]);576}577 578uint16_t579ahd_inw(struct ahd_softc *ahd, u_int port)580{581 /*582 * Read high byte first as some registers increment583 * or have other side effects when the low byte is584 * read.585 */586 uint16_t r = ahd_inb(ahd, port+1) << 8;587 return r | ahd_inb(ahd, port);588}589 590void591ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)592{593 /*594 * Write low byte first to accommodate registers595 * such as PRGMCNT where the order maters.596 */597 ahd_outb(ahd, port, value & 0xFF);598 ahd_outb(ahd, port+1, (value >> 8) & 0xFF);599}600 601uint32_t602ahd_inl(struct ahd_softc *ahd, u_int port)603{604 return ((ahd_inb(ahd, port))605 | (ahd_inb(ahd, port+1) << 8)606 | (ahd_inb(ahd, port+2) << 16)607 | (ahd_inb(ahd, port+3) << 24));608}609 610void611ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value)612{613 ahd_outb(ahd, port, (value) & 0xFF);614 ahd_outb(ahd, port+1, ((value) >> 8) & 0xFF);615 ahd_outb(ahd, port+2, ((value) >> 16) & 0xFF);616 ahd_outb(ahd, port+3, ((value) >> 24) & 0xFF);617}618 619uint64_t620ahd_inq(struct ahd_softc *ahd, u_int port)621{622 return ((ahd_inb(ahd, port))623 | (ahd_inb(ahd, port+1) << 8)624 | (ahd_inb(ahd, port+2) << 16)625 | (ahd_inb(ahd, port+3) << 24)626 | (((uint64_t)ahd_inb(ahd, port+4)) << 32)627 | (((uint64_t)ahd_inb(ahd, port+5)) << 40)628 | (((uint64_t)ahd_inb(ahd, port+6)) << 48)629 | (((uint64_t)ahd_inb(ahd, port+7)) << 56));630}631 632void633ahd_outq(struct ahd_softc *ahd, u_int port, uint64_t value)634{635 ahd_outb(ahd, port, value & 0xFF);636 ahd_outb(ahd, port+1, (value >> 8) & 0xFF);637 ahd_outb(ahd, port+2, (value >> 16) & 0xFF);638 ahd_outb(ahd, port+3, (value >> 24) & 0xFF);639 ahd_outb(ahd, port+4, (value >> 32) & 0xFF);640 ahd_outb(ahd, port+5, (value >> 40) & 0xFF);641 ahd_outb(ahd, port+6, (value >> 48) & 0xFF);642 ahd_outb(ahd, port+7, (value >> 56) & 0xFF);643}644 645u_int646ahd_get_scbptr(struct ahd_softc *ahd)647{648 AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),649 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));650 return (ahd_inb(ahd, SCBPTR) | (ahd_inb(ahd, SCBPTR + 1) << 8));651}652 653void654ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr)655{656 AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),657 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));658 ahd_outb(ahd, SCBPTR, scbptr & 0xFF);659 ahd_outb(ahd, SCBPTR+1, (scbptr >> 8) & 0xFF);660}661 662#if 0 /* unused */663static u_int664ahd_get_hnscb_qoff(struct ahd_softc *ahd)665{666 return (ahd_inw_atomic(ahd, HNSCB_QOFF));667}668#endif669 670static void671ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value)672{673 ahd_outw_atomic(ahd, HNSCB_QOFF, value);674}675 676#if 0 /* unused */677static u_int678ahd_get_hescb_qoff(struct ahd_softc *ahd)679{680 return (ahd_inb(ahd, HESCB_QOFF));681}682#endif683 684static void685ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value)686{687 ahd_outb(ahd, HESCB_QOFF, value);688}689 690static u_int691ahd_get_snscb_qoff(struct ahd_softc *ahd)692{693 u_int oldvalue;694 695 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);696 oldvalue = ahd_inw(ahd, SNSCB_QOFF);697 ahd_outw(ahd, SNSCB_QOFF, oldvalue);698 return (oldvalue);699}700 701static void702ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value)703{704 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);705 ahd_outw(ahd, SNSCB_QOFF, value);706}707 708#if 0 /* unused */709static u_int710ahd_get_sescb_qoff(struct ahd_softc *ahd)711{712 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);713 return (ahd_inb(ahd, SESCB_QOFF));714}715#endif716 717static void718ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value)719{720 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);721 ahd_outb(ahd, SESCB_QOFF, value);722}723 724#if 0 /* unused */725static u_int726ahd_get_sdscb_qoff(struct ahd_softc *ahd)727{728 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);729 return (ahd_inb(ahd, SDSCB_QOFF) | (ahd_inb(ahd, SDSCB_QOFF + 1) << 8));730}731#endif732 733static void734ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value)735{736 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);737 ahd_outb(ahd, SDSCB_QOFF, value & 0xFF);738 ahd_outb(ahd, SDSCB_QOFF+1, (value >> 8) & 0xFF);739}740 741u_int742ahd_inb_scbram(struct ahd_softc *ahd, u_int offset)743{744 u_int value;745 746 /*747 * Workaround PCI-X Rev A. hardware bug.748 * After a host read of SCB memory, the chip749 * may become confused into thinking prefetch750 * was required. This starts the discard timer751 * running and can cause an unexpected discard752 * timer interrupt. The work around is to read753 * a normal register prior to the exhaustion of754 * the discard timer. The mode pointer register755 * has no side effects and so serves well for756 * this purpose.757 *758 * Razor #528759 */760 value = ahd_inb(ahd, offset);761 if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0)762 ahd_inb(ahd, MODE_PTR);763 return (value);764}765 766u_int767ahd_inw_scbram(struct ahd_softc *ahd, u_int offset)768{769 return (ahd_inb_scbram(ahd, offset)770 | (ahd_inb_scbram(ahd, offset+1) << 8));771}772 773static uint32_t774ahd_inl_scbram(struct ahd_softc *ahd, u_int offset)775{776 return (ahd_inw_scbram(ahd, offset)777 | (ahd_inw_scbram(ahd, offset+2) << 16));778}779 780static uint64_t781ahd_inq_scbram(struct ahd_softc *ahd, u_int offset)782{783 return (ahd_inl_scbram(ahd, offset)784 | ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32);785}786 787struct scb *788ahd_lookup_scb(struct ahd_softc *ahd, u_int tag)789{790 struct scb* scb;791 792 if (tag >= AHD_SCB_MAX)793 return (NULL);794 scb = ahd->scb_data.scbindex[tag];795 if (scb != NULL)796 ahd_sync_scb(ahd, scb,797 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);798 return (scb);799}800 801static void802ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb)803{804 struct hardware_scb *q_hscb;805 struct map_node *q_hscb_map;806 uint32_t saved_hscb_busaddr;807 808 /*809 * Our queuing method is a bit tricky. The card810 * knows in advance which HSCB (by address) to download,811 * and we can't disappoint it. To achieve this, the next812 * HSCB to download is saved off in ahd->next_queued_hscb.813 * When we are called to queue "an arbitrary scb",814 * we copy the contents of the incoming HSCB to the one815 * the sequencer knows about, swap HSCB pointers and816 * finally assign the SCB to the tag indexed location817 * in the scb_array. This makes sure that we can still818 * locate the correct SCB by SCB_TAG.819 */820 q_hscb = ahd->next_queued_hscb;821 q_hscb_map = ahd->next_queued_hscb_map;822 saved_hscb_busaddr = q_hscb->hscb_busaddr;823 memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));824 q_hscb->hscb_busaddr = saved_hscb_busaddr;825 q_hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;826 827 /* Now swap HSCB pointers. */828 ahd->next_queued_hscb = scb->hscb;829 ahd->next_queued_hscb_map = scb->hscb_map;830 scb->hscb = q_hscb;831 scb->hscb_map = q_hscb_map;832 833 /* Now define the mapping from tag to SCB in the scbindex */834 ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;835}836 837/*838 * Tell the sequencer about a new transaction to execute.839 */840void841ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb)842{843 ahd_swap_with_next_hscb(ahd, scb);844 845 if (SCBID_IS_NULL(SCB_GET_TAG(scb)))846 panic("Attempt to queue invalid SCB tag %x\n",847 SCB_GET_TAG(scb));848 849 /*850 * Keep a history of SCBs we've downloaded in the qinfifo.851 */852 ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb);853 ahd->qinfifonext++;854 855 if (scb->sg_count != 0)856 ahd_setup_data_scb(ahd, scb);857 else858 ahd_setup_noxfer_scb(ahd, scb);859 ahd_setup_scb_common(ahd, scb);860 861 /*862 * Make sure our data is consistent from the863 * perspective of the adapter.864 */865 ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);866 867#ifdef AHD_DEBUG868 if ((ahd_debug & AHD_SHOW_QUEUE) != 0) {869 uint64_t host_dataptr;870 871 host_dataptr = ahd_le64toh(scb->hscb->dataptr);872 printk("%s: Queueing SCB %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n",873 ahd_name(ahd),874 SCB_GET_TAG(scb), scb->hscb->scsiid,875 ahd_le32toh(scb->hscb->hscb_busaddr),876 (u_int)((host_dataptr >> 32) & 0xFFFFFFFF),877 (u_int)(host_dataptr & 0xFFFFFFFF),878 ahd_le32toh(scb->hscb->datacnt));879 }880#endif881 /* Tell the adapter about the newly queued SCB */882 ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);883}884 885/************************** Interrupt Processing ******************************/886static void887ahd_sync_qoutfifo(struct ahd_softc *ahd, int op)888{889 ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,890 /*offset*/0,891 /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op);892}893 894static void895ahd_sync_tqinfifo(struct ahd_softc *ahd, int op)896{897#ifdef AHD_TARGET_MODE898 if ((ahd->flags & AHD_TARGETROLE) != 0) {899 ahd_dmamap_sync(ahd, ahd->shared_data_dmat,900 ahd->shared_data_map.dmamap,901 ahd_targetcmd_offset(ahd, 0),902 sizeof(struct target_cmd) * AHD_TMODE_CMDS,903 op);904 }905#endif906}907 908/*909 * See if the firmware has posted any completed commands910 * into our in-core command complete fifos.911 */912#define AHD_RUN_QOUTFIFO 0x1913#define AHD_RUN_TQINFIFO 0x2914static u_int915ahd_check_cmdcmpltqueues(struct ahd_softc *ahd)916{917 u_int retval;918 919 retval = 0;920 ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,921 /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo),922 /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD);923 if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag924 == ahd->qoutfifonext_valid_tag)925 retval |= AHD_RUN_QOUTFIFO;926#ifdef AHD_TARGET_MODE927 if ((ahd->flags & AHD_TARGETROLE) != 0928 && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) {929 ahd_dmamap_sync(ahd, ahd->shared_data_dmat,930 ahd->shared_data_map.dmamap,931 ahd_targetcmd_offset(ahd, ahd->tqinfifofnext),932 /*len*/sizeof(struct target_cmd),933 BUS_DMASYNC_POSTREAD);934 if (ahd->targetcmds[ahd->tqinfifonext].cmd_valid != 0)935 retval |= AHD_RUN_TQINFIFO;936 }937#endif938 return (retval);939}940 941/*942 * Catch an interrupt from the adapter943 */944int945ahd_intr(struct ahd_softc *ahd)946{947 u_int intstat;948 949 if ((ahd->pause & INTEN) == 0) {950 /*951 * Our interrupt is not enabled on the chip952 * and may be disabled for re-entrancy reasons,953 * so just return. This is likely just a shared954 * interrupt.955 */956 return (0);957 }958 959 /*960 * Instead of directly reading the interrupt status register,961 * infer the cause of the interrupt by checking our in-core962 * completion queues. This avoids a costly PCI bus read in963 * most cases.964 */965 if ((ahd->flags & AHD_ALL_INTERRUPTS) == 0966 && (ahd_check_cmdcmpltqueues(ahd) != 0))967 intstat = CMDCMPLT;968 else969 intstat = ahd_inb(ahd, INTSTAT);970 971 if ((intstat & INT_PEND) == 0)972 return (0);973 974 if (intstat & CMDCMPLT) {975 ahd_outb(ahd, CLRINT, CLRCMDINT);976 977 /*978 * Ensure that the chip sees that we've cleared979 * this interrupt before we walk the output fifo.980 * Otherwise, we may, due to posted bus writes,981 * clear the interrupt after we finish the scan,982 * and after the sequencer has added new entries983 * and asserted the interrupt again.984 */985 if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {986 if (ahd_is_paused(ahd)) {987 /*988 * Potentially lost SEQINT.989 * If SEQINTCODE is non-zero,990 * simulate the SEQINT.991 */992 if (ahd_inb(ahd, SEQINTCODE) != NO_SEQINT)993 intstat |= SEQINT;994 }995 } else {996 ahd_flush_device_writes(ahd);997 }998 ahd_run_qoutfifo(ahd);999 ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]++;1000 ahd->cmdcmplt_total++;1001#ifdef AHD_TARGET_MODE1002 if ((ahd->flags & AHD_TARGETROLE) != 0)1003 ahd_run_tqinfifo(ahd, /*paused*/FALSE);1004#endif1005 }1006 1007 /*1008 * Handle statuses that may invalidate our cached1009 * copy of INTSTAT separately.1010 */1011 if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) {1012 /* Hot eject. Do nothing */1013 } else if (intstat & HWERRINT) {1014 ahd_handle_hwerrint(ahd);1015 } else if ((intstat & (PCIINT|SPLTINT)) != 0) {1016 ahd->bus_intr(ahd);1017 } else {1018 1019 if ((intstat & SEQINT) != 0)1020 ahd_handle_seqint(ahd, intstat);1021 1022 if ((intstat & SCSIINT) != 0)1023 ahd_handle_scsiint(ahd, intstat);1024 }1025 return (1);1026}1027 1028/******************************** Private Inlines *****************************/1029static inline void1030ahd_assert_atn(struct ahd_softc *ahd)1031{1032 ahd_outb(ahd, SCSISIGO, ATNO);1033}1034 1035/*1036 * Determine if the current connection has a packetized1037 * agreement. This does not necessarily mean that we1038 * are currently in a packetized transfer. We could1039 * just as easily be sending or receiving a message.1040 */1041static int1042ahd_currently_packetized(struct ahd_softc *ahd)1043{1044 ahd_mode_state saved_modes;1045 int packetized;1046 1047 saved_modes = ahd_save_modes(ahd);1048 if ((ahd->bugs & AHD_PKTIZED_STATUS_BUG) != 0) {1049 /*1050 * The packetized bit refers to the last1051 * connection, not the current one. Check1052 * for non-zero LQISTATE instead.1053 */1054 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);1055 packetized = ahd_inb(ahd, LQISTATE) != 0;1056 } else {1057 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);1058 packetized = ahd_inb(ahd, LQISTAT2) & PACKETIZED;1059 }1060 ahd_restore_modes(ahd, saved_modes);1061 return (packetized);1062}1063 1064static inline int1065ahd_set_active_fifo(struct ahd_softc *ahd)1066{1067 u_int active_fifo;1068 1069 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);1070 active_fifo = ahd_inb(ahd, DFFSTAT) & CURRFIFO;1071 switch (active_fifo) {1072 case 0:1073 case 1:1074 ahd_set_modes(ahd, active_fifo, active_fifo);1075 return (1);1076 default:1077 return (0);1078 }1079}1080 1081static inline void1082ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl)1083{1084 ahd_busy_tcl(ahd, tcl, SCB_LIST_NULL);1085}1086 1087/*1088 * Determine whether the sequencer reported a residual1089 * for this SCB/transaction.1090 */1091static inline void1092ahd_update_residual(struct ahd_softc *ahd, struct scb *scb)1093{1094 uint32_t sgptr;1095 1096 sgptr = ahd_le32toh(scb->hscb->sgptr);1097 if ((sgptr & SG_STATUS_VALID) != 0)1098 ahd_calc_residual(ahd, scb);1099}1100 1101static inline void1102ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb)1103{1104 uint32_t sgptr;1105 1106 sgptr = ahd_le32toh(scb->hscb->sgptr);1107 if ((sgptr & SG_STATUS_VALID) != 0)1108 ahd_handle_scb_status(ahd, scb);1109 else1110 ahd_done(ahd, scb);1111}1112 1113 1114/************************* Sequencer Execution Control ************************/1115/*1116 * Restart the sequencer program from address zero1117 */1118static void1119ahd_restart(struct ahd_softc *ahd)1120{1121 1122 ahd_pause(ahd);1123 1124 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);1125 1126 /* No more pending messages */1127 ahd_clear_msg_state(ahd);1128 ahd_outb(ahd, SCSISIGO, 0); /* De-assert BSY */1129 ahd_outb(ahd, MSG_OUT, NOP); /* No message to send */1130 ahd_outb(ahd, SXFRCTL1, ahd_inb(ahd, SXFRCTL1) & ~BITBUCKET);1131 ahd_outb(ahd, SEQINTCTL, 0);1132 ahd_outb(ahd, LASTPHASE, P_BUSFREE);1133 ahd_outb(ahd, SEQ_FLAGS, 0);1134 ahd_outb(ahd, SAVED_SCSIID, 0xFF);1135 ahd_outb(ahd, SAVED_LUN, 0xFF);1136 1137 /*1138 * Ensure that the sequencer's idea of TQINPOS1139 * matches our own. The sequencer increments TQINPOS1140 * only after it sees a DMA complete and a reset could1141 * occur before the increment leaving the kernel to believe1142 * the command arrived but the sequencer to not.1143 */1144 ahd_outb(ahd, TQINPOS, ahd->tqinfifonext);1145 1146 /* Always allow reselection */1147 ahd_outb(ahd, SCSISEQ1,1148 ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP));1149 ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);1150 1151 /*1152 * Clear any pending sequencer interrupt. It is no1153 * longer relevant since we're resetting the Program1154 * Counter.1155 */1156 ahd_outb(ahd, CLRINT, CLRSEQINT);1157 1158 ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);1159 ahd_unpause(ahd);1160}1161 1162static void1163ahd_clear_fifo(struct ahd_softc *ahd, u_int fifo)1164{1165 ahd_mode_state saved_modes;1166 1167#ifdef AHD_DEBUG1168 if ((ahd_debug & AHD_SHOW_FIFOS) != 0)1169 printk("%s: Clearing FIFO %d\n", ahd_name(ahd), fifo);1170#endif1171 saved_modes = ahd_save_modes(ahd);1172 ahd_set_modes(ahd, fifo, fifo);1173 ahd_outb(ahd, DFFSXFRCTL, RSTCHN|CLRSHCNT);1174 if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)1175 ahd_outb(ahd, CCSGCTL, CCSGRESET);1176 ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);1177 ahd_outb(ahd, SG_STATE, 0);1178 ahd_restore_modes(ahd, saved_modes);1179}1180 1181/************************* Input/Output Queues ********************************/1182/*1183 * Flush and completed commands that are sitting in the command1184 * complete queues down on the chip but have yet to be dma'ed back up.1185 */1186static void1187ahd_flush_qoutfifo(struct ahd_softc *ahd)1188{1189 struct scb *scb;1190 ahd_mode_state saved_modes;1191 u_int saved_scbptr;1192 u_int ccscbctl;1193 u_int scbid;1194 u_int next_scbid;1195 1196 saved_modes = ahd_save_modes(ahd);1197 1198 /*1199 * Flush the good status FIFO for completed packetized commands.1200 */1201 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);1202 saved_scbptr = ahd_get_scbptr(ahd);1203 while ((ahd_inb(ahd, LQISTAT2) & LQIGSAVAIL) != 0) {1204 u_int fifo_mode;1205 u_int i;1206 1207 scbid = ahd_inw(ahd, GSFIFO);1208 scb = ahd_lookup_scb(ahd, scbid);1209 if (scb == NULL) {1210 printk("%s: Warning - GSFIFO SCB %d invalid\n",1211 ahd_name(ahd), scbid);1212 continue;1213 }1214 /*1215 * Determine if this transaction is still active in1216 * any FIFO. If it is, we must flush that FIFO to1217 * the host before completing the command.1218 */1219 fifo_mode = 0;1220rescan_fifos:1221 for (i = 0; i < 2; i++) {1222 /* Toggle to the other mode. */1223 fifo_mode ^= 1;1224 ahd_set_modes(ahd, fifo_mode, fifo_mode);1225 1226 if (ahd_scb_active_in_fifo(ahd, scb) == 0)1227 continue;1228 1229 ahd_run_data_fifo(ahd, scb);1230 1231 /*1232 * Running this FIFO may cause a CFG4DATA for1233 * this same transaction to assert in the other1234 * FIFO or a new snapshot SAVEPTRS interrupt1235 * in this FIFO. Even running a FIFO may not1236 * clear the transaction if we are still waiting1237 * for data to drain to the host. We must loop1238 * until the transaction is not active in either1239 * FIFO just to be sure. Reset our loop counter1240 * so we will visit both FIFOs again before1241 * declaring this transaction finished. We1242 * also delay a bit so that status has a chance1243 * to change before we look at this FIFO again.1244 */1245 ahd_delay(200);1246 goto rescan_fifos;1247 }1248 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);1249 ahd_set_scbptr(ahd, scbid);1250 if ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_LIST_NULL) == 01251 && ((ahd_inb_scbram(ahd, SCB_SGPTR) & SG_FULL_RESID) != 01252 || (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR)1253 & SG_LIST_NULL) != 0)) {1254 u_int comp_head;1255 1256 /*1257 * The transfer completed with a residual.1258 * Place this SCB on the complete DMA list1259 * so that we update our in-core copy of the1260 * SCB before completing the command.1261 */1262 ahd_outb(ahd, SCB_SCSI_STATUS, 0);1263 ahd_outb(ahd, SCB_SGPTR,1264 ahd_inb_scbram(ahd, SCB_SGPTR)1265 | SG_STATUS_VALID);1266 ahd_outw(ahd, SCB_TAG, scbid);1267 ahd_outw(ahd, SCB_NEXT_COMPLETE, SCB_LIST_NULL);1268 comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);1269 if (SCBID_IS_NULL(comp_head)) {1270 ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, scbid);1271 ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);1272 } else {1273 u_int tail;1274 1275 tail = ahd_inw(ahd, COMPLETE_DMA_SCB_TAIL);1276 ahd_set_scbptr(ahd, tail);1277 ahd_outw(ahd, SCB_NEXT_COMPLETE, scbid);1278 ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);1279 ahd_set_scbptr(ahd, scbid);1280 }1281 } else1282 ahd_complete_scb(ahd, scb);1283 }1284 ahd_set_scbptr(ahd, saved_scbptr);1285 1286 /*1287 * Setup for command channel portion of flush.1288 */1289 ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);1290 1291 /*1292 * Wait for any inprogress DMA to complete and clear DMA state1293 * if this is for an SCB in the qinfifo.1294 */1295 while (((ccscbctl = ahd_inb(ahd, CCSCBCTL)) & (CCARREN|CCSCBEN)) != 0) {1296 1297 if ((ccscbctl & (CCSCBDIR|CCARREN)) == (CCSCBDIR|CCARREN)) {1298 if ((ccscbctl & ARRDONE) != 0)1299 break;1300 } else if ((ccscbctl & CCSCBDONE) != 0)1301 break;1302 ahd_delay(200);1303 }1304 /*1305 * We leave the sequencer to cleanup in the case of DMA's to1306 * update the qoutfifo. In all other cases (DMA's to the1307 * chip or a push of an SCB from the COMPLETE_DMA_SCB list),1308 * we disable the DMA engine so that the sequencer will not1309 * attempt to handle the DMA completion.1310 */1311 if ((ccscbctl & CCSCBDIR) != 0 || (ccscbctl & ARRDONE) != 0)1312 ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN));1313 1314 /*1315 * Complete any SCBs that just finished1316 * being DMA'ed into the qoutfifo.1317 */1318 ahd_run_qoutfifo(ahd);1319 1320 saved_scbptr = ahd_get_scbptr(ahd);1321 /*1322 * Manually update/complete any completed SCBs that are waiting to be1323 * DMA'ed back up to the host.1324 */1325 scbid = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);1326 while (!SCBID_IS_NULL(scbid)) {1327 uint8_t *hscb_ptr;1328 u_int i;1329 1330 ahd_set_scbptr(ahd, scbid);1331 next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);1332 scb = ahd_lookup_scb(ahd, scbid);1333 if (scb == NULL) {1334 printk("%s: Warning - DMA-up and complete "1335 "SCB %d invalid\n", ahd_name(ahd), scbid);1336 continue;1337 }1338 hscb_ptr = (uint8_t *)scb->hscb;1339 for (i = 0; i < sizeof(struct hardware_scb); i++)1340 *hscb_ptr++ = ahd_inb_scbram(ahd, SCB_BASE + i);1341 1342 ahd_complete_scb(ahd, scb);1343 scbid = next_scbid;1344 }1345 ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);1346 ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);1347 1348 scbid = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);1349 while (!SCBID_IS_NULL(scbid)) {1350 1351 ahd_set_scbptr(ahd, scbid);1352 next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);1353 scb = ahd_lookup_scb(ahd, scbid);1354 if (scb == NULL) {1355 printk("%s: Warning - Complete Qfrz SCB %d invalid\n",1356 ahd_name(ahd), scbid);1357 continue;1358 }1359 1360 ahd_complete_scb(ahd, scb);1361 scbid = next_scbid;1362 }1363 ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);1364 1365 scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD);1366 while (!SCBID_IS_NULL(scbid)) {1367 1368 ahd_set_scbptr(ahd, scbid);1369 next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);1370 scb = ahd_lookup_scb(ahd, scbid);1371 if (scb == NULL) {1372 printk("%s: Warning - Complete SCB %d invalid\n",1373 ahd_name(ahd), scbid);1374 continue;1375 }1376 1377 ahd_complete_scb(ahd, scb);1378 scbid = next_scbid;1379 }1380 ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);1381 1382 /*1383 * Restore state.1384 */1385 ahd_set_scbptr(ahd, saved_scbptr);1386 ahd_restore_modes(ahd, saved_modes);1387 ahd->flags |= AHD_UPDATE_PEND_CMDS;1388}1389 1390/*1391 * Determine if an SCB for a packetized transaction1392 * is active in a FIFO.1393 */1394static int1395ahd_scb_active_in_fifo(struct ahd_softc *ahd, struct scb *scb)1396{1397 1398 /*1399 * The FIFO is only active for our transaction if1400 * the SCBPTR matches the SCB's ID and the firmware1401 * has installed a handler for the FIFO or we have1402 * a pending SAVEPTRS or CFG4DATA interrupt.1403 */1404 if (ahd_get_scbptr(ahd) != SCB_GET_TAG(scb)1405 || ((ahd_inb(ahd, LONGJMP_ADDR+1) & INVALID_ADDR) != 01406 && (ahd_inb(ahd, SEQINTSRC) & (CFG4DATA|SAVEPTRS)) == 0))1407 return (0);1408 1409 return (1);1410}1411 1412/*1413 * Run a data fifo to completion for a transaction we know1414 * has completed across the SCSI bus (good status has been1415 * received). We are already set to the correct FIFO mode1416 * on entry to this routine.1417 *1418 * This function attempts to operate exactly as the firmware1419 * would when running this FIFO. Care must be taken to update1420 * this routine any time the firmware's FIFO algorithm is1421 * changed.1422 */1423static void1424ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)1425{1426 u_int seqintsrc;1427 1428 seqintsrc = ahd_inb(ahd, SEQINTSRC);1429 if ((seqintsrc & CFG4DATA) != 0) {1430 uint32_t datacnt;1431 uint32_t sgptr;1432 1433 /*1434 * Clear full residual flag.1435 */1436 sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;1437 ahd_outb(ahd, SCB_SGPTR, sgptr);1438 1439 /*1440 * Load datacnt and address.1441 */1442 datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);1443 if ((datacnt & AHD_DMA_LAST_SEG) != 0) {1444 sgptr |= LAST_SEG;1445 ahd_outb(ahd, SG_STATE, 0);1446 } else1447 ahd_outb(ahd, SG_STATE, LOADING_NEEDED);1448 ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));1449 ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);1450 ahd_outb(ahd, SG_CACHE_PRE, sgptr);1451 ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);1452 1453 /*1454 * Initialize Residual Fields.1455 */1456 ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);1457 ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);1458 1459 /*1460 * Mark the SCB as having a FIFO in use.1461 */1462 ahd_outb(ahd, SCB_FIFO_USE_COUNT,1463 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);1464 1465 /*1466 * Install a "fake" handler for this FIFO.1467 */1468 ahd_outw(ahd, LONGJMP_ADDR, 0);1469 1470 /*1471 * Notify the hardware that we have satisfied1472 * this sequencer interrupt.1473 */1474 ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);1475 } else if ((seqintsrc & SAVEPTRS) != 0) {1476 uint32_t sgptr;1477 uint32_t resid;1478 1479 if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {1480 /*1481 * Snapshot Save Pointers. All that1482 * is necessary to clear the snapshot1483 * is a CLRCHN.1484 */1485 goto clrchn;1486 }1487 1488 /*1489 * Disable S/G fetch so the DMA engine1490 * is available to future users.1491 */1492 if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)1493 ahd_outb(ahd, CCSGCTL, 0);1494 ahd_outb(ahd, SG_STATE, 0);1495 1496 /*1497 * Flush the data FIFO. Strickly only1498 * necessary for Rev A parts.1499 */1500 ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);1501 1502 /*1503 * Calculate residual.1504 */1505 sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);1506 resid = ahd_inl(ahd, SHCNT);1507 resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;1508 ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);1509 if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {1510 /*1511 * Must back up to the correct S/G element.1512 * Typically this just means resetting our1513 * low byte to the offset in the SG_CACHE,1514 * but if we wrapped, we have to correct1515 * the other bytes of the sgptr too.1516 */1517 if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 01518 && (sgptr & 0x80) == 0)1519 sgptr -= 0x100;1520 sgptr &= ~0xFF;1521 sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)1522 & SG_ADDR_MASK;1523 ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);1524 ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);1525 } else if ((resid & AHD_SG_LEN_MASK) == 0) {1526 ahd_outb(ahd, SCB_RESIDUAL_SGPTR,1527 sgptr | SG_LIST_NULL);1528 }1529 /*1530 * Save Pointers.1531 */1532 ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));1533 ahd_outl(ahd, SCB_DATACNT, resid);1534 ahd_outl(ahd, SCB_SGPTR, sgptr);1535 ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);1536 ahd_outb(ahd, SEQIMODE,1537 ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);1538 /*1539 * If the data is to the SCSI bus, we are1540 * done, otherwise wait for FIFOEMP.1541 */1542 if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)1543 goto clrchn;1544 } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {1545 uint32_t sgptr;1546 uint64_t data_addr;1547 uint32_t data_len;1548 u_int dfcntrl;1549 1550 /*1551 * Disable S/G fetch so the DMA engine1552 * is available to future users. We won't1553 * be using the DMA engine to load segments.1554 */1555 if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) {1556 ahd_outb(ahd, CCSGCTL, 0);1557 ahd_outb(ahd, SG_STATE, LOADING_NEEDED);1558 }1559 1560 /*1561 * Wait for the DMA engine to notice that the1562 * host transfer is enabled and that there is1563 * space in the S/G FIFO for new segments before1564 * loading more segments.1565 */1566 if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) != 01567 && (ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) {1568 1569 /*1570 * Determine the offset of the next S/G1571 * element to load.1572 */1573 sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);1574 sgptr &= SG_PTR_MASK;1575 if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {1576 struct ahd_dma64_seg *sg;1577 1578 sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);1579 data_addr = sg->addr;1580 data_len = sg->len;1581 sgptr += sizeof(*sg);1582 } else {1583 struct ahd_dma_seg *sg;1584 1585 sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);1586 data_addr = sg->len & AHD_SG_HIGH_ADDR_MASK;1587 data_addr <<= 8;1588 data_addr |= sg->addr;1589 data_len = sg->len;1590 sgptr += sizeof(*sg);1591 }1592 1593 /*1594 * Update residual information.1595 */1596 ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, data_len >> 24);1597 ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);1598 1599 /*1600 * Load the S/G.1601 */1602 if (data_len & AHD_DMA_LAST_SEG) {1603 sgptr |= LAST_SEG;1604 ahd_outb(ahd, SG_STATE, 0);1605 }1606 ahd_outq(ahd, HADDR, data_addr);1607 ahd_outl(ahd, HCNT, data_len & AHD_SG_LEN_MASK);1608 ahd_outb(ahd, SG_CACHE_PRE, sgptr & 0xFF);1609 1610 /*1611 * Advertise the segment to the hardware.1612 */1613 dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN;1614 if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) {1615 /*1616 * Use SCSIENWRDIS so that SCSIEN1617 * is never modified by this1618 * operation.1619 */1620 dfcntrl |= SCSIENWRDIS;1621 }1622 ahd_outb(ahd, DFCNTRL, dfcntrl);1623 }1624 } else if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG_DONE) != 0) {1625 1626 /*1627 * Transfer completed to the end of SG list1628 * and has flushed to the host.1629 */1630 ahd_outb(ahd, SCB_SGPTR,1631 ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);1632 goto clrchn;1633 } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {1634clrchn:1635 /*1636 * Clear any handler for this FIFO, decrement1637 * the FIFO use count for the SCB, and release1638 * the FIFO.1639 */1640 ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);1641 ahd_outb(ahd, SCB_FIFO_USE_COUNT,1642 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);1643 ahd_outb(ahd, DFFSXFRCTL, CLRCHN);1644 }1645}1646 1647/*1648 * Look for entries in the QoutFIFO that have completed.1649 * The valid_tag completion field indicates the validity1650 * of the entry - the valid value toggles each time through1651 * the queue. We use the sg_status field in the completion1652 * entry to avoid referencing the hscb if the completion1653 * occurred with no errors and no residual. sg_status is1654 * a copy of the first byte (little endian) of the sgptr1655 * hscb field.1656 */1657static void1658ahd_run_qoutfifo(struct ahd_softc *ahd)1659{1660 struct ahd_completion *completion;1661 struct scb *scb;1662 u_int scb_index;1663 1664 if ((ahd->flags & AHD_RUNNING_QOUTFIFO) != 0)1665 panic("ahd_run_qoutfifo recursion");1666 ahd->flags |= AHD_RUNNING_QOUTFIFO;1667 ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD);1668 for (;;) {1669 completion = &ahd->qoutfifo[ahd->qoutfifonext];1670 1671 if (completion->valid_tag != ahd->qoutfifonext_valid_tag)1672 break;1673 1674 scb_index = ahd_le16toh(completion->tag);1675 scb = ahd_lookup_scb(ahd, scb_index);1676 if (scb == NULL) {1677 printk("%s: WARNING no command for scb %d "1678 "(cmdcmplt)\nQOUTPOS = %d\n",1679 ahd_name(ahd), scb_index,1680 ahd->qoutfifonext);1681 ahd_dump_card_state(ahd);1682 } else if ((completion->sg_status & SG_STATUS_VALID) != 0) {1683 ahd_handle_scb_status(ahd, scb);1684 } else {1685 ahd_done(ahd, scb);1686 }1687 1688 ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1);1689 if (ahd->qoutfifonext == 0)1690 ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID;1691 }1692 ahd->flags &= ~AHD_RUNNING_QOUTFIFO;1693}1694 1695/************************* Interrupt Handling *********************************/1696static void1697ahd_handle_hwerrint(struct ahd_softc *ahd)1698{1699 /*1700 * Some catastrophic hardware error has occurred.1701 * Print it for the user and disable the controller.1702 */1703 int i;1704 int error;1705 1706 error = ahd_inb(ahd, ERROR);1707 for (i = 0; i < num_errors; i++) {1708 if ((error & ahd_hard_errors[i].errno) != 0)1709 printk("%s: hwerrint, %s\n",1710 ahd_name(ahd), ahd_hard_errors[i].errmesg);1711 }1712 1713 ahd_dump_card_state(ahd);1714 panic("BRKADRINT");1715 1716 /* Tell everyone that this HBA is no longer available */1717 ahd_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,1718 CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_UNKNOWN,1719 CAM_NO_HBA);1720 1721 /* Tell the system that this controller has gone away. */1722 ahd_free(ahd);1723}1724 1725#ifdef AHD_DEBUG1726static void1727ahd_dump_sglist(struct scb *scb)1728{1729 int i;1730 1731 if (scb->sg_count > 0) {1732 if ((scb->ahd_softc->flags & AHD_64BIT_ADDRESSING) != 0) {1733 struct ahd_dma64_seg *sg_list;1734 1735 sg_list = (struct ahd_dma64_seg*)scb->sg_list;1736 for (i = 0; i < scb->sg_count; i++) {1737 uint64_t addr;1738 1739 addr = ahd_le64toh(sg_list[i].addr);1740 printk("sg[%d] - Addr 0x%x%x : Length %d%s\n",1741 i,1742 (uint32_t)((addr >> 32) & 0xFFFFFFFF),1743 (uint32_t)(addr & 0xFFFFFFFF),1744 sg_list[i].len & AHD_SG_LEN_MASK,1745 (sg_list[i].len & AHD_DMA_LAST_SEG)1746 ? " Last" : "");1747 }1748 } else {1749 struct ahd_dma_seg *sg_list;1750 1751 sg_list = (struct ahd_dma_seg*)scb->sg_list;1752 for (i = 0; i < scb->sg_count; i++) {1753 uint32_t len;1754 1755 len = ahd_le32toh(sg_list[i].len);1756 printk("sg[%d] - Addr 0x%x%x : Length %d%s\n",1757 i,1758 (len & AHD_SG_HIGH_ADDR_MASK) >> 24,1759 ahd_le32toh(sg_list[i].addr),1760 len & AHD_SG_LEN_MASK,1761 len & AHD_DMA_LAST_SEG ? " Last" : "");1762 }1763 }1764 }1765}1766#endif /* AHD_DEBUG */1767 1768static void1769ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)1770{1771 u_int seqintcode;1772 1773 /*1774 * Save the sequencer interrupt code and clear the SEQINT1775 * bit. We will unpause the sequencer, if appropriate,1776 * after servicing the request.1777 */1778 seqintcode = ahd_inb(ahd, SEQINTCODE);1779 ahd_outb(ahd, CLRINT, CLRSEQINT);1780 if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) {1781 /*1782 * Unpause the sequencer and let it clear1783 * SEQINT by writing NO_SEQINT to it. This1784 * will cause the sequencer to be paused again,1785 * which is the expected state of this routine.1786 */1787 ahd_unpause(ahd);1788 while (!ahd_is_paused(ahd))1789 ;1790 ahd_outb(ahd, CLRINT, CLRSEQINT);1791 }1792 ahd_update_modes(ahd);1793#ifdef AHD_DEBUG1794 if ((ahd_debug & AHD_SHOW_MISC) != 0)1795 printk("%s: Handle Seqint Called for code %d\n",1796 ahd_name(ahd), seqintcode);1797#endif1798 switch (seqintcode) {1799 case ENTERING_NONPACK:1800 {1801 struct scb *scb;1802 u_int scbid;1803 1804 AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),1805 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));1806 scbid = ahd_get_scbptr(ahd);1807 scb = ahd_lookup_scb(ahd, scbid);1808 if (scb == NULL) {1809 /*1810 * Somehow need to know if this1811 * is from a selection or reselection.1812 * From that, we can determine target1813 * ID so we at least have an I_T nexus.1814 */1815 } else {1816 ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid);1817 ahd_outb(ahd, SAVED_LUN, scb->hscb->lun);1818 ahd_outb(ahd, SEQ_FLAGS, 0x0);1819 }1820 if ((ahd_inb(ahd, LQISTAT2) & LQIPHASE_OUTPKT) != 01821 && (ahd_inb(ahd, SCSISIGO) & ATNO) != 0) {1822 /*1823 * Phase change after read stream with1824 * CRC error with P0 asserted on last1825 * packet.1826 */1827#ifdef AHD_DEBUG1828 if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)1829 printk("%s: Assuming LQIPHASE_NLQ with "1830 "P0 assertion\n", ahd_name(ahd));1831#endif1832 }1833#ifdef AHD_DEBUG1834 if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)1835 printk("%s: Entering NONPACK\n", ahd_name(ahd));1836#endif1837 break;1838 }1839 case INVALID_SEQINT:1840 printk("%s: Invalid Sequencer interrupt occurred, "1841 "resetting channel.\n",1842 ahd_name(ahd));1843#ifdef AHD_DEBUG1844 if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)1845 ahd_dump_card_state(ahd);1846#endif1847 ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);1848 break;1849 case STATUS_OVERRUN:1850 {1851 struct scb *scb;1852 u_int scbid;1853 1854 scbid = ahd_get_scbptr(ahd);1855 scb = ahd_lookup_scb(ahd, scbid);1856 if (scb != NULL)1857 ahd_print_path(ahd, scb);1858 else1859 printk("%s: ", ahd_name(ahd));1860 printk("SCB %d Packetized Status Overrun", scbid);1861 ahd_dump_card_state(ahd);1862 ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);1863 break;1864 }1865 case CFG4ISTAT_INTR:1866 {1867 struct scb *scb;1868 u_int scbid;1869 1870 scbid = ahd_get_scbptr(ahd);1871 scb = ahd_lookup_scb(ahd, scbid);1872 if (scb == NULL) {1873 ahd_dump_card_state(ahd);1874 printk("CFG4ISTAT: Free SCB %d referenced", scbid);1875 panic("For safety");1876 }1877 ahd_outq(ahd, HADDR, scb->sense_busaddr);1878 ahd_outw(ahd, HCNT, AHD_SENSE_BUFSIZE);1879 ahd_outb(ahd, HCNT + 2, 0);1880 ahd_outb(ahd, SG_CACHE_PRE, SG_LAST_SEG);1881 ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);1882 break;1883 }1884 case ILLEGAL_PHASE:1885 {1886 u_int bus_phase;1887 1888 bus_phase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;1889 printk("%s: ILLEGAL_PHASE 0x%x\n",1890 ahd_name(ahd), bus_phase);1891 1892 switch (bus_phase) {1893 case P_DATAOUT:1894 case P_DATAIN:1895 case P_DATAOUT_DT:1896 case P_DATAIN_DT:1897 case P_MESGOUT:1898 case P_STATUS:1899 case P_MESGIN:1900 ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);1901 printk("%s: Issued Bus Reset.\n", ahd_name(ahd));1902 break;1903 case P_COMMAND:1904 {1905 struct ahd_devinfo devinfo;1906 struct scb *scb;1907 u_int scbid;1908 1909 /*1910 * If a target takes us into the command phase1911 * assume that it has been externally reset and1912 * has thus lost our previous packetized negotiation1913 * agreement. Since we have not sent an identify1914 * message and may not have fully qualified the1915 * connection, we change our command to TUR, assert1916 * ATN and ABORT the task when we go to message in1917 * phase. The OSM will see the REQUEUE_REQUEST1918 * status and retry the command.1919 */1920 scbid = ahd_get_scbptr(ahd);1921 scb = ahd_lookup_scb(ahd, scbid);1922 if (scb == NULL) {1923 printk("Invalid phase with no valid SCB. "1924 "Resetting bus.\n");1925 ahd_reset_channel(ahd, 'A',1926 /*Initiate Reset*/TRUE);1927 break;1928 }1929 ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb),1930 SCB_GET_TARGET(ahd, scb),1931 SCB_GET_LUN(scb),1932 SCB_GET_CHANNEL(ahd, scb),1933 ROLE_INITIATOR);1934 ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,1935 AHD_TRANS_ACTIVE, /*paused*/TRUE);1936 ahd_set_syncrate(ahd, &devinfo, /*period*/0,1937 /*offset*/0, /*ppr_options*/0,1938 AHD_TRANS_ACTIVE, /*paused*/TRUE);1939 /* Hand-craft TUR command */1940 ahd_outb(ahd, SCB_CDB_STORE, 0);1941 ahd_outb(ahd, SCB_CDB_STORE+1, 0);1942 ahd_outb(ahd, SCB_CDB_STORE+2, 0);1943 ahd_outb(ahd, SCB_CDB_STORE+3, 0);1944 ahd_outb(ahd, SCB_CDB_STORE+4, 0);1945 ahd_outb(ahd, SCB_CDB_STORE+5, 0);1946 ahd_outb(ahd, SCB_CDB_LEN, 6);1947 scb->hscb->control &= ~(TAG_ENB|SCB_TAG_TYPE);1948 scb->hscb->control |= MK_MESSAGE;1949 ahd_outb(ahd, SCB_CONTROL, scb->hscb->control);1950 ahd_outb(ahd, MSG_OUT, HOST_MSG);1951 ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid);1952 /*1953 * The lun is 0, regardless of the SCB's lun1954 * as we have not sent an identify message.1955 */1956 ahd_outb(ahd, SAVED_LUN, 0);1957 ahd_outb(ahd, SEQ_FLAGS, 0);1958 ahd_assert_atn(ahd);1959 scb->flags &= ~SCB_PACKETIZED;1960 scb->flags |= SCB_ABORT|SCB_EXTERNAL_RESET;1961 ahd_freeze_devq(ahd, scb);1962 ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);1963 ahd_freeze_scb(scb);1964 1965 /* Notify XPT */1966 ahd_send_async(ahd, devinfo.channel, devinfo.target,1967 CAM_LUN_WILDCARD, AC_SENT_BDR);1968 1969 /*1970 * Allow the sequencer to continue with1971 * non-pack processing.1972 */1973 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);1974 ahd_outb(ahd, CLRLQOINT1, CLRLQOPHACHGINPKT);1975 if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {1976 ahd_outb(ahd, CLRLQOINT1, 0);1977 }1978#ifdef AHD_DEBUG1979 if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {1980 ahd_print_path(ahd, scb);1981 printk("Unexpected command phase from "1982 "packetized target\n");1983 }1984#endif1985 break;1986 }1987 }1988 break;1989 }1990 case CFG4OVERRUN:1991 {1992 struct scb *scb;1993 u_int scb_index;1994 1995#ifdef AHD_DEBUG1996 if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {1997 printk("%s: CFG4OVERRUN mode = %x\n", ahd_name(ahd),1998 ahd_inb(ahd, MODE_PTR));1999 }2000#endif2001 scb_index = ahd_get_scbptr(ahd);2002 scb = ahd_lookup_scb(ahd, scb_index);2003 if (scb == NULL) {2004 /*2005 * Attempt to transfer to an SCB that is2006 * not outstanding.2007 */2008 ahd_assert_atn(ahd);2009 ahd_outb(ahd, MSG_OUT, HOST_MSG);2010 ahd->msgout_buf[0] = ABORT_TASK;2011 ahd->msgout_len = 1;2012 ahd->msgout_index = 0;2013 ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;2014 /*2015 * Clear status received flag to prevent any2016 * attempt to complete this bogus SCB.2017 */2018 ahd_outb(ahd, SCB_CONTROL,2019 ahd_inb_scbram(ahd, SCB_CONTROL)2020 & ~STATUS_RCVD);2021 }2022 break;2023 }2024 case DUMP_CARD_STATE:2025 {2026 ahd_dump_card_state(ahd);2027 break;2028 }2029 case PDATA_REINIT:2030 {2031#ifdef AHD_DEBUG2032 if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {2033 printk("%s: PDATA_REINIT - DFCNTRL = 0x%x "2034 "SG_CACHE_SHADOW = 0x%x\n",2035 ahd_name(ahd), ahd_inb(ahd, DFCNTRL),2036 ahd_inb(ahd, SG_CACHE_SHADOW));2037 }2038#endif2039 ahd_reinitialize_dataptrs(ahd);2040 break;2041 }2042 case HOST_MSG_LOOP:2043 {2044 struct ahd_devinfo devinfo;2045 2046 /*2047 * The sequencer has encountered a message phase2048 * that requires host assistance for completion.2049 * While handling the message phase(s), we will be2050 * notified by the sequencer after each byte is2051 * transferred so we can track bus phase changes.2052 *2053 * If this is the first time we've seen a HOST_MSG_LOOP2054 * interrupt, initialize the state of the host message2055 * loop.2056 */2057 ahd_fetch_devinfo(ahd, &devinfo);2058 if (ahd->msg_type == MSG_TYPE_NONE) {2059 struct scb *scb;2060 u_int scb_index;2061 u_int bus_phase;2062 2063 bus_phase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;2064 if (bus_phase != P_MESGIN2065 && bus_phase != P_MESGOUT) {2066 printk("ahd_intr: HOST_MSG_LOOP bad "2067 "phase 0x%x\n", bus_phase);2068 /*2069 * Probably transitioned to bus free before2070 * we got here. Just punt the message.2071 */2072 ahd_dump_card_state(ahd);2073 ahd_clear_intstat(ahd);2074 ahd_restart(ahd);2075 return;2076 }2077 2078 scb_index = ahd_get_scbptr(ahd);2079 scb = ahd_lookup_scb(ahd, scb_index);2080 if (devinfo.role == ROLE_INITIATOR) {2081 if (bus_phase == P_MESGOUT)2082 ahd_setup_initiator_msgout(ahd,2083 &devinfo,2084 scb);2085 else {2086 ahd->msg_type =2087 MSG_TYPE_INITIATOR_MSGIN;2088 ahd->msgin_index = 0;2089 }2090 }2091#ifdef AHD_TARGET_MODE2092 else {2093 if (bus_phase == P_MESGOUT) {2094 ahd->msg_type =2095 MSG_TYPE_TARGET_MSGOUT;2096 ahd->msgin_index = 0;2097 } else2098 ahd_setup_target_msgin(ahd,2099 &devinfo,2100 scb);2101 }2102#endif2103 }2104 2105 ahd_handle_message_phase(ahd);2106 break;2107 }2108 case NO_MATCH:2109 {2110 /* Ensure we don't leave the selection hardware on */2111 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);2112 ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);2113 2114 printk("%s:%c:%d: no active SCB for reconnecting "2115 "target - issuing BUS DEVICE RESET\n",2116 ahd_name(ahd), 'A', ahd_inb(ahd, SELID) >> 4);2117 printk("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, "2118 "REG0 == 0x%x ACCUM = 0x%x\n",2119 ahd_inb(ahd, SAVED_SCSIID), ahd_inb(ahd, SAVED_LUN),2120 ahd_inw(ahd, REG0), ahd_inb(ahd, ACCUM));2121 printk("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, "2122 "SINDEX == 0x%x\n",2123 ahd_inb(ahd, SEQ_FLAGS), ahd_get_scbptr(ahd),2124 ahd_find_busy_tcl(ahd,2125 BUILD_TCL(ahd_inb(ahd, SAVED_SCSIID),2126 ahd_inb(ahd, SAVED_LUN))),2127 ahd_inw(ahd, SINDEX));2128 printk("SELID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, "2129 "SCB_CONTROL == 0x%x\n",2130 ahd_inb(ahd, SELID), ahd_inb_scbram(ahd, SCB_SCSIID),2131 ahd_inb_scbram(ahd, SCB_LUN),2132 ahd_inb_scbram(ahd, SCB_CONTROL));2133 printk("SCSIBUS[0] == 0x%x, SCSISIGI == 0x%x\n",2134 ahd_inb(ahd, SCSIBUS), ahd_inb(ahd, SCSISIGI));2135 printk("SXFRCTL0 == 0x%x\n", ahd_inb(ahd, SXFRCTL0));2136 printk("SEQCTL0 == 0x%x\n", ahd_inb(ahd, SEQCTL0));2137 ahd_dump_card_state(ahd);2138 ahd->msgout_buf[0] = TARGET_RESET;2139 ahd->msgout_len = 1;2140 ahd->msgout_index = 0;2141 ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;2142 ahd_outb(ahd, MSG_OUT, HOST_MSG);2143 ahd_assert_atn(ahd);2144 break;2145 }2146 case PROTO_VIOLATION:2147 {2148 ahd_handle_proto_violation(ahd);2149 break;2150 }2151 case IGN_WIDE_RES:2152 {2153 struct ahd_devinfo devinfo;2154 2155 ahd_fetch_devinfo(ahd, &devinfo);2156 ahd_handle_ign_wide_residue(ahd, &devinfo);2157 break;2158 }2159 case BAD_PHASE:2160 {2161 u_int lastphase;2162 2163 lastphase = ahd_inb(ahd, LASTPHASE);2164 printk("%s:%c:%d: unknown scsi bus phase %x, "2165 "lastphase = 0x%x. Attempting to continue\n",2166 ahd_name(ahd), 'A',2167 SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)),2168 lastphase, ahd_inb(ahd, SCSISIGI));2169 break;2170 }2171 case MISSED_BUSFREE:2172 {2173 u_int lastphase;2174 2175 lastphase = ahd_inb(ahd, LASTPHASE);2176 printk("%s:%c:%d: Missed busfree. "2177 "Lastphase = 0x%x, Curphase = 0x%x\n",2178 ahd_name(ahd), 'A',2179 SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)),2180 lastphase, ahd_inb(ahd, SCSISIGI));2181 ahd_restart(ahd);2182 return;2183 }2184 case DATA_OVERRUN:2185 {2186 /*2187 * When the sequencer detects an overrun, it2188 * places the controller in "BITBUCKET" mode2189 * and allows the target to complete its transfer.2190 * Unfortunately, none of the counters get updated2191 * when the controller is in this mode, so we have2192 * no way of knowing how large the overrun was.2193 */2194 struct scb *scb;2195 u_int scbindex;2196#ifdef AHD_DEBUG2197 u_int lastphase;2198#endif2199 2200 scbindex = ahd_get_scbptr(ahd);2201 scb = ahd_lookup_scb(ahd, scbindex);2202#ifdef AHD_DEBUG2203 lastphase = ahd_inb(ahd, LASTPHASE);2204 if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {2205 ahd_print_path(ahd, scb);2206 printk("data overrun detected %s. Tag == 0x%x.\n",2207 ahd_lookup_phase_entry(lastphase)->phasemsg,2208 SCB_GET_TAG(scb));2209 ahd_print_path(ahd, scb);2210 printk("%s seen Data Phase. Length = %ld. "2211 "NumSGs = %d.\n",2212 ahd_inb(ahd, SEQ_FLAGS) & DPHASE2213 ? "Have" : "Haven't",2214 ahd_get_transfer_length(scb), scb->sg_count);2215 ahd_dump_sglist(scb);2216 }2217#endif2218 2219 /*2220 * Set this and it will take effect when the2221 * target does a command complete.2222 */2223 ahd_freeze_devq(ahd, scb);2224 ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR);2225 ahd_freeze_scb(scb);2226 break;2227 }2228 case MKMSG_FAILED:2229 {2230 struct ahd_devinfo devinfo;2231 struct scb *scb;2232 u_int scbid;2233 2234 ahd_fetch_devinfo(ahd, &devinfo);2235 printk("%s:%c:%d:%d: Attempt to issue message failed\n",2236 ahd_name(ahd), devinfo.channel, devinfo.target,2237 devinfo.lun);2238 scbid = ahd_get_scbptr(ahd);2239 scb = ahd_lookup_scb(ahd, scbid);2240 if (scb != NULL2241 && (scb->flags & SCB_RECOVERY_SCB) != 0)2242 /*2243 * Ensure that we didn't put a second instance of this2244 * SCB into the QINFIFO.2245 */2246 ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),2247 SCB_GET_CHANNEL(ahd, scb),2248 SCB_GET_LUN(scb), SCB_GET_TAG(scb),2249 ROLE_INITIATOR, /*status*/0,2250 SEARCH_REMOVE);2251 ahd_outb(ahd, SCB_CONTROL,2252 ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE);2253 break;2254 }2255 case TASKMGMT_FUNC_COMPLETE:2256 {2257 u_int scbid;2258 struct scb *scb;2259 2260 scbid = ahd_get_scbptr(ahd);2261 scb = ahd_lookup_scb(ahd, scbid);2262 if (scb != NULL) {2263 u_int lun;2264 u_int tag;2265 cam_status error;2266 2267 ahd_print_path(ahd, scb);2268 printk("Task Management Func 0x%x Complete\n",2269 scb->hscb->task_management);2270 lun = CAM_LUN_WILDCARD;2271 tag = SCB_LIST_NULL;2272 2273 switch (scb->hscb->task_management) {2274 case SIU_TASKMGMT_ABORT_TASK:2275 tag = SCB_GET_TAG(scb);2276 fallthrough;2277 case SIU_TASKMGMT_ABORT_TASK_SET:2278 case SIU_TASKMGMT_CLEAR_TASK_SET:2279 lun = scb->hscb->lun;2280 error = CAM_REQ_ABORTED;2281 ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),2282 'A', lun, tag, ROLE_INITIATOR,2283 error);2284 break;2285 case SIU_TASKMGMT_LUN_RESET:2286 lun = scb->hscb->lun;2287 fallthrough;2288 case SIU_TASKMGMT_TARGET_RESET:2289 {2290 struct ahd_devinfo devinfo;2291 2292 ahd_scb_devinfo(ahd, &devinfo, scb);2293 error = CAM_BDR_SENT;2294 ahd_handle_devreset(ahd, &devinfo, lun,2295 CAM_BDR_SENT,2296 lun != CAM_LUN_WILDCARD2297 ? "Lun Reset"2298 : "Target Reset",2299 /*verbose_level*/0);2300 break;2301 }2302 default:2303 panic("Unexpected TaskMgmt Func\n");2304 break;2305 }2306 }2307 break;2308 }2309 case TASKMGMT_CMD_CMPLT_OKAY:2310 {2311 u_int scbid;2312 struct scb *scb;2313 2314 /*2315 * An ABORT TASK TMF failed to be delivered before2316 * the targeted command completed normally.2317 */2318 scbid = ahd_get_scbptr(ahd);2319 scb = ahd_lookup_scb(ahd, scbid);2320 if (scb != NULL) {2321 /*2322 * Remove the second instance of this SCB from2323 * the QINFIFO if it is still there.2324 */2325 ahd_print_path(ahd, scb);2326 printk("SCB completes before TMF\n");2327 /*2328 * Handle losing the race. Wait until any2329 * current selection completes. We will then2330 * set the TMF back to zero in this SCB so that2331 * the sequencer doesn't bother to issue another2332 * sequencer interrupt for its completion.2333 */2334 while ((ahd_inb(ahd, SCSISEQ0) & ENSELO) != 02335 && (ahd_inb(ahd, SSTAT0) & SELDO) == 02336 && (ahd_inb(ahd, SSTAT1) & SELTO) == 0)2337 ;2338 ahd_outb(ahd, SCB_TASK_MANAGEMENT, 0);2339 ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),2340 SCB_GET_CHANNEL(ahd, scb),2341 SCB_GET_LUN(scb), SCB_GET_TAG(scb),2342 ROLE_INITIATOR, /*status*/0,2343 SEARCH_REMOVE);2344 }2345 break;2346 }2347 case TRACEPOINT0:2348 case TRACEPOINT1:2349 case TRACEPOINT2:2350 case TRACEPOINT3:2351 printk("%s: Tracepoint %d\n", ahd_name(ahd),2352 seqintcode - TRACEPOINT0);2353 break;2354 case NO_SEQINT:2355 break;2356 case SAW_HWERR:2357 ahd_handle_hwerrint(ahd);2358 break;2359 default:2360 printk("%s: Unexpected SEQINTCODE %d\n", ahd_name(ahd),2361 seqintcode);2362 break;2363 }2364 /*2365 * The sequencer is paused immediately on2366 * a SEQINT, so we should restart it when2367 * we're done.2368 */2369 ahd_unpause(ahd);2370}2371 2372static void2373ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)2374{2375 struct scb *scb;2376 u_int status0;2377 u_int status3;2378 u_int status;2379 u_int lqistat1;2380 u_int lqostat0;2381 u_int scbid;2382 u_int busfreetime;2383 2384 ahd_update_modes(ahd);2385 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);2386 2387 status3 = ahd_inb(ahd, SSTAT3) & (NTRAMPERR|OSRAMPERR);2388 status0 = ahd_inb(ahd, SSTAT0) & (IOERR|OVERRUN|SELDI|SELDO);2389 status = ahd_inb(ahd, SSTAT1) & (SELTO|SCSIRSTI|BUSFREE|SCSIPERR);2390 lqistat1 = ahd_inb(ahd, LQISTAT1);2391 lqostat0 = ahd_inb(ahd, LQOSTAT0);2392 busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME;2393 2394 /*2395 * Ignore external resets after a bus reset.2396 */2397 if (((status & SCSIRSTI) != 0) && (ahd->flags & AHD_BUS_RESET_ACTIVE)) {2398 ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI);2399 return;2400 }2401 2402 /*2403 * Clear bus reset flag2404 */2405 ahd->flags &= ~AHD_BUS_RESET_ACTIVE;2406 2407 if ((status0 & (SELDI|SELDO)) != 0) {2408 u_int simode0;2409 2410 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);2411 simode0 = ahd_inb(ahd, SIMODE0);2412 status0 &= simode0 & (IOERR|OVERRUN|SELDI|SELDO);2413 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);2414 }2415 scbid = ahd_get_scbptr(ahd);2416 scb = ahd_lookup_scb(ahd, scbid);2417 if (scb != NULL2418 && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)2419 scb = NULL;2420 2421 if ((status0 & IOERR) != 0) {2422 u_int now_lvd;2423 2424 now_lvd = ahd_inb(ahd, SBLKCTL) & ENAB40;2425 printk("%s: Transceiver State Has Changed to %s mode\n",2426 ahd_name(ahd), now_lvd ? "LVD" : "SE");2427 ahd_outb(ahd, CLRSINT0, CLRIOERR);2428 /*2429 * A change in I/O mode is equivalent to a bus reset.2430 */2431 ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);2432 ahd_pause(ahd);2433 ahd_setup_iocell_workaround(ahd);2434 ahd_unpause(ahd);2435 } else if ((status0 & OVERRUN) != 0) {2436 2437 printk("%s: SCSI offset overrun detected. Resetting bus.\n",2438 ahd_name(ahd));2439 ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);2440 } else if ((status & SCSIRSTI) != 0) {2441 2442 printk("%s: Someone reset channel A\n", ahd_name(ahd));2443 ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE);2444 } else if ((status & SCSIPERR) != 0) {2445 2446 /* Make sure the sequencer is in a safe location. */2447 ahd_clear_critical_section(ahd);2448 2449 ahd_handle_transmission_error(ahd);2450 } else if (lqostat0 != 0) {2451 2452 printk("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0);2453 ahd_outb(ahd, CLRLQOINT0, lqostat0);2454 if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)2455 ahd_outb(ahd, CLRLQOINT1, 0);2456 } else if ((status & SELTO) != 0) {2457 /* Stop the selection */2458 ahd_outb(ahd, SCSISEQ0, 0);2459 2460 /* Make sure the sequencer is in a safe location. */2461 ahd_clear_critical_section(ahd);2462 2463 /* No more pending messages */2464 ahd_clear_msg_state(ahd);2465 2466 /* Clear interrupt state */2467 ahd_outb(ahd, CLRSINT1, CLRSELTIMEO|CLRBUSFREE|CLRSCSIPERR);2468 2469 /*2470 * Although the driver does not care about the2471 * 'Selection in Progress' status bit, the busy2472 * LED does. SELINGO is only cleared by a successful2473 * selection, so we must manually clear it to insure2474 * the LED turns off just incase no future successful2475 * selections occur (e.g. no devices on the bus).2476 */2477 ahd_outb(ahd, CLRSINT0, CLRSELINGO);2478 2479 scbid = ahd_inw(ahd, WAITING_TID_HEAD);2480 scb = ahd_lookup_scb(ahd, scbid);2481 if (scb == NULL) {2482 printk("%s: ahd_intr - referenced scb not "2483 "valid during SELTO scb(0x%x)\n",2484 ahd_name(ahd), scbid);2485 ahd_dump_card_state(ahd);2486 } else {2487 struct ahd_devinfo devinfo;2488#ifdef AHD_DEBUG2489 if ((ahd_debug & AHD_SHOW_SELTO) != 0) {2490 ahd_print_path(ahd, scb);2491 printk("Saw Selection Timeout for SCB 0x%x\n",2492 scbid);2493 }2494#endif2495 ahd_scb_devinfo(ahd, &devinfo, scb);2496 ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT);2497 ahd_freeze_devq(ahd, scb);2498 2499 /*2500 * Cancel any pending transactions on the device2501 * now that it seems to be missing. This will2502 * also revert us to async/narrow transfers until2503 * we can renegotiate with the device.2504 */2505 ahd_handle_devreset(ahd, &devinfo,2506 CAM_LUN_WILDCARD,2507 CAM_SEL_TIMEOUT,2508 "Selection Timeout",2509 /*verbose_level*/1);2510 }2511 ahd_outb(ahd, CLRINT, CLRSCSIINT);2512 ahd_iocell_first_selection(ahd);2513 ahd_unpause(ahd);2514 } else if ((status0 & (SELDI|SELDO)) != 0) {2515 2516 ahd_iocell_first_selection(ahd);2517 ahd_unpause(ahd);2518 } else if (status3 != 0) {2519 printk("%s: SCSI Cell parity error SSTAT3 == 0x%x\n",2520 ahd_name(ahd), status3);2521 ahd_outb(ahd, CLRSINT3, status3);2522 } else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) {2523 2524 /* Make sure the sequencer is in a safe location. */2525 ahd_clear_critical_section(ahd);2526 2527 ahd_handle_lqiphase_error(ahd, lqistat1);2528 } else if ((lqistat1 & LQICRCI_NLQ) != 0) {2529 /*2530 * This status can be delayed during some2531 * streaming operations. The SCSIPHASE2532 * handler has already dealt with this case2533 * so just clear the error.2534 */2535 ahd_outb(ahd, CLRLQIINT1, CLRLQICRCI_NLQ);2536 } else if ((status & BUSFREE) != 02537 || (lqistat1 & LQOBUSFREE) != 0) {2538 u_int lqostat1;2539 int restart;2540 int clear_fifo;2541 int packetized;2542 u_int mode;2543 2544 /*2545 * Clear our selection hardware as soon as possible.2546 * We may have an entry in the waiting Q for this target,2547 * that is affected by this busfree and we don't want to2548 * go about selecting the target while we handle the event.2549 */2550 ahd_outb(ahd, SCSISEQ0, 0);2551 2552 /* Make sure the sequencer is in a safe location. */2553 ahd_clear_critical_section(ahd);2554 2555 /*2556 * Determine what we were up to at the time of2557 * the busfree.2558 */2559 mode = AHD_MODE_SCSI;2560 busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME;2561 lqostat1 = ahd_inb(ahd, LQOSTAT1);2562 switch (busfreetime) {2563 case BUSFREE_DFF0:2564 case BUSFREE_DFF1:2565 {2566 mode = busfreetime == BUSFREE_DFF02567 ? AHD_MODE_DFF0 : AHD_MODE_DFF1;2568 ahd_set_modes(ahd, mode, mode);2569 scbid = ahd_get_scbptr(ahd);2570 scb = ahd_lookup_scb(ahd, scbid);2571 if (scb == NULL) {2572 printk("%s: Invalid SCB %d in DFF%d "2573 "during unexpected busfree\n",2574 ahd_name(ahd), scbid, mode);2575 packetized = 0;2576 } else2577 packetized = (scb->flags & SCB_PACKETIZED) != 0;2578 clear_fifo = 1;2579 break;2580 }2581 case BUSFREE_LQO:2582 clear_fifo = 0;2583 packetized = 1;2584 break;2585 default:2586 clear_fifo = 0;2587 packetized = (lqostat1 & LQOBUSFREE) != 0;2588 if (!packetized2589 && ahd_inb(ahd, LASTPHASE) == P_BUSFREE2590 && (ahd_inb(ahd, SSTAT0) & SELDI) == 02591 && ((ahd_inb(ahd, SSTAT0) & SELDO) == 02592 || (ahd_inb(ahd, SCSISEQ0) & ENSELO) == 0))2593 /*2594 * Assume packetized if we are not2595 * on the bus in a non-packetized2596 * capacity and any pending selection2597 * was a packetized selection.2598 */2599 packetized = 1;2600 break;2601 }2602 2603#ifdef AHD_DEBUG2604 if ((ahd_debug & AHD_SHOW_MISC) != 0)2605 printk("Saw Busfree. Busfreetime = 0x%x.\n",2606 busfreetime);2607#endif2608 /*2609 * Busfrees that occur in non-packetized phases are2610 * handled by the nonpkt_busfree handler.2611 */2612 if (packetized && ahd_inb(ahd, LASTPHASE) == P_BUSFREE) {2613 restart = ahd_handle_pkt_busfree(ahd, busfreetime);2614 } else {2615 packetized = 0;2616 restart = ahd_handle_nonpkt_busfree(ahd);2617 }2618 /*2619 * Clear the busfree interrupt status. The setting of2620 * the interrupt is a pulse, so in a perfect world, we2621 * would not need to muck with the ENBUSFREE logic. This2622 * would ensure that if the bus moves on to another2623 * connection, busfree protection is still in force. If2624 * BUSFREEREV is broken, however, we must manually clear2625 * the ENBUSFREE if the busfree occurred during a non-pack2626 * connection so that we don't get false positives during2627 * future, packetized, connections.2628 */2629 ahd_outb(ahd, CLRSINT1, CLRBUSFREE);2630 if (packetized == 02631 && (ahd->bugs & AHD_BUSFREEREV_BUG) != 0)2632 ahd_outb(ahd, SIMODE1,2633 ahd_inb(ahd, SIMODE1) & ~ENBUSFREE);2634 2635 if (clear_fifo)2636 ahd_clear_fifo(ahd, mode);2637 2638 ahd_clear_msg_state(ahd);2639 ahd_outb(ahd, CLRINT, CLRSCSIINT);2640 if (restart) {2641 ahd_restart(ahd);2642 } else {2643 ahd_unpause(ahd);2644 }2645 } else {2646 printk("%s: Missing case in ahd_handle_scsiint. status = %x\n",2647 ahd_name(ahd), status);2648 ahd_dump_card_state(ahd);2649 ahd_clear_intstat(ahd);2650 ahd_unpause(ahd);2651 }2652}2653 2654static void2655ahd_handle_transmission_error(struct ahd_softc *ahd)2656{2657 struct scb *scb;2658 u_int scbid;2659 u_int lqistat1;2660 u_int msg_out;2661 u_int curphase;2662 u_int lastphase;2663 u_int perrdiag;2664 u_int cur_col;2665 int silent;2666 2667 scb = NULL;2668 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);2669 lqistat1 = ahd_inb(ahd, LQISTAT1) & ~(LQIPHASE_LQ|LQIPHASE_NLQ);2670 ahd_inb(ahd, LQISTAT2);2671 if ((lqistat1 & (LQICRCI_NLQ|LQICRCI_LQ)) == 02672 && (ahd->bugs & AHD_NLQICRC_DELAYED_BUG) != 0) {2673 u_int lqistate;2674 2675 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);2676 lqistate = ahd_inb(ahd, LQISTATE);2677 if ((lqistate >= 0x1E && lqistate <= 0x24)2678 || (lqistate == 0x29)) {2679#ifdef AHD_DEBUG2680 if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {2681 printk("%s: NLQCRC found via LQISTATE\n",2682 ahd_name(ahd));2683 }2684#endif2685 lqistat1 |= LQICRCI_NLQ;2686 }2687 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);2688 }2689 2690 ahd_outb(ahd, CLRLQIINT1, lqistat1);2691 lastphase = ahd_inb(ahd, LASTPHASE);2692 curphase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;2693 perrdiag = ahd_inb(ahd, PERRDIAG);2694 msg_out = INITIATOR_ERROR;2695 ahd_outb(ahd, CLRSINT1, CLRSCSIPERR);2696 2697 /*2698 * Try to find the SCB associated with this error.2699 */2700 silent = FALSE;2701 if (lqistat1 == 02702 || (lqistat1 & LQICRCI_NLQ) != 0) {2703 if ((lqistat1 & (LQICRCI_NLQ|LQIOVERI_NLQ)) != 0)2704 ahd_set_active_fifo(ahd);2705 scbid = ahd_get_scbptr(ahd);2706 scb = ahd_lookup_scb(ahd, scbid);2707 if (scb != NULL && SCB_IS_SILENT(scb))2708 silent = TRUE;2709 }2710 2711 cur_col = 0;2712 if (silent == FALSE) {2713 printk("%s: Transmission error detected\n", ahd_name(ahd));2714 ahd_lqistat1_print(lqistat1, &cur_col, 50);2715 ahd_lastphase_print(lastphase, &cur_col, 50);2716 ahd_scsisigi_print(curphase, &cur_col, 50);2717 ahd_perrdiag_print(perrdiag, &cur_col, 50);2718 printk("\n");2719 ahd_dump_card_state(ahd);2720 }2721 2722 if ((lqistat1 & (LQIOVERI_LQ|LQIOVERI_NLQ)) != 0) {2723 if (silent == FALSE) {2724 printk("%s: Gross protocol error during incoming "2725 "packet. lqistat1 == 0x%x. Resetting bus.\n",2726 ahd_name(ahd), lqistat1);2727 }2728 ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);2729 return;2730 } else if ((lqistat1 & LQICRCI_LQ) != 0) {2731 /*2732 * A CRC error has been detected on an incoming LQ.2733 * The bus is currently hung on the last ACK.2734 * Hit LQIRETRY to release the last ack, and2735 * wait for the sequencer to determine that ATNO2736 * is asserted while in message out to take us2737 * to our host message loop. No NONPACKREQ or2738 * LQIPHASE type errors will occur in this2739 * scenario. After this first LQIRETRY, the LQI2740 * manager will be in ISELO where it will2741 * happily sit until another packet phase begins.2742 * Unexpected bus free detection is enabled2743 * through any phases that occur after we release2744 * this last ack until the LQI manager sees a2745 * packet phase. This implies we may have to2746 * ignore a perfectly valid "unexected busfree"2747 * after our "initiator detected error" message is2748 * sent. A busfree is the expected response after2749 * we tell the target that it's L_Q was corrupted.2750 * (SPI4R09 10.7.3.3.3)2751 */2752 ahd_outb(ahd, LQCTL2, LQIRETRY);2753 printk("LQIRetry for LQICRCI_LQ to release ACK\n");2754 } else if ((lqistat1 & LQICRCI_NLQ) != 0) {2755 /*2756 * We detected a CRC error in a NON-LQ packet.2757 * The hardware has varying behavior in this situation2758 * depending on whether this packet was part of a2759 * stream or not.2760 *2761 * PKT by PKT mode:2762 * The hardware has already acked the complete packet.2763 * If the target honors our outstanding ATN condition,2764 * we should be (or soon will be) in MSGOUT phase.2765 * This will trigger the LQIPHASE_LQ status bit as the2766 * hardware was expecting another LQ. Unexpected2767 * busfree detection is enabled. Once LQIPHASE_LQ is2768 * true (first entry into host message loop is much2769 * the same), we must clear LQIPHASE_LQ and hit2770 * LQIRETRY so the hardware is ready to handle2771 * a future LQ. NONPACKREQ will not be asserted again2772 * once we hit LQIRETRY until another packet is2773 * processed. The target may either go busfree2774 * or start another packet in response to our message.2775 *2776 * Read Streaming P0 asserted:2777 * If we raise ATN and the target completes the entire2778 * stream (P0 asserted during the last packet), the2779 * hardware will ack all data and return to the ISTART2780 * state. When the target reponds to our ATN condition,2781 * LQIPHASE_LQ will be asserted. We should respond to2782 * this with an LQIRETRY to prepare for any future2783 * packets. NONPACKREQ will not be asserted again2784 * once we hit LQIRETRY until another packet is2785 * processed. The target may either go busfree or2786 * start another packet in response to our message.2787 * Busfree detection is enabled.2788 *2789 * Read Streaming P0 not asserted:2790 * If we raise ATN and the target transitions to2791 * MSGOUT in or after a packet where P0 is not2792 * asserted, the hardware will assert LQIPHASE_NLQ.2793 * We should respond to the LQIPHASE_NLQ with an2794 * LQIRETRY. Should the target stay in a non-pkt2795 * phase after we send our message, the hardware2796 * will assert LQIPHASE_LQ. Recovery is then just as2797 * listed above for the read streaming with P0 asserted.2798 * Busfree detection is enabled.2799 */2800 if (silent == FALSE)2801 printk("LQICRC_NLQ\n");2802 if (scb == NULL) {2803 printk("%s: No SCB valid for LQICRC_NLQ. "2804 "Resetting bus\n", ahd_name(ahd));2805 ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);2806 return;2807 }2808 } else if ((lqistat1 & LQIBADLQI) != 0) {2809 printk("Need to handle BADLQI!\n");2810 ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);2811 return;2812 } else if ((perrdiag & (PARITYERR|PREVPHASE)) == PARITYERR) {2813 if ((curphase & ~P_DATAIN_DT) != 0) {2814 /* Ack the byte. So we can continue. */2815 if (silent == FALSE)2816 printk("Acking %s to clear perror\n",2817 ahd_lookup_phase_entry(curphase)->phasemsg);2818 ahd_inb(ahd, SCSIDAT);2819 }2820 2821 if (curphase == P_MESGIN)2822 msg_out = MSG_PARITY_ERROR;2823 }2824 2825 /*2826 * We've set the hardware to assert ATN if we2827 * get a parity error on "in" phases, so all we2828 * need to do is stuff the message buffer with2829 * the appropriate message. "In" phases have set2830 * mesg_out to something other than NOP.2831 */2832 ahd->send_msg_perror = msg_out;2833 if (scb != NULL && msg_out == INITIATOR_ERROR)2834 scb->flags |= SCB_TRANSMISSION_ERROR;2835 ahd_outb(ahd, MSG_OUT, HOST_MSG);2836 ahd_outb(ahd, CLRINT, CLRSCSIINT);2837 ahd_unpause(ahd);2838}2839 2840static void2841ahd_handle_lqiphase_error(struct ahd_softc *ahd, u_int lqistat1)2842{2843 /*2844 * Clear the sources of the interrupts.2845 */2846 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);2847 ahd_outb(ahd, CLRLQIINT1, lqistat1);2848 2849 /*2850 * If the "illegal" phase changes were in response2851 * to our ATN to flag a CRC error, AND we ended up2852 * on packet boundaries, clear the error, restart the2853 * LQI manager as appropriate, and go on our merry2854 * way toward sending the message. Otherwise, reset2855 * the bus to clear the error.2856 */2857 ahd_set_active_fifo(ahd);2858 if ((ahd_inb(ahd, SCSISIGO) & ATNO) != 02859 && (ahd_inb(ahd, MDFFSTAT) & DLZERO) != 0) {2860 if ((lqistat1 & LQIPHASE_LQ) != 0) {2861 printk("LQIRETRY for LQIPHASE_LQ\n");2862 ahd_outb(ahd, LQCTL2, LQIRETRY);2863 } else if ((lqistat1 & LQIPHASE_NLQ) != 0) {2864 printk("LQIRETRY for LQIPHASE_NLQ\n");2865 ahd_outb(ahd, LQCTL2, LQIRETRY);2866 } else2867 panic("ahd_handle_lqiphase_error: No phase errors\n");2868 ahd_dump_card_state(ahd);2869 ahd_outb(ahd, CLRINT, CLRSCSIINT);2870 ahd_unpause(ahd);2871 } else {2872 printk("Resetting Channel for LQI Phase error\n");2873 ahd_dump_card_state(ahd);2874 ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);2875 }2876}2877 2878/*2879 * Packetized unexpected or expected busfree.2880 * Entered in mode based on busfreetime.2881 */2882static int2883ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)2884{2885 u_int lqostat1;2886 2887 AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),2888 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));2889 lqostat1 = ahd_inb(ahd, LQOSTAT1);2890 if ((lqostat1 & LQOBUSFREE) != 0) {2891 struct scb *scb;2892 u_int scbid;2893 u_int saved_scbptr;2894 u_int waiting_h;2895 u_int waiting_t;2896 u_int next;2897 2898 /*2899 * The LQO manager detected an unexpected busfree2900 * either:2901 *2902 * 1) During an outgoing LQ.2903 * 2) After an outgoing LQ but before the first2904 * REQ of the command packet.2905 * 3) During an outgoing command packet.2906 *2907 * In all cases, CURRSCB is pointing to the2908 * SCB that encountered the failure. Clean2909 * up the queue, clear SELDO and LQOBUSFREE,2910 * and allow the sequencer to restart the select2911 * out at its lesure.2912 */2913 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);2914 scbid = ahd_inw(ahd, CURRSCB);2915 scb = ahd_lookup_scb(ahd, scbid);2916 if (scb == NULL)2917 panic("SCB not valid during LQOBUSFREE");2918 /*2919 * Clear the status.2920 */2921 ahd_outb(ahd, CLRLQOINT1, CLRLQOBUSFREE);2922 if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)2923 ahd_outb(ahd, CLRLQOINT1, 0);2924 ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);2925 ahd_flush_device_writes(ahd);2926 ahd_outb(ahd, CLRSINT0, CLRSELDO);2927 2928 /*2929 * Return the LQO manager to its idle loop. It will2930 * not do this automatically if the busfree occurs2931 * after the first REQ of either the LQ or command2932 * packet or between the LQ and command packet.2933 */2934 ahd_outb(ahd, LQCTL2, ahd_inb(ahd, LQCTL2) | LQOTOIDLE);2935 2936 /*2937 * Update the waiting for selection queue so2938 * we restart on the correct SCB.2939 */2940 waiting_h = ahd_inw(ahd, WAITING_TID_HEAD);2941 saved_scbptr = ahd_get_scbptr(ahd);2942 if (waiting_h != scbid) {2943 2944 ahd_outw(ahd, WAITING_TID_HEAD, scbid);2945 waiting_t = ahd_inw(ahd, WAITING_TID_TAIL);2946 if (waiting_t == waiting_h) {2947 ahd_outw(ahd, WAITING_TID_TAIL, scbid);2948 next = SCB_LIST_NULL;2949 } else {2950 ahd_set_scbptr(ahd, waiting_h);2951 next = ahd_inw_scbram(ahd, SCB_NEXT2);2952 }2953 ahd_set_scbptr(ahd, scbid);2954 ahd_outw(ahd, SCB_NEXT2, next);2955 }2956 ahd_set_scbptr(ahd, saved_scbptr);2957 if (scb->crc_retry_count < AHD_MAX_LQ_CRC_ERRORS) {2958 if (SCB_IS_SILENT(scb) == FALSE) {2959 ahd_print_path(ahd, scb);2960 printk("Probable outgoing LQ CRC error. "2961 "Retrying command\n");2962 }2963 scb->crc_retry_count++;2964 } else {2965 ahd_set_transaction_status(scb, CAM_UNCOR_PARITY);2966 ahd_freeze_scb(scb);2967 ahd_freeze_devq(ahd, scb);2968 }2969 /* Return unpausing the sequencer. */2970 return (0);2971 } else if ((ahd_inb(ahd, PERRDIAG) & PARITYERR) != 0) {2972 /*2973 * Ignore what are really parity errors that2974 * occur on the last REQ of a free running2975 * clock prior to going busfree. Some drives2976 * do not properly active negate just before2977 * going busfree resulting in a parity glitch.2978 */2979 ahd_outb(ahd, CLRSINT1, CLRSCSIPERR|CLRBUSFREE);2980#ifdef AHD_DEBUG2981 if ((ahd_debug & AHD_SHOW_MASKED_ERRORS) != 0)2982 printk("%s: Parity on last REQ detected "2983 "during busfree phase.\n",2984 ahd_name(ahd));2985#endif2986 /* Return unpausing the sequencer. */2987 return (0);2988 }2989 if (ahd->src_mode != AHD_MODE_SCSI) {2990 u_int scbid;2991 struct scb *scb;2992 2993 scbid = ahd_get_scbptr(ahd);2994 scb = ahd_lookup_scb(ahd, scbid);2995 ahd_print_path(ahd, scb);2996 printk("Unexpected PKT busfree condition\n");2997 ahd_dump_card_state(ahd);2998 ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb), 'A',2999 SCB_GET_LUN(scb), SCB_GET_TAG(scb),3000 ROLE_INITIATOR, CAM_UNEXP_BUSFREE);3001 3002 /* Return restarting the sequencer. */3003 return (1);3004 }3005 printk("%s: Unexpected PKT busfree condition\n", ahd_name(ahd));3006 ahd_dump_card_state(ahd);3007 /* Restart the sequencer. */3008 return (1);3009}3010 3011/*3012 * Non-packetized unexpected or expected busfree.3013 */3014static int3015ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)3016{3017 struct ahd_devinfo devinfo;3018 struct scb *scb;3019 u_int lastphase;3020 u_int saved_scsiid;3021 u_int saved_lun;3022 u_int target;3023 u_int initiator_role_id;3024 u_int scbid;3025 u_int ppr_busfree;3026 int printerror;3027 3028 /*3029 * Look at what phase we were last in. If its message out,3030 * chances are pretty good that the busfree was in response3031 * to one of our abort requests.3032 */3033 lastphase = ahd_inb(ahd, LASTPHASE);3034 saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);3035 saved_lun = ahd_inb(ahd, SAVED_LUN);3036 target = SCSIID_TARGET(ahd, saved_scsiid);3037 initiator_role_id = SCSIID_OUR_ID(saved_scsiid);3038 ahd_compile_devinfo(&devinfo, initiator_role_id,3039 target, saved_lun, 'A', ROLE_INITIATOR);3040 printerror = 1;3041 3042 scbid = ahd_get_scbptr(ahd);3043 scb = ahd_lookup_scb(ahd, scbid);3044 if (scb != NULL3045 && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)3046 scb = NULL;3047 3048 ppr_busfree = (ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0;3049 if (lastphase == P_MESGOUT) {3050 u_int tag;3051 3052 tag = SCB_LIST_NULL;3053 if (ahd_sent_msg(ahd, AHDMSG_1B, ABORT_TASK, TRUE)3054 || ahd_sent_msg(ahd, AHDMSG_1B, ABORT_TASK_SET, TRUE)) {3055 int found;3056 int sent_msg;3057 3058 if (scb == NULL) {3059 ahd_print_devinfo(ahd, &devinfo);3060 printk("Abort for unidentified "3061 "connection completed.\n");3062 /* restart the sequencer. */3063 return (1);3064 }3065 sent_msg = ahd->msgout_buf[ahd->msgout_index - 1];3066 ahd_print_path(ahd, scb);3067 printk("SCB %d - Abort%s Completed.\n",3068 SCB_GET_TAG(scb),3069 sent_msg == ABORT_TASK ? "" : " Tag");3070 3071 if (sent_msg == ABORT_TASK)3072 tag = SCB_GET_TAG(scb);3073 3074 if ((scb->flags & SCB_EXTERNAL_RESET) != 0) {3075 /*3076 * This abort is in response to an3077 * unexpected switch to command phase3078 * for a packetized connection. Since3079 * the identify message was never sent,3080 * "saved lun" is 0. We really want to3081 * abort only the SCB that encountered3082 * this error, which could have a different3083 * lun. The SCB will be retried so the OS3084 * will see the UA after renegotiating to3085 * packetized.3086 */3087 tag = SCB_GET_TAG(scb);3088 saved_lun = scb->hscb->lun;3089 }3090 found = ahd_abort_scbs(ahd, target, 'A', saved_lun,3091 tag, ROLE_INITIATOR,3092 CAM_REQ_ABORTED);3093 printk("found == 0x%x\n", found);3094 printerror = 0;3095 } else if (ahd_sent_msg(ahd, AHDMSG_1B,3096 TARGET_RESET, TRUE)) {3097 ahd_handle_devreset(ahd, &devinfo, CAM_LUN_WILDCARD,3098 CAM_BDR_SENT, "Bus Device Reset",3099 /*verbose_level*/0);3100 printerror = 0;3101 } else if (ahd_sent_msg(ahd, AHDMSG_EXT, EXTENDED_PPR, FALSE)3102 && ppr_busfree == 0) {3103 struct ahd_initiator_tinfo *tinfo;3104 struct ahd_tmode_tstate *tstate;3105 3106 /*3107 * PPR Rejected.3108 *3109 * If the previous negotiation was packetized,3110 * this could be because the device has been3111 * reset without our knowledge. Force our3112 * current negotiation to async and retry the3113 * negotiation. Otherwise retry the command3114 * with non-ppr negotiation.3115 */3116#ifdef AHD_DEBUG3117 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)3118 printk("PPR negotiation rejected busfree.\n");3119#endif3120 tinfo = ahd_fetch_transinfo(ahd, devinfo.channel,3121 devinfo.our_scsiid,3122 devinfo.target, &tstate);3123 if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)!=0) {3124 ahd_set_width(ahd, &devinfo,3125 MSG_EXT_WDTR_BUS_8_BIT,3126 AHD_TRANS_CUR,3127 /*paused*/TRUE);3128 ahd_set_syncrate(ahd, &devinfo,3129 /*period*/0, /*offset*/0,3130 /*ppr_options*/0,3131 AHD_TRANS_CUR,3132 /*paused*/TRUE);3133 /*3134 * The expect PPR busfree handler below3135 * will effect the retry and necessary3136 * abort.3137 */3138 } else {3139 tinfo->curr.transport_version = 2;3140 tinfo->goal.transport_version = 2;3141 tinfo->goal.ppr_options = 0;3142 if (scb != NULL) {3143 /*3144 * Remove any SCBs in the waiting3145 * for selection queue that may3146 * also be for this target so that3147 * command ordering is preserved.3148 */3149 ahd_freeze_devq(ahd, scb);3150 ahd_qinfifo_requeue_tail(ahd, scb);3151 }3152 printerror = 0;3153 }3154 } else if (ahd_sent_msg(ahd, AHDMSG_EXT, EXTENDED_WDTR, FALSE)3155 && ppr_busfree == 0) {3156 /*3157 * Negotiation Rejected. Go-narrow and3158 * retry command.3159 */3160#ifdef AHD_DEBUG3161 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)3162 printk("WDTR negotiation rejected busfree.\n");3163#endif3164 ahd_set_width(ahd, &devinfo,3165 MSG_EXT_WDTR_BUS_8_BIT,3166 AHD_TRANS_CUR|AHD_TRANS_GOAL,3167 /*paused*/TRUE);3168 if (scb != NULL) {3169 /*3170 * Remove any SCBs in the waiting for3171 * selection queue that may also be for3172 * this target so that command ordering3173 * is preserved.3174 */3175 ahd_freeze_devq(ahd, scb);3176 ahd_qinfifo_requeue_tail(ahd, scb);3177 }3178 printerror = 0;3179 } else if (ahd_sent_msg(ahd, AHDMSG_EXT, EXTENDED_SDTR, FALSE)3180 && ppr_busfree == 0) {3181 /*3182 * Negotiation Rejected. Go-async and3183 * retry command.3184 */3185#ifdef AHD_DEBUG3186 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)3187 printk("SDTR negotiation rejected busfree.\n");3188#endif3189 ahd_set_syncrate(ahd, &devinfo,3190 /*period*/0, /*offset*/0,3191 /*ppr_options*/0,3192 AHD_TRANS_CUR|AHD_TRANS_GOAL,3193 /*paused*/TRUE);3194 if (scb != NULL) {3195 /*3196 * Remove any SCBs in the waiting for3197 * selection queue that may also be for3198 * this target so that command ordering3199 * is preserved.3200 */3201 ahd_freeze_devq(ahd, scb);3202 ahd_qinfifo_requeue_tail(ahd, scb);3203 }3204 printerror = 0;3205 } else if ((ahd->msg_flags & MSG_FLAG_EXPECT_IDE_BUSFREE) != 03206 && ahd_sent_msg(ahd, AHDMSG_1B,3207 INITIATOR_ERROR, TRUE)) {3208 3209#ifdef AHD_DEBUG3210 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)3211 printk("Expected IDE Busfree\n");3212#endif3213 printerror = 0;3214 } else if ((ahd->msg_flags & MSG_FLAG_EXPECT_QASREJ_BUSFREE)3215 && ahd_sent_msg(ahd, AHDMSG_1B,3216 MESSAGE_REJECT, TRUE)) {3217 3218#ifdef AHD_DEBUG3219 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)3220 printk("Expected QAS Reject Busfree\n");3221#endif3222 printerror = 0;3223 }3224 }3225 3226 /*3227 * The busfree required flag is honored at the end of3228 * the message phases. We check it last in case we3229 * had to send some other message that caused a busfree.3230 */3231 if (scb != NULL && printerror != 03232 && (lastphase == P_MESGIN || lastphase == P_MESGOUT)3233 && ((ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0)) {3234 3235 ahd_freeze_devq(ahd, scb);3236 ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);3237 ahd_freeze_scb(scb);3238 if ((ahd->msg_flags & MSG_FLAG_IU_REQ_CHANGED) != 0) {3239 ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),3240 SCB_GET_CHANNEL(ahd, scb),3241 SCB_GET_LUN(scb), SCB_LIST_NULL,3242 ROLE_INITIATOR, CAM_REQ_ABORTED);3243 } else {3244#ifdef AHD_DEBUG3245 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)3246 printk("PPR Negotiation Busfree.\n");3247#endif3248 ahd_done(ahd, scb);3249 }3250 printerror = 0;3251 }3252 if (printerror != 0) {3253 int aborted;3254 3255 aborted = 0;3256 if (scb != NULL) {3257 u_int tag;3258 3259 if ((scb->hscb->control & TAG_ENB) != 0)3260 tag = SCB_GET_TAG(scb);3261 else3262 tag = SCB_LIST_NULL;3263 ahd_print_path(ahd, scb);3264 aborted = ahd_abort_scbs(ahd, target, 'A',3265 SCB_GET_LUN(scb), tag,3266 ROLE_INITIATOR,3267 CAM_UNEXP_BUSFREE);3268 } else {3269 /*3270 * We had not fully identified this connection,3271 * so we cannot abort anything.3272 */3273 printk("%s: ", ahd_name(ahd));3274 }3275 printk("Unexpected busfree %s, %d SCBs aborted, "3276 "PRGMCNT == 0x%x\n",3277 ahd_lookup_phase_entry(lastphase)->phasemsg,3278 aborted,3279 ahd_inw(ahd, PRGMCNT));3280 ahd_dump_card_state(ahd);3281 if (lastphase != P_BUSFREE)3282 ahd_force_renegotiation(ahd, &devinfo);3283 }3284 /* Always restart the sequencer. */3285 return (1);3286}3287 3288static void3289ahd_handle_proto_violation(struct ahd_softc *ahd)3290{3291 struct ahd_devinfo devinfo;3292 struct scb *scb;3293 u_int scbid;3294 u_int seq_flags;3295 u_int curphase;3296 u_int lastphase;3297 int found;3298 3299 ahd_fetch_devinfo(ahd, &devinfo);3300 scbid = ahd_get_scbptr(ahd);3301 scb = ahd_lookup_scb(ahd, scbid);3302 seq_flags = ahd_inb(ahd, SEQ_FLAGS);3303 curphase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK;3304 lastphase = ahd_inb(ahd, LASTPHASE);3305 if ((seq_flags & NOT_IDENTIFIED) != 0) {3306 3307 /*3308 * The reconnecting target either did not send an3309 * identify message, or did, but we didn't find an SCB3310 * to match.3311 */3312 ahd_print_devinfo(ahd, &devinfo);3313 printk("Target did not send an IDENTIFY message. "3314 "LASTPHASE = 0x%x.\n", lastphase);3315 scb = NULL;3316 } else if (scb == NULL) {3317 /*3318 * We don't seem to have an SCB active for this3319 * transaction. Print an error and reset the bus.3320 */3321 ahd_print_devinfo(ahd, &devinfo);3322 printk("No SCB found during protocol violation\n");3323 goto proto_violation_reset;3324 } else {3325 ahd_set_transaction_status(scb, CAM_SEQUENCE_FAIL);3326 if ((seq_flags & NO_CDB_SENT) != 0) {3327 ahd_print_path(ahd, scb);3328 printk("No or incomplete CDB sent to device.\n");3329 } else if ((ahd_inb_scbram(ahd, SCB_CONTROL)3330 & STATUS_RCVD) == 0) {3331 /*3332 * The target never bothered to provide status to3333 * us prior to completing the command. Since we don't3334 * know the disposition of this command, we must attempt3335 * to abort it. Assert ATN and prepare to send an abort3336 * message.3337 */3338 ahd_print_path(ahd, scb);3339 printk("Completed command without status.\n");3340 } else {3341 ahd_print_path(ahd, scb);3342 printk("Unknown protocol violation.\n");3343 ahd_dump_card_state(ahd);3344 }3345 }3346 if ((lastphase & ~P_DATAIN_DT) == 03347 || lastphase == P_COMMAND) {3348proto_violation_reset:3349 /*3350 * Target either went directly to data3351 * phase or didn't respond to our ATN.3352 * The only safe thing to do is to blow3353 * it away with a bus reset.3354 */3355 found = ahd_reset_channel(ahd, 'A', TRUE);3356 printk("%s: Issued Channel %c Bus Reset. "3357 "%d SCBs aborted\n", ahd_name(ahd), 'A', found);3358 } else {3359 /*3360 * Leave the selection hardware off in case3361 * this abort attempt will affect yet to3362 * be sent commands.3363 */3364 ahd_outb(ahd, SCSISEQ0,3365 ahd_inb(ahd, SCSISEQ0) & ~ENSELO);3366 ahd_assert_atn(ahd);3367 ahd_outb(ahd, MSG_OUT, HOST_MSG);3368 if (scb == NULL) {3369 ahd_print_devinfo(ahd, &devinfo);3370 ahd->msgout_buf[0] = ABORT_TASK;3371 ahd->msgout_len = 1;3372 ahd->msgout_index = 0;3373 ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;3374 } else {3375 ahd_print_path(ahd, scb);3376 scb->flags |= SCB_ABORT;3377 }3378 printk("Protocol violation %s. Attempting to abort.\n",3379 ahd_lookup_phase_entry(curphase)->phasemsg);3380 }3381}3382 3383/*3384 * Force renegotiation to occur the next time we initiate3385 * a command to the current device.3386 */3387static void3388ahd_force_renegotiation(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)3389{3390 struct ahd_initiator_tinfo *targ_info;3391 struct ahd_tmode_tstate *tstate;3392 3393#ifdef AHD_DEBUG3394 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {3395 ahd_print_devinfo(ahd, devinfo);3396 printk("Forcing renegotiation\n");3397 }3398#endif3399 targ_info = ahd_fetch_transinfo(ahd,3400 devinfo->channel,3401 devinfo->our_scsiid,3402 devinfo->target,3403 &tstate);3404 ahd_update_neg_request(ahd, devinfo, tstate,3405 targ_info, AHD_NEG_IF_NON_ASYNC);3406}3407 3408#define AHD_MAX_STEPS 20003409static void3410ahd_clear_critical_section(struct ahd_softc *ahd)3411{3412 ahd_mode_state saved_modes;3413 int stepping;3414 int steps;3415 int first_instr;3416 u_int simode0;3417 u_int simode1;3418 u_int simode3;3419 u_int lqimode0;3420 u_int lqimode1;3421 u_int lqomode0;3422 u_int lqomode1;3423 3424 if (ahd->num_critical_sections == 0)3425 return;3426 3427 stepping = FALSE;3428 steps = 0;3429 first_instr = 0;3430 simode0 = 0;3431 simode1 = 0;3432 simode3 = 0;3433 lqimode0 = 0;3434 lqimode1 = 0;3435 lqomode0 = 0;3436 lqomode1 = 0;3437 saved_modes = ahd_save_modes(ahd);3438 for (;;) {3439 struct cs *cs;3440 u_int seqaddr;3441 u_int i;3442 3443 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);3444 seqaddr = ahd_inw(ahd, CURADDR);3445 3446 cs = ahd->critical_sections;3447 for (i = 0; i < ahd->num_critical_sections; i++, cs++) {3448 if (cs->begin < seqaddr && cs->end >= seqaddr)3449 break;3450 }3451 3452 if (i == ahd->num_critical_sections)3453 break;3454 3455 if (steps > AHD_MAX_STEPS) {3456 printk("%s: Infinite loop in critical section\n"3457 "%s: First Instruction 0x%x now 0x%x\n",3458 ahd_name(ahd), ahd_name(ahd), first_instr,3459 seqaddr);3460 ahd_dump_card_state(ahd);3461 panic("critical section loop");3462 }3463 3464 steps++;3465#ifdef AHD_DEBUG3466 if ((ahd_debug & AHD_SHOW_MISC) != 0)3467 printk("%s: Single stepping at 0x%x\n", ahd_name(ahd),3468 seqaddr);3469#endif3470 if (stepping == FALSE) {3471 3472 first_instr = seqaddr;3473 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);3474 simode0 = ahd_inb(ahd, SIMODE0);3475 simode3 = ahd_inb(ahd, SIMODE3);3476 lqimode0 = ahd_inb(ahd, LQIMODE0);3477 lqimode1 = ahd_inb(ahd, LQIMODE1);3478 lqomode0 = ahd_inb(ahd, LQOMODE0);3479 lqomode1 = ahd_inb(ahd, LQOMODE1);3480 ahd_outb(ahd, SIMODE0, 0);3481 ahd_outb(ahd, SIMODE3, 0);3482 ahd_outb(ahd, LQIMODE0, 0);3483 ahd_outb(ahd, LQIMODE1, 0);3484 ahd_outb(ahd, LQOMODE0, 0);3485 ahd_outb(ahd, LQOMODE1, 0);3486 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);3487 simode1 = ahd_inb(ahd, SIMODE1);3488 /*3489 * We don't clear ENBUSFREE. Unfortunately3490 * we cannot re-enable busfree detection within3491 * the current connection, so we must leave it3492 * on while single stepping.3493 */3494 ahd_outb(ahd, SIMODE1, simode1 & ENBUSFREE);3495 ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) | STEP);3496 stepping = TRUE;3497 }3498 ahd_outb(ahd, CLRSINT1, CLRBUSFREE);3499 ahd_outb(ahd, CLRINT, CLRSCSIINT);3500 ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);3501 ahd_outb(ahd, HCNTRL, ahd->unpause);3502 while (!ahd_is_paused(ahd))3503 ahd_delay(200);3504 ahd_update_modes(ahd);3505 }3506 if (stepping) {3507 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);3508 ahd_outb(ahd, SIMODE0, simode0);3509 ahd_outb(ahd, SIMODE3, simode3);3510 ahd_outb(ahd, LQIMODE0, lqimode0);3511 ahd_outb(ahd, LQIMODE1, lqimode1);3512 ahd_outb(ahd, LQOMODE0, lqomode0);3513 ahd_outb(ahd, LQOMODE1, lqomode1);3514 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);3515 ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) & ~STEP);3516 ahd_outb(ahd, SIMODE1, simode1);3517 /*3518 * SCSIINT seems to glitch occasionally when3519 * the interrupt masks are restored. Clear SCSIINT3520 * one more time so that only persistent errors3521 * are seen as a real interrupt.3522 */3523 ahd_outb(ahd, CLRINT, CLRSCSIINT);3524 }3525 ahd_restore_modes(ahd, saved_modes);3526}3527 3528/*3529 * Clear any pending interrupt status.3530 */3531static void3532ahd_clear_intstat(struct ahd_softc *ahd)3533{3534 AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),3535 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));3536 /* Clear any interrupt conditions this may have caused */3537 ahd_outb(ahd, CLRLQIINT0, CLRLQIATNQAS|CLRLQICRCT1|CLRLQICRCT23538 |CLRLQIBADLQT|CLRLQIATNLQ|CLRLQIATNCMD);3539 ahd_outb(ahd, CLRLQIINT1, CLRLQIPHASE_LQ|CLRLQIPHASE_NLQ|CLRLIQABORT3540 |CLRLQICRCI_LQ|CLRLQICRCI_NLQ|CLRLQIBADLQI3541 |CLRLQIOVERI_LQ|CLRLQIOVERI_NLQ|CLRNONPACKREQ);3542 ahd_outb(ahd, CLRLQOINT0, CLRLQOTARGSCBPERR|CLRLQOSTOPT2|CLRLQOATNLQ3543 |CLRLQOATNPKT|CLRLQOTCRC);3544 ahd_outb(ahd, CLRLQOINT1, CLRLQOINITSCBPERR|CLRLQOSTOPI2|CLRLQOBADQAS3545 |CLRLQOBUSFREE|CLRLQOPHACHGINPKT);3546 if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {3547 ahd_outb(ahd, CLRLQOINT0, 0);3548 ahd_outb(ahd, CLRLQOINT1, 0);3549 }3550 ahd_outb(ahd, CLRSINT3, CLRNTRAMPERR|CLROSRAMPERR);3551 ahd_outb(ahd, CLRSINT1, CLRSELTIMEO|CLRATNO|CLRSCSIRSTI3552 |CLRBUSFREE|CLRSCSIPERR|CLRREQINIT);3553 ahd_outb(ahd, CLRSINT0, CLRSELDO|CLRSELDI|CLRSELINGO3554 |CLRIOERR|CLROVERRUN);3555 ahd_outb(ahd, CLRINT, CLRSCSIINT);3556}3557 3558/**************************** Debugging Routines ******************************/3559#ifdef AHD_DEBUG3560uint32_t ahd_debug = AHD_DEBUG_OPTS;3561#endif3562 3563#if 03564void3565ahd_print_scb(struct scb *scb)3566{3567 struct hardware_scb *hscb;3568 int i;3569 3570 hscb = scb->hscb;3571 printk("scb:%p control:0x%x scsiid:0x%x lun:%d cdb_len:%d\n",3572 (void *)scb,3573 hscb->control,3574 hscb->scsiid,3575 hscb->lun,3576 hscb->cdb_len);3577 printk("Shared Data: ");3578 for (i = 0; i < sizeof(hscb->shared_data.idata.cdb); i++)3579 printk("%#02x", hscb->shared_data.idata.cdb[i]);3580 printk(" dataptr:%#x%x datacnt:%#x sgptr:%#x tag:%#x\n",3581 (uint32_t)((ahd_le64toh(hscb->dataptr) >> 32) & 0xFFFFFFFF),3582 (uint32_t)(ahd_le64toh(hscb->dataptr) & 0xFFFFFFFF),3583 ahd_le32toh(hscb->datacnt),3584 ahd_le32toh(hscb->sgptr),3585 SCB_GET_TAG(scb));3586 ahd_dump_sglist(scb);3587}3588#endif /* 0 */3589 3590/************************* Transfer Negotiation *******************************/3591/*3592 * Allocate per target mode instance (ID we respond to as a target)3593 * transfer negotiation data structures.3594 */3595static struct ahd_tmode_tstate *3596ahd_alloc_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel)3597{3598 struct ahd_tmode_tstate *master_tstate;3599 struct ahd_tmode_tstate *tstate;3600 int i;3601 3602 master_tstate = ahd->enabled_targets[ahd->our_id];3603 if (ahd->enabled_targets[scsi_id] != NULL3604 && ahd->enabled_targets[scsi_id] != master_tstate)3605 panic("%s: ahd_alloc_tstate - Target already allocated",3606 ahd_name(ahd));3607 tstate = kmalloc(sizeof(*tstate), GFP_ATOMIC);3608 if (tstate == NULL)3609 return (NULL);3610 3611 /*3612 * If we have allocated a master tstate, copy user settings from3613 * the master tstate (taken from SRAM or the EEPROM) for this3614 * channel, but reset our current and goal settings to async/narrow3615 * until an initiator talks to us.3616 */3617 if (master_tstate != NULL) {3618 memcpy(tstate, master_tstate, sizeof(*tstate));3619 memset(tstate->enabled_luns, 0, sizeof(tstate->enabled_luns));3620 for (i = 0; i < 16; i++) {3621 memset(&tstate->transinfo[i].curr, 0,3622 sizeof(tstate->transinfo[i].curr));3623 memset(&tstate->transinfo[i].goal, 0,3624 sizeof(tstate->transinfo[i].goal));3625 }3626 } else3627 memset(tstate, 0, sizeof(*tstate));3628 ahd->enabled_targets[scsi_id] = tstate;3629 return (tstate);3630}3631 3632#ifdef AHD_TARGET_MODE3633/*3634 * Free per target mode instance (ID we respond to as a target)3635 * transfer negotiation data structures.3636 */3637static void3638ahd_free_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel, int force)3639{3640 struct ahd_tmode_tstate *tstate;3641 3642 /*3643 * Don't clean up our "master" tstate.3644 * It has our default user settings.3645 */3646 if (scsi_id == ahd->our_id3647 && force == FALSE)3648 return;3649 3650 tstate = ahd->enabled_targets[scsi_id];3651 kfree(tstate);3652 ahd->enabled_targets[scsi_id] = NULL;3653}3654#endif3655 3656/*3657 * Called when we have an active connection to a target on the bus,3658 * this function finds the nearest period to the input period limited3659 * by the capabilities of the bus connectivity of and sync settings for3660 * the target.3661 */3662static void3663ahd_devlimited_syncrate(struct ahd_softc *ahd,3664 struct ahd_initiator_tinfo *tinfo,3665 u_int *period, u_int *ppr_options, role_t role)3666{3667 struct ahd_transinfo *transinfo;3668 u_int maxsync;3669 3670 if ((ahd_inb(ahd, SBLKCTL) & ENAB40) != 03671 && (ahd_inb(ahd, SSTAT2) & EXP_ACTIVE) == 0) {3672 maxsync = AHD_SYNCRATE_PACED;3673 } else {3674 maxsync = AHD_SYNCRATE_ULTRA;3675 /* Can't do DT related options on an SE bus */3676 *ppr_options &= MSG_EXT_PPR_QAS_REQ;3677 }3678 /*3679 * Never allow a value higher than our current goal3680 * period otherwise we may allow a target initiated3681 * negotiation to go above the limit as set by the3682 * user. In the case of an initiator initiated3683 * sync negotiation, we limit based on the user3684 * setting. This allows the system to still accept3685 * incoming negotiations even if target initiated3686 * negotiation is not performed.3687 */3688 if (role == ROLE_TARGET)3689 transinfo = &tinfo->user;3690 else3691 transinfo = &tinfo->goal;3692 *ppr_options &= (transinfo->ppr_options|MSG_EXT_PPR_PCOMP_EN);3693 if (transinfo->width == MSG_EXT_WDTR_BUS_8_BIT) {3694 maxsync = max(maxsync, (u_int)AHD_SYNCRATE_ULTRA2);3695 *ppr_options &= ~MSG_EXT_PPR_DT_REQ;3696 }3697 if (transinfo->period == 0) {3698 *period = 0;3699 *ppr_options = 0;3700 } else {3701 *period = max(*period, (u_int)transinfo->period);3702 ahd_find_syncrate(ahd, period, ppr_options, maxsync);3703 }3704}3705 3706/*3707 * Look up the valid period to SCSIRATE conversion in our table.3708 * Return the period and offset that should be sent to the target3709 * if this was the beginning of an SDTR.3710 */3711void3712ahd_find_syncrate(struct ahd_softc *ahd, u_int *period,3713 u_int *ppr_options, u_int maxsync)3714{3715 if (*period < maxsync)3716 *period = maxsync;3717 3718 if ((*ppr_options & MSG_EXT_PPR_DT_REQ) != 03719 && *period > AHD_SYNCRATE_MIN_DT)3720 *ppr_options &= ~MSG_EXT_PPR_DT_REQ;3721 3722 if (*period > AHD_SYNCRATE_MIN)3723 *period = 0;3724 3725 /* Honor PPR option conformance rules. */3726 if (*period > AHD_SYNCRATE_PACED)3727 *ppr_options &= ~MSG_EXT_PPR_RTI;3728 3729 if ((*ppr_options & MSG_EXT_PPR_IU_REQ) == 0)3730 *ppr_options &= (MSG_EXT_PPR_DT_REQ|MSG_EXT_PPR_QAS_REQ);3731 3732 if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0)3733 *ppr_options &= MSG_EXT_PPR_QAS_REQ;3734 3735 /* Skip all PACED only entries if IU is not available */3736 if ((*ppr_options & MSG_EXT_PPR_IU_REQ) == 03737 && *period < AHD_SYNCRATE_DT)3738 *period = AHD_SYNCRATE_DT;3739 3740 /* Skip all DT only entries if DT is not available */3741 if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 03742 && *period < AHD_SYNCRATE_ULTRA2)3743 *period = AHD_SYNCRATE_ULTRA2;3744}3745 3746/*3747 * Truncate the given synchronous offset to a value the3748 * current adapter type and syncrate are capable of.3749 */3750static void3751ahd_validate_offset(struct ahd_softc *ahd,3752 struct ahd_initiator_tinfo *tinfo,3753 u_int period, u_int *offset, int wide,3754 role_t role)3755{3756 u_int maxoffset;3757 3758 /* Limit offset to what we can do */3759 if (period == 0)3760 maxoffset = 0;3761 else if (period <= AHD_SYNCRATE_PACED) {3762 if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0)3763 maxoffset = MAX_OFFSET_PACED_BUG;3764 else3765 maxoffset = MAX_OFFSET_PACED;3766 } else3767 maxoffset = MAX_OFFSET_NON_PACED;3768 *offset = min(*offset, maxoffset);3769 if (tinfo != NULL) {3770 if (role == ROLE_TARGET)3771 *offset = min(*offset, (u_int)tinfo->user.offset);3772 else3773 *offset = min(*offset, (u_int)tinfo->goal.offset);3774 }3775}3776 3777/*3778 * Truncate the given transfer width parameter to a value the3779 * current adapter type is capable of.3780 */3781static void3782ahd_validate_width(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo,3783 u_int *bus_width, role_t role)3784{3785 switch (*bus_width) {3786 default:3787 if (ahd->features & AHD_WIDE) {3788 /* Respond Wide */3789 *bus_width = MSG_EXT_WDTR_BUS_16_BIT;3790 break;3791 }3792 fallthrough;3793 case MSG_EXT_WDTR_BUS_8_BIT:3794 *bus_width = MSG_EXT_WDTR_BUS_8_BIT;3795 break;3796 }3797 if (tinfo != NULL) {3798 if (role == ROLE_TARGET)3799 *bus_width = min((u_int)tinfo->user.width, *bus_width);3800 else3801 *bus_width = min((u_int)tinfo->goal.width, *bus_width);3802 }3803}3804 3805/*3806 * Update the bitmask of targets for which the controller should3807 * negotiate with at the next convenient opportunity. This currently3808 * means the next time we send the initial identify messages for3809 * a new transaction.3810 */3811int3812ahd_update_neg_request(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,3813 struct ahd_tmode_tstate *tstate,3814 struct ahd_initiator_tinfo *tinfo, ahd_neg_type neg_type)3815{3816 u_int auto_negotiate_orig;3817 3818 auto_negotiate_orig = tstate->auto_negotiate;3819 if (neg_type == AHD_NEG_ALWAYS) {3820 /*3821 * Force our "current" settings to be3822 * unknown so that unless a bus reset3823 * occurs the need to renegotiate is3824 * recorded persistently.3825 */3826 if ((ahd->features & AHD_WIDE) != 0)3827 tinfo->curr.width = AHD_WIDTH_UNKNOWN;3828 tinfo->curr.period = AHD_PERIOD_UNKNOWN;3829 tinfo->curr.offset = AHD_OFFSET_UNKNOWN;3830 }3831 if (tinfo->curr.period != tinfo->goal.period3832 || tinfo->curr.width != tinfo->goal.width3833 || tinfo->curr.offset != tinfo->goal.offset3834 || tinfo->curr.ppr_options != tinfo->goal.ppr_options3835 || (neg_type == AHD_NEG_IF_NON_ASYNC3836 && (tinfo->goal.offset != 03837 || tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT3838 || tinfo->goal.ppr_options != 0)))3839 tstate->auto_negotiate |= devinfo->target_mask;3840 else3841 tstate->auto_negotiate &= ~devinfo->target_mask;3842 3843 return (auto_negotiate_orig != tstate->auto_negotiate);3844}3845 3846/*3847 * Update the user/goal/curr tables of synchronous negotiation3848 * parameters as well as, in the case of a current or active update,3849 * any data structures on the host controller. In the case of an3850 * active update, the specified target is currently talking to us on3851 * the bus, so the transfer parameter update must take effect3852 * immediately.3853 */3854void3855ahd_set_syncrate(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,3856 u_int period, u_int offset, u_int ppr_options,3857 u_int type, int paused)3858{3859 struct ahd_initiator_tinfo *tinfo;3860 struct ahd_tmode_tstate *tstate;3861 u_int old_period;3862 u_int old_offset;3863 u_int old_ppr;3864 int active;3865 int update_needed;3866 3867 active = (type & AHD_TRANS_ACTIVE) == AHD_TRANS_ACTIVE;3868 update_needed = 0;3869 3870 if (period == 0 || offset == 0) {3871 period = 0;3872 offset = 0;3873 }3874 3875 tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,3876 devinfo->target, &tstate);3877 3878 if ((type & AHD_TRANS_USER) != 0) {3879 tinfo->user.period = period;3880 tinfo->user.offset = offset;3881 tinfo->user.ppr_options = ppr_options;3882 }3883 3884 if ((type & AHD_TRANS_GOAL) != 0) {3885 tinfo->goal.period = period;3886 tinfo->goal.offset = offset;3887 tinfo->goal.ppr_options = ppr_options;3888 }3889 3890 old_period = tinfo->curr.period;3891 old_offset = tinfo->curr.offset;3892 old_ppr = tinfo->curr.ppr_options;3893 3894 if ((type & AHD_TRANS_CUR) != 03895 && (old_period != period3896 || old_offset != offset3897 || old_ppr != ppr_options)) {3898 3899 update_needed++;3900 3901 tinfo->curr.period = period;3902 tinfo->curr.offset = offset;3903 tinfo->curr.ppr_options = ppr_options;3904 3905 ahd_send_async(ahd, devinfo->channel, devinfo->target,3906 CAM_LUN_WILDCARD, AC_TRANSFER_NEG);3907 if (bootverbose) {3908 if (offset != 0) {3909 int options;3910 3911 printk("%s: target %d synchronous with "3912 "period = 0x%x, offset = 0x%x",3913 ahd_name(ahd), devinfo->target,3914 period, offset);3915 options = 0;3916 if ((ppr_options & MSG_EXT_PPR_RD_STRM) != 0) {3917 printk("(RDSTRM");3918 options++;3919 }3920 if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) {3921 printk("%s", options ? "|DT" : "(DT");3922 options++;3923 }3924 if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {3925 printk("%s", options ? "|IU" : "(IU");3926 options++;3927 }3928 if ((ppr_options & MSG_EXT_PPR_RTI) != 0) {3929 printk("%s", options ? "|RTI" : "(RTI");3930 options++;3931 }3932 if ((ppr_options & MSG_EXT_PPR_QAS_REQ) != 0) {3933 printk("%s", options ? "|QAS" : "(QAS");3934 options++;3935 }3936 if (options != 0)3937 printk(")\n");3938 else3939 printk("\n");3940 } else {3941 printk("%s: target %d using "3942 "asynchronous transfers%s\n",3943 ahd_name(ahd), devinfo->target,3944 (ppr_options & MSG_EXT_PPR_QAS_REQ) != 03945 ? "(QAS)" : "");3946 }3947 }3948 }3949 /*3950 * Always refresh the neg-table to handle the case of the3951 * sequencer setting the ENATNO bit for a MK_MESSAGE request.3952 * We will always renegotiate in that case if this is a3953 * packetized request. Also manage the busfree expected flag3954 * from this common routine so that we catch changes due to3955 * WDTR or SDTR messages.3956 */3957 if ((type & AHD_TRANS_CUR) != 0) {3958 if (!paused)3959 ahd_pause(ahd);3960 ahd_update_neg_table(ahd, devinfo, &tinfo->curr);3961 if (!paused)3962 ahd_unpause(ahd);3963 if (ahd->msg_type != MSG_TYPE_NONE) {3964 if ((old_ppr & MSG_EXT_PPR_IU_REQ)3965 != (ppr_options & MSG_EXT_PPR_IU_REQ)) {3966#ifdef AHD_DEBUG3967 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {3968 ahd_print_devinfo(ahd, devinfo);3969 printk("Expecting IU Change busfree\n");3970 }3971#endif3972 ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE3973 | MSG_FLAG_IU_REQ_CHANGED;3974 }3975 if ((old_ppr & MSG_EXT_PPR_IU_REQ) != 0) {3976#ifdef AHD_DEBUG3977 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)3978 printk("PPR with IU_REQ outstanding\n");3979#endif3980 ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE;3981 }3982 }3983 }3984 3985 update_needed += ahd_update_neg_request(ahd, devinfo, tstate,3986 tinfo, AHD_NEG_TO_GOAL);3987 3988 if (update_needed && active)3989 ahd_update_pending_scbs(ahd);3990}3991 3992/*3993 * Update the user/goal/curr tables of wide negotiation3994 * parameters as well as, in the case of a current or active update,3995 * any data structures on the host controller. In the case of an3996 * active update, the specified target is currently talking to us on3997 * the bus, so the transfer parameter update must take effect3998 * immediately.3999 */4000void4001ahd_set_width(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,4002 u_int width, u_int type, int paused)4003{4004 struct ahd_initiator_tinfo *tinfo;4005 struct ahd_tmode_tstate *tstate;4006 u_int oldwidth;4007 int active;4008 int update_needed;4009 4010 active = (type & AHD_TRANS_ACTIVE) == AHD_TRANS_ACTIVE;4011 update_needed = 0;4012 tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,4013 devinfo->target, &tstate);4014 4015 if ((type & AHD_TRANS_USER) != 0)4016 tinfo->user.width = width;4017 4018 if ((type & AHD_TRANS_GOAL) != 0)4019 tinfo->goal.width = width;4020 4021 oldwidth = tinfo->curr.width;4022 if ((type & AHD_TRANS_CUR) != 0 && oldwidth != width) {4023 4024 update_needed++;4025 4026 tinfo->curr.width = width;4027 ahd_send_async(ahd, devinfo->channel, devinfo->target,4028 CAM_LUN_WILDCARD, AC_TRANSFER_NEG);4029 if (bootverbose) {4030 printk("%s: target %d using %dbit transfers\n",4031 ahd_name(ahd), devinfo->target,4032 8 * (0x01 << width));4033 }4034 }4035 4036 if ((type & AHD_TRANS_CUR) != 0) {4037 if (!paused)4038 ahd_pause(ahd);4039 ahd_update_neg_table(ahd, devinfo, &tinfo->curr);4040 if (!paused)4041 ahd_unpause(ahd);4042 }4043 4044 update_needed += ahd_update_neg_request(ahd, devinfo, tstate,4045 tinfo, AHD_NEG_TO_GOAL);4046 if (update_needed && active)4047 ahd_update_pending_scbs(ahd);4048 4049}4050 4051/*4052 * Update the current state of tagged queuing for a given target.4053 */4054static void4055ahd_set_tags(struct ahd_softc *ahd, struct scsi_cmnd *cmd,4056 struct ahd_devinfo *devinfo, ahd_queue_alg alg)4057{4058 struct scsi_device *sdev = cmd->device;4059 4060 ahd_platform_set_tags(ahd, sdev, devinfo, alg);4061 ahd_send_async(ahd, devinfo->channel, devinfo->target,4062 devinfo->lun, AC_TRANSFER_NEG);4063}4064 4065static void4066ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,4067 struct ahd_transinfo *tinfo)4068{4069 ahd_mode_state saved_modes;4070 u_int period;4071 u_int ppr_opts;4072 u_int con_opts;4073 u_int offset;4074 u_int saved_negoaddr;4075 uint8_t iocell_opts[sizeof(ahd->iocell_opts)];4076 4077 saved_modes = ahd_save_modes(ahd);4078 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);4079 4080 saved_negoaddr = ahd_inb(ahd, NEGOADDR);4081 ahd_outb(ahd, NEGOADDR, devinfo->target);4082 period = tinfo->period;4083 offset = tinfo->offset;4084 memcpy(iocell_opts, ahd->iocell_opts, sizeof(ahd->iocell_opts));4085 ppr_opts = tinfo->ppr_options & (MSG_EXT_PPR_QAS_REQ|MSG_EXT_PPR_DT_REQ4086 |MSG_EXT_PPR_IU_REQ|MSG_EXT_PPR_RTI);4087 con_opts = 0;4088 if (period == 0)4089 period = AHD_SYNCRATE_ASYNC;4090 if (period == AHD_SYNCRATE_160) {4091 4092 if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) {4093 /*4094 * When the SPI4 spec was finalized, PACE transfers4095 * was not made a configurable option in the PPR4096 * message. Instead it is assumed to be enabled for4097 * any syncrate faster than 80MHz. Nevertheless,4098 * Harpoon2A4 allows this to be configurable.4099 *4100 * Harpoon2A4 also assumes at most 2 data bytes per4101 * negotiated REQ/ACK offset. Paced transfers take4102 * 4, so we must adjust our offset.4103 */4104 ppr_opts |= PPROPT_PACE;4105 offset *= 2;4106 4107 /*4108 * Harpoon2A assumed that there would be a4109 * fallback rate between 160MHz and 80MHz,4110 * so 7 is used as the period factor rather4111 * than 8 for 160MHz.4112 */4113 period = AHD_SYNCRATE_REVA_160;4114 }4115 if ((tinfo->ppr_options & MSG_EXT_PPR_PCOMP_EN) == 0)4116 iocell_opts[AHD_PRECOMP_SLEW_INDEX] &=4117 ~AHD_PRECOMP_MASK;4118 } else {4119 /*4120 * Precomp should be disabled for non-paced transfers.4121 */4122 iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK;4123 4124 if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 04125 && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 04126 && (ppr_opts & MSG_EXT_PPR_IU_REQ) == 0) {4127 /*4128 * Slow down our CRC interval to be4129 * compatible with non-packetized4130 * U160 devices that can't handle a4131 * CRC at full speed.4132 */4133 con_opts |= ENSLOWCRC;4134 }4135 4136 if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) {4137 /*4138 * On H2A4, revert to a slower slewrate4139 * on non-paced transfers.4140 */4141 iocell_opts[AHD_PRECOMP_SLEW_INDEX] &=4142 ~AHD_SLEWRATE_MASK;4143 }4144 }4145 4146 ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW);4147 ahd_outb(ahd, ANNEXDAT, iocell_opts[AHD_PRECOMP_SLEW_INDEX]);4148 ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_AMPLITUDE);4149 ahd_outb(ahd, ANNEXDAT, iocell_opts[AHD_AMPLITUDE_INDEX]);4150 4151 ahd_outb(ahd, NEGPERIOD, period);4152 ahd_outb(ahd, NEGPPROPTS, ppr_opts);4153 ahd_outb(ahd, NEGOFFSET, offset);4154 4155 if (tinfo->width == MSG_EXT_WDTR_BUS_16_BIT)4156 con_opts |= WIDEXFER;4157 4158 /*4159 * Slow down our CRC interval to be4160 * compatible with packetized U320 devices4161 * that can't handle a CRC at full speed4162 */4163 if (ahd->features & AHD_AIC79XXB_SLOWCRC) {4164 con_opts |= ENSLOWCRC;4165 }4166 4167 /*4168 * During packetized transfers, the target will4169 * give us the opportunity to send command packets4170 * without us asserting attention.4171 */4172 if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ) == 0)4173 con_opts |= ENAUTOATNO;4174 ahd_outb(ahd, NEGCONOPTS, con_opts);4175 ahd_outb(ahd, NEGOADDR, saved_negoaddr);4176 ahd_restore_modes(ahd, saved_modes);4177}4178 4179/*4180 * When the transfer settings for a connection change, setup for4181 * negotiation in pending SCBs to effect the change as quickly as4182 * possible. We also cancel any negotiations that are scheduled4183 * for inflight SCBs that have not been started yet.4184 */4185static void4186ahd_update_pending_scbs(struct ahd_softc *ahd)4187{4188 struct scb *pending_scb;4189 int pending_scb_count;4190 int paused;4191 u_int saved_scbptr;4192 ahd_mode_state saved_modes;4193 4194 /*4195 * Traverse the pending SCB list and ensure that all of the4196 * SCBs there have the proper settings. We can only safely4197 * clear the negotiation required flag (setting requires the4198 * execution queue to be modified) and this is only possible4199 * if we are not already attempting to select out for this4200 * SCB. For this reason, all callers only call this routine4201 * if we are changing the negotiation settings for the currently4202 * active transaction on the bus.4203 */4204 pending_scb_count = 0;4205 LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {4206 struct ahd_devinfo devinfo;4207 struct ahd_tmode_tstate *tstate;4208 4209 ahd_scb_devinfo(ahd, &devinfo, pending_scb);4210 ahd_fetch_transinfo(ahd, devinfo.channel, devinfo.our_scsiid,4211 devinfo.target, &tstate);4212 if ((tstate->auto_negotiate & devinfo.target_mask) == 04213 && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) {4214 pending_scb->flags &= ~SCB_AUTO_NEGOTIATE;4215 pending_scb->hscb->control &= ~MK_MESSAGE;4216 }4217 ahd_sync_scb(ahd, pending_scb,4218 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);4219 pending_scb_count++;4220 }4221 4222 if (pending_scb_count == 0)4223 return;4224 4225 if (ahd_is_paused(ahd)) {4226 paused = 1;4227 } else {4228 paused = 0;4229 ahd_pause(ahd);4230 }4231 4232 /*4233 * Force the sequencer to reinitialize the selection for4234 * the command at the head of the execution queue if it4235 * has already been setup. The negotiation changes may4236 * effect whether we select-out with ATN. It is only4237 * safe to clear ENSELO when the bus is not free and no4238 * selection is in progres or completed.4239 */4240 saved_modes = ahd_save_modes(ahd);4241 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);4242 if ((ahd_inb(ahd, SCSISIGI) & BSYI) != 04243 && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0)4244 ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);4245 saved_scbptr = ahd_get_scbptr(ahd);4246 /* Ensure that the hscbs down on the card match the new information */4247 LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {4248 u_int scb_tag;4249 u_int control;4250 4251 scb_tag = SCB_GET_TAG(pending_scb);4252 ahd_set_scbptr(ahd, scb_tag);4253 control = ahd_inb_scbram(ahd, SCB_CONTROL);4254 control &= ~MK_MESSAGE;4255 control |= pending_scb->hscb->control & MK_MESSAGE;4256 ahd_outb(ahd, SCB_CONTROL, control);4257 }4258 ahd_set_scbptr(ahd, saved_scbptr);4259 ahd_restore_modes(ahd, saved_modes);4260 4261 if (paused == 0)4262 ahd_unpause(ahd);4263}4264 4265/**************************** Pathing Information *****************************/4266static void4267ahd_fetch_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)4268{4269 ahd_mode_state saved_modes;4270 u_int saved_scsiid;4271 role_t role;4272 int our_id;4273 4274 saved_modes = ahd_save_modes(ahd);4275 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);4276 4277 if (ahd_inb(ahd, SSTAT0) & TARGET)4278 role = ROLE_TARGET;4279 else4280 role = ROLE_INITIATOR;4281 4282 if (role == ROLE_TARGET4283 && (ahd_inb(ahd, SEQ_FLAGS) & CMDPHASE_PENDING) != 0) {4284 /* We were selected, so pull our id from TARGIDIN */4285 our_id = ahd_inb(ahd, TARGIDIN) & OID;4286 } else if (role == ROLE_TARGET)4287 our_id = ahd_inb(ahd, TOWNID);4288 else4289 our_id = ahd_inb(ahd, IOWNID);4290 4291 saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);4292 ahd_compile_devinfo(devinfo,4293 our_id,4294 SCSIID_TARGET(ahd, saved_scsiid),4295 ahd_inb(ahd, SAVED_LUN),4296 SCSIID_CHANNEL(ahd, saved_scsiid),4297 role);4298 ahd_restore_modes(ahd, saved_modes);4299}4300 4301void4302ahd_print_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)4303{4304 printk("%s:%c:%d:%d: ", ahd_name(ahd), 'A',4305 devinfo->target, devinfo->lun);4306}4307 4308static const struct ahd_phase_table_entry*4309ahd_lookup_phase_entry(int phase)4310{4311 const struct ahd_phase_table_entry *entry;4312 const struct ahd_phase_table_entry *last_entry;4313 4314 /*4315 * num_phases doesn't include the default entry which4316 * will be returned if the phase doesn't match.4317 */4318 last_entry = &ahd_phase_table[num_phases];4319 for (entry = ahd_phase_table; entry < last_entry; entry++) {4320 if (phase == entry->phase)4321 break;4322 }4323 return (entry);4324}4325 4326void4327ahd_compile_devinfo(struct ahd_devinfo *devinfo, u_int our_id, u_int target,4328 u_int lun, char channel, role_t role)4329{4330 devinfo->our_scsiid = our_id;4331 devinfo->target = target;4332 devinfo->lun = lun;4333 devinfo->target_offset = target;4334 devinfo->channel = channel;4335 devinfo->role = role;4336 if (channel == 'B')4337 devinfo->target_offset += 8;4338 devinfo->target_mask = (0x01 << devinfo->target_offset);4339}4340 4341static void4342ahd_scb_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,4343 struct scb *scb)4344{4345 role_t role;4346 int our_id;4347 4348 our_id = SCSIID_OUR_ID(scb->hscb->scsiid);4349 role = ROLE_INITIATOR;4350 if ((scb->hscb->control & TARGET_SCB) != 0)4351 role = ROLE_TARGET;4352 ahd_compile_devinfo(devinfo, our_id, SCB_GET_TARGET(ahd, scb),4353 SCB_GET_LUN(scb), SCB_GET_CHANNEL(ahd, scb), role);4354}4355 4356 4357/************************ Message Phase Processing ****************************/4358/*4359 * When an initiator transaction with the MK_MESSAGE flag either reconnects4360 * or enters the initial message out phase, we are interrupted. Fill our4361 * outgoing message buffer with the appropriate message and beging handing4362 * the message phase(s) manually.4363 */4364static void4365ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,4366 struct scb *scb)4367{4368 /*4369 * To facilitate adding multiple messages together,4370 * each routine should increment the index and len4371 * variables instead of setting them explicitly.4372 */4373 ahd->msgout_index = 0;4374 ahd->msgout_len = 0;4375 4376 if (ahd_currently_packetized(ahd))4377 ahd->msg_flags |= MSG_FLAG_PACKETIZED;4378 4379 if (ahd->send_msg_perror4380 && ahd_inb(ahd, MSG_OUT) == HOST_MSG) {4381 ahd->msgout_buf[ahd->msgout_index++] = ahd->send_msg_perror;4382 ahd->msgout_len++;4383 ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;4384#ifdef AHD_DEBUG4385 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)4386 printk("Setting up for Parity Error delivery\n");4387#endif4388 return;4389 } else if (scb == NULL) {4390 printk("%s: WARNING. No pending message for "4391 "I_T msgin. Issuing NO-OP\n", ahd_name(ahd));4392 ahd->msgout_buf[ahd->msgout_index++] = NOP;4393 ahd->msgout_len++;4394 ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;4395 return;4396 }4397 4398 if ((scb->flags & SCB_DEVICE_RESET) == 04399 && (scb->flags & SCB_PACKETIZED) == 04400 && ahd_inb(ahd, MSG_OUT) == MSG_IDENTIFYFLAG) {4401 u_int identify_msg;4402 4403 identify_msg = MSG_IDENTIFYFLAG | SCB_GET_LUN(scb);4404 if ((scb->hscb->control & DISCENB) != 0)4405 identify_msg |= MSG_IDENTIFY_DISCFLAG;4406 ahd->msgout_buf[ahd->msgout_index++] = identify_msg;4407 ahd->msgout_len++;4408 4409 if ((scb->hscb->control & TAG_ENB) != 0) {4410 ahd->msgout_buf[ahd->msgout_index++] =4411 scb->hscb->control & (TAG_ENB|SCB_TAG_TYPE);4412 ahd->msgout_buf[ahd->msgout_index++] = SCB_GET_TAG(scb);4413 ahd->msgout_len += 2;4414 }4415 }4416 4417 if (scb->flags & SCB_DEVICE_RESET) {4418 ahd->msgout_buf[ahd->msgout_index++] = TARGET_RESET;4419 ahd->msgout_len++;4420 ahd_print_path(ahd, scb);4421 printk("Bus Device Reset Message Sent\n");4422 /*4423 * Clear our selection hardware in advance of4424 * the busfree. We may have an entry in the waiting4425 * Q for this target, and we don't want to go about4426 * selecting while we handle the busfree and blow it4427 * away.4428 */4429 ahd_outb(ahd, SCSISEQ0, 0);4430 } else if ((scb->flags & SCB_ABORT) != 0) {4431 4432 if ((scb->hscb->control & TAG_ENB) != 0) {4433 ahd->msgout_buf[ahd->msgout_index++] = ABORT_TASK;4434 } else {4435 ahd->msgout_buf[ahd->msgout_index++] = ABORT_TASK_SET;4436 }4437 ahd->msgout_len++;4438 ahd_print_path(ahd, scb);4439 printk("Abort%s Message Sent\n",4440 (scb->hscb->control & TAG_ENB) != 0 ? " Tag" : "");4441 /*4442 * Clear our selection hardware in advance of4443 * the busfree. We may have an entry in the waiting4444 * Q for this target, and we don't want to go about4445 * selecting while we handle the busfree and blow it4446 * away.4447 */4448 ahd_outb(ahd, SCSISEQ0, 0);4449 } else if ((scb->flags & (SCB_AUTO_NEGOTIATE|SCB_NEGOTIATE)) != 0) {4450 ahd_build_transfer_msg(ahd, devinfo);4451 /*4452 * Clear our selection hardware in advance of potential4453 * PPR IU status change busfree. We may have an entry in4454 * the waiting Q for this target, and we don't want to go4455 * about selecting while we handle the busfree and blow4456 * it away.4457 */4458 ahd_outb(ahd, SCSISEQ0, 0);4459 } else {4460 printk("ahd_intr: AWAITING_MSG for an SCB that "4461 "does not have a waiting message\n");4462 printk("SCSIID = %x, target_mask = %x\n", scb->hscb->scsiid,4463 devinfo->target_mask);4464 panic("SCB = %d, SCB Control = %x:%x, MSG_OUT = %x "4465 "SCB flags = %x", SCB_GET_TAG(scb), scb->hscb->control,4466 ahd_inb_scbram(ahd, SCB_CONTROL), ahd_inb(ahd, MSG_OUT),4467 scb->flags);4468 }4469 4470 /*4471 * Clear the MK_MESSAGE flag from the SCB so we aren't4472 * asked to send this message again.4473 */4474 ahd_outb(ahd, SCB_CONTROL,4475 ahd_inb_scbram(ahd, SCB_CONTROL) & ~MK_MESSAGE);4476 scb->hscb->control &= ~MK_MESSAGE;4477 ahd->msgout_index = 0;4478 ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;4479}4480 4481/*4482 * Build an appropriate transfer negotiation message for the4483 * currently active target.4484 */4485static void4486ahd_build_transfer_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)4487{4488 /*4489 * We need to initiate transfer negotiations.4490 * If our current and goal settings are identical,4491 * we want to renegotiate due to a check condition.4492 */4493 struct ahd_initiator_tinfo *tinfo;4494 struct ahd_tmode_tstate *tstate;4495 int dowide;4496 int dosync;4497 int doppr;4498 u_int period;4499 u_int ppr_options;4500 u_int offset;4501 4502 tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,4503 devinfo->target, &tstate);4504 /*4505 * Filter our period based on the current connection.4506 * If we can't perform DT transfers on this segment (not in LVD4507 * mode for instance), then our decision to issue a PPR message4508 * may change.4509 */4510 period = tinfo->goal.period;4511 offset = tinfo->goal.offset;4512 ppr_options = tinfo->goal.ppr_options;4513 /* Target initiated PPR is not allowed in the SCSI spec */4514 if (devinfo->role == ROLE_TARGET)4515 ppr_options = 0;4516 ahd_devlimited_syncrate(ahd, tinfo, &period,4517 &ppr_options, devinfo->role);4518 dowide = tinfo->curr.width != tinfo->goal.width;4519 dosync = tinfo->curr.offset != offset || tinfo->curr.period != period;4520 /*4521 * Only use PPR if we have options that need it, even if the device4522 * claims to support it. There might be an expander in the way4523 * that doesn't.4524 */4525 doppr = ppr_options != 0;4526 4527 if (!dowide && !dosync && !doppr) {4528 dowide = tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT;4529 dosync = tinfo->goal.offset != 0;4530 }4531 4532 if (!dowide && !dosync && !doppr) {4533 /*4534 * Force async with a WDTR message if we have a wide bus,4535 * or just issue an SDTR with a 0 offset.4536 */4537 if ((ahd->features & AHD_WIDE) != 0)4538 dowide = 1;4539 else4540 dosync = 1;4541 4542 if (bootverbose) {4543 ahd_print_devinfo(ahd, devinfo);4544 printk("Ensuring async\n");4545 }4546 }4547 /* Target initiated PPR is not allowed in the SCSI spec */4548 if (devinfo->role == ROLE_TARGET)4549 doppr = 0;4550 4551 /*4552 * Both the PPR message and SDTR message require the4553 * goal syncrate to be limited to what the target device4554 * is capable of handling (based on whether an LVD->SE4555 * expander is on the bus), so combine these two cases.4556 * Regardless, guarantee that if we are using WDTR and SDTR4557 * messages that WDTR comes first.4558 */4559 if (doppr || (dosync && !dowide)) {4560 4561 offset = tinfo->goal.offset;4562 ahd_validate_offset(ahd, tinfo, period, &offset,4563 doppr ? tinfo->goal.width4564 : tinfo->curr.width,4565 devinfo->role);4566 if (doppr) {4567 ahd_construct_ppr(ahd, devinfo, period, offset,4568 tinfo->goal.width, ppr_options);4569 } else {4570 ahd_construct_sdtr(ahd, devinfo, period, offset);4571 }4572 } else {4573 ahd_construct_wdtr(ahd, devinfo, tinfo->goal.width);4574 }4575}4576 4577/*4578 * Build a synchronous negotiation message in our message4579 * buffer based on the input parameters.4580 */4581static void4582ahd_construct_sdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,4583 u_int period, u_int offset)4584{4585 if (offset == 0)4586 period = AHD_ASYNC_XFER_PERIOD;4587 ahd->msgout_index += spi_populate_sync_msg(4588 ahd->msgout_buf + ahd->msgout_index, period, offset);4589 ahd->msgout_len += 5;4590 if (bootverbose) {4591 printk("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n",4592 ahd_name(ahd), devinfo->channel, devinfo->target,4593 devinfo->lun, period, offset);4594 }4595}4596 4597/*4598 * Build a wide negotiateion message in our message4599 * buffer based on the input parameters.4600 */4601static void4602ahd_construct_wdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,4603 u_int bus_width)4604{4605 ahd->msgout_index += spi_populate_width_msg(4606 ahd->msgout_buf + ahd->msgout_index, bus_width);4607 ahd->msgout_len += 4;4608 if (bootverbose) {4609 printk("(%s:%c:%d:%d): Sending WDTR %x\n",4610 ahd_name(ahd), devinfo->channel, devinfo->target,4611 devinfo->lun, bus_width);4612 }4613}4614 4615/*4616 * Build a parallel protocol request message in our message4617 * buffer based on the input parameters.4618 */4619static void4620ahd_construct_ppr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,4621 u_int period, u_int offset, u_int bus_width,4622 u_int ppr_options)4623{4624 /*4625 * Always request precompensation from4626 * the other target if we are running4627 * at paced syncrates.4628 */4629 if (period <= AHD_SYNCRATE_PACED)4630 ppr_options |= MSG_EXT_PPR_PCOMP_EN;4631 if (offset == 0)4632 period = AHD_ASYNC_XFER_PERIOD;4633 ahd->msgout_index += spi_populate_ppr_msg(4634 ahd->msgout_buf + ahd->msgout_index, period, offset,4635 bus_width, ppr_options);4636 ahd->msgout_len += 8;4637 if (bootverbose) {4638 printk("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, "4639 "offset %x, ppr_options %x\n", ahd_name(ahd),4640 devinfo->channel, devinfo->target, devinfo->lun,4641 bus_width, period, offset, ppr_options);4642 }4643}4644 4645/*4646 * Clear any active message state.4647 */4648static void4649ahd_clear_msg_state(struct ahd_softc *ahd)4650{4651 ahd_mode_state saved_modes;4652 4653 saved_modes = ahd_save_modes(ahd);4654 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);4655 ahd->send_msg_perror = 0;4656 ahd->msg_flags = MSG_FLAG_NONE;4657 ahd->msgout_len = 0;4658 ahd->msgin_index = 0;4659 ahd->msg_type = MSG_TYPE_NONE;4660 if ((ahd_inb(ahd, SCSISIGO) & ATNO) != 0) {4661 /*4662 * The target didn't care to respond to our4663 * message request, so clear ATN.4664 */4665 ahd_outb(ahd, CLRSINT1, CLRATNO);4666 }4667 ahd_outb(ahd, MSG_OUT, NOP);4668 ahd_outb(ahd, SEQ_FLAGS2,4669 ahd_inb(ahd, SEQ_FLAGS2) & ~TARGET_MSG_PENDING);4670 ahd_restore_modes(ahd, saved_modes);4671}4672 4673/*4674 * Manual message loop handler.4675 */4676static void4677ahd_handle_message_phase(struct ahd_softc *ahd)4678{4679 struct ahd_devinfo devinfo;4680 u_int bus_phase;4681 int end_session;4682 4683 ahd_fetch_devinfo(ahd, &devinfo);4684 end_session = FALSE;4685 bus_phase = ahd_inb(ahd, LASTPHASE);4686 4687 if ((ahd_inb(ahd, LQISTAT2) & LQIPHASE_OUTPKT) != 0) {4688 printk("LQIRETRY for LQIPHASE_OUTPKT\n");4689 ahd_outb(ahd, LQCTL2, LQIRETRY);4690 }4691reswitch:4692 switch (ahd->msg_type) {4693 case MSG_TYPE_INITIATOR_MSGOUT:4694 {4695 int lastbyte;4696 int phasemis;4697 int msgdone;4698 4699 if (ahd->msgout_len == 0 && ahd->send_msg_perror == 0)4700 panic("HOST_MSG_LOOP interrupt with no active message");4701 4702#ifdef AHD_DEBUG4703 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {4704 ahd_print_devinfo(ahd, &devinfo);4705 printk("INITIATOR_MSG_OUT");4706 }4707#endif4708 phasemis = bus_phase != P_MESGOUT;4709 if (phasemis) {4710#ifdef AHD_DEBUG4711 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {4712 printk(" PHASEMIS %s\n",4713 ahd_lookup_phase_entry(bus_phase)4714 ->phasemsg);4715 }4716#endif4717 if (bus_phase == P_MESGIN) {4718 /*4719 * Change gears and see if4720 * this messages is of interest to4721 * us or should be passed back to4722 * the sequencer.4723 */4724 ahd_outb(ahd, CLRSINT1, CLRATNO);4725 ahd->send_msg_perror = 0;4726 ahd->msg_type = MSG_TYPE_INITIATOR_MSGIN;4727 ahd->msgin_index = 0;4728 goto reswitch;4729 }4730 end_session = TRUE;4731 break;4732 }4733 4734 if (ahd->send_msg_perror) {4735 ahd_outb(ahd, CLRSINT1, CLRATNO);4736 ahd_outb(ahd, CLRSINT1, CLRREQINIT);4737#ifdef AHD_DEBUG4738 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)4739 printk(" byte 0x%x\n", ahd->send_msg_perror);4740#endif4741 /*4742 * If we are notifying the target of a CRC error4743 * during packetized operations, the target is4744 * within its rights to acknowledge our message4745 * with a busfree.4746 */4747 if ((ahd->msg_flags & MSG_FLAG_PACKETIZED) != 04748 && ahd->send_msg_perror == INITIATOR_ERROR)4749 ahd->msg_flags |= MSG_FLAG_EXPECT_IDE_BUSFREE;4750 4751 ahd_outb(ahd, RETURN_2, ahd->send_msg_perror);4752 ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_WRITE);4753 break;4754 }4755 4756 msgdone = ahd->msgout_index == ahd->msgout_len;4757 if (msgdone) {4758 /*4759 * The target has requested a retry.4760 * Re-assert ATN, reset our message index to4761 * 0, and try again.4762 */4763 ahd->msgout_index = 0;4764 ahd_assert_atn(ahd);4765 }4766 4767 lastbyte = ahd->msgout_index == (ahd->msgout_len - 1);4768 if (lastbyte) {4769 /* Last byte is signified by dropping ATN */4770 ahd_outb(ahd, CLRSINT1, CLRATNO);4771 }4772 4773 /*4774 * Clear our interrupt status and present4775 * the next byte on the bus.4776 */4777 ahd_outb(ahd, CLRSINT1, CLRREQINIT);4778#ifdef AHD_DEBUG4779 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)4780 printk(" byte 0x%x\n",4781 ahd->msgout_buf[ahd->msgout_index]);4782#endif4783 ahd_outb(ahd, RETURN_2, ahd->msgout_buf[ahd->msgout_index++]);4784 ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_WRITE);4785 break;4786 }4787 case MSG_TYPE_INITIATOR_MSGIN:4788 {4789 int phasemis;4790 int message_done;4791 4792#ifdef AHD_DEBUG4793 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {4794 ahd_print_devinfo(ahd, &devinfo);4795 printk("INITIATOR_MSG_IN");4796 }4797#endif4798 phasemis = bus_phase != P_MESGIN;4799 if (phasemis) {4800#ifdef AHD_DEBUG4801 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {4802 printk(" PHASEMIS %s\n",4803 ahd_lookup_phase_entry(bus_phase)4804 ->phasemsg);4805 }4806#endif4807 ahd->msgin_index = 0;4808 if (bus_phase == P_MESGOUT4809 && (ahd->send_msg_perror != 04810 || (ahd->msgout_len != 04811 && ahd->msgout_index == 0))) {4812 ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;4813 goto reswitch;4814 }4815 end_session = TRUE;4816 break;4817 }4818 4819 /* Pull the byte in without acking it */4820 ahd->msgin_buf[ahd->msgin_index] = ahd_inb(ahd, SCSIBUS);4821#ifdef AHD_DEBUG4822 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)4823 printk(" byte 0x%x\n",4824 ahd->msgin_buf[ahd->msgin_index]);4825#endif4826 4827 message_done = ahd_parse_msg(ahd, &devinfo);4828 4829 if (message_done) {4830 /*4831 * Clear our incoming message buffer in case there4832 * is another message following this one.4833 */4834 ahd->msgin_index = 0;4835 4836 /*4837 * If this message illicited a response,4838 * assert ATN so the target takes us to the4839 * message out phase.4840 */4841 if (ahd->msgout_len != 0) {4842#ifdef AHD_DEBUG4843 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) {4844 ahd_print_devinfo(ahd, &devinfo);4845 printk("Asserting ATN for response\n");4846 }4847#endif4848 ahd_assert_atn(ahd);4849 }4850 } else4851 ahd->msgin_index++;4852 4853 if (message_done == MSGLOOP_TERMINATED) {4854 end_session = TRUE;4855 } else {4856 /* Ack the byte */4857 ahd_outb(ahd, CLRSINT1, CLRREQINIT);4858 ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_READ);4859 }4860 break;4861 }4862 case MSG_TYPE_TARGET_MSGIN:4863 {4864 int msgdone;4865 int msgout_request;4866 4867 /*4868 * By default, the message loop will continue.4869 */4870 ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);4871 4872 if (ahd->msgout_len == 0)4873 panic("Target MSGIN with no active message");4874 4875 /*4876 * If we interrupted a mesgout session, the initiator4877 * will not know this until our first REQ. So, we4878 * only honor mesgout requests after we've sent our4879 * first byte.4880 */4881 if ((ahd_inb(ahd, SCSISIGI) & ATNI) != 04882 && ahd->msgout_index > 0)4883 msgout_request = TRUE;4884 else4885 msgout_request = FALSE;4886 4887 if (msgout_request) {4888 4889 /*4890 * Change gears and see if4891 * this messages is of interest to4892 * us or should be passed back to4893 * the sequencer.4894 */4895 ahd->msg_type = MSG_TYPE_TARGET_MSGOUT;4896 ahd_outb(ahd, SCSISIGO, P_MESGOUT | BSYO);4897 ahd->msgin_index = 0;4898 /* Dummy read to REQ for first byte */4899 ahd_inb(ahd, SCSIDAT);4900 ahd_outb(ahd, SXFRCTL0,4901 ahd_inb(ahd, SXFRCTL0) | SPIOEN);4902 break;4903 }4904 4905 msgdone = ahd->msgout_index == ahd->msgout_len;4906 if (msgdone) {4907 ahd_outb(ahd, SXFRCTL0,4908 ahd_inb(ahd, SXFRCTL0) & ~SPIOEN);4909 end_session = TRUE;4910 break;4911 }4912 4913 /*4914 * Present the next byte on the bus.4915 */4916 ahd_outb(ahd, SXFRCTL0, ahd_inb(ahd, SXFRCTL0) | SPIOEN);4917 ahd_outb(ahd, SCSIDAT, ahd->msgout_buf[ahd->msgout_index++]);4918 break;4919 }4920 case MSG_TYPE_TARGET_MSGOUT:4921 {4922 int lastbyte;4923 int msgdone;4924 4925 /*4926 * By default, the message loop will continue.4927 */4928 ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);4929 4930 /*4931 * The initiator signals that this is4932 * the last byte by dropping ATN.4933 */4934 lastbyte = (ahd_inb(ahd, SCSISIGI) & ATNI) == 0;4935 4936 /*4937 * Read the latched byte, but turn off SPIOEN first4938 * so that we don't inadvertently cause a REQ for the4939 * next byte.4940 */4941 ahd_outb(ahd, SXFRCTL0, ahd_inb(ahd, SXFRCTL0) & ~SPIOEN);4942 ahd->msgin_buf[ahd->msgin_index] = ahd_inb(ahd, SCSIDAT);4943 msgdone = ahd_parse_msg(ahd, &devinfo);4944 if (msgdone == MSGLOOP_TERMINATED) {4945 /*4946 * The message is *really* done in that it caused4947 * us to go to bus free. The sequencer has already4948 * been reset at this point, so pull the ejection4949 * handle.4950 */4951 return;4952 }4953 4954 ahd->msgin_index++;4955 4956 /*4957 * XXX Read spec about initiator dropping ATN too soon4958 * and use msgdone to detect it.4959 */4960 if (msgdone == MSGLOOP_MSGCOMPLETE) {4961 ahd->msgin_index = 0;4962 4963 /*4964 * If this message illicited a response, transition4965 * to the Message in phase and send it.4966 */4967 if (ahd->msgout_len != 0) {4968 ahd_outb(ahd, SCSISIGO, P_MESGIN | BSYO);4969 ahd_outb(ahd, SXFRCTL0,4970 ahd_inb(ahd, SXFRCTL0) | SPIOEN);4971 ahd->msg_type = MSG_TYPE_TARGET_MSGIN;4972 ahd->msgin_index = 0;4973 break;4974 }4975 }4976 4977 if (lastbyte)4978 end_session = TRUE;4979 else {4980 /* Ask for the next byte. */4981 ahd_outb(ahd, SXFRCTL0,4982 ahd_inb(ahd, SXFRCTL0) | SPIOEN);4983 }4984 4985 break;4986 }4987 default:4988 panic("Unknown REQINIT message type");4989 }4990 4991 if (end_session) {4992 if ((ahd->msg_flags & MSG_FLAG_PACKETIZED) != 0) {4993 printk("%s: Returning to Idle Loop\n",4994 ahd_name(ahd));4995 ahd_clear_msg_state(ahd);4996 4997 /*4998 * Perform the equivalent of a clear_target_state.4999 */5000 ahd_outb(ahd, LASTPHASE, P_BUSFREE);5001 ahd_outb(ahd, SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT);5002 ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);5003 } else {5004 ahd_clear_msg_state(ahd);5005 ahd_outb(ahd, RETURN_1, EXIT_MSG_LOOP);5006 }5007 }5008}5009 5010/*5011 * See if we sent a particular extended message to the target.5012 * If "full" is true, return true only if the target saw the full5013 * message. If "full" is false, return true if the target saw at5014 * least the first byte of the message.5015 */5016static int5017ahd_sent_msg(struct ahd_softc *ahd, ahd_msgtype type, u_int msgval, int full)5018{5019 int found;5020 u_int index;5021 5022 found = FALSE;5023 index = 0;5024 5025 while (index < ahd->msgout_len) {5026 if (ahd->msgout_buf[index] == EXTENDED_MESSAGE) {5027 u_int end_index;5028 5029 end_index = index + 1 + ahd->msgout_buf[index + 1];5030 if (ahd->msgout_buf[index+2] == msgval5031 && type == AHDMSG_EXT) {5032 5033 if (full) {5034 if (ahd->msgout_index > end_index)5035 found = TRUE;5036 } else if (ahd->msgout_index > index)5037 found = TRUE;5038 }5039 index = end_index;5040 } else if (ahd->msgout_buf[index] >= SIMPLE_QUEUE_TAG5041 && ahd->msgout_buf[index] <= IGNORE_WIDE_RESIDUE) {5042 5043 /* Skip tag type and tag id or residue param*/5044 index += 2;5045 } else {5046 /* Single byte message */5047 if (type == AHDMSG_1B5048 && ahd->msgout_index > index5049 && (ahd->msgout_buf[index] == msgval5050 || ((ahd->msgout_buf[index] & MSG_IDENTIFYFLAG) != 05051 && msgval == MSG_IDENTIFYFLAG)))5052 found = TRUE;5053 index++;5054 }5055 5056 if (found)5057 break;5058 }5059 return (found);5060}5061 5062/*5063 * Wait for a complete incoming message, parse it, and respond accordingly.5064 */5065static int5066ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)5067{5068 struct ahd_initiator_tinfo *tinfo;5069 struct ahd_tmode_tstate *tstate;5070 int reject;5071 int done;5072 int response;5073 5074 done = MSGLOOP_IN_PROG;5075 response = FALSE;5076 reject = FALSE;5077 tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,5078 devinfo->target, &tstate);5079 5080 /*5081 * Parse as much of the message as is available,5082 * rejecting it if we don't support it. When5083 * the entire message is available and has been5084 * handled, return MSGLOOP_MSGCOMPLETE, indicating5085 * that we have parsed an entire message.5086 *5087 * In the case of extended messages, we accept the length5088 * byte outright and perform more checking once we know the5089 * extended message type.5090 */5091 switch (ahd->msgin_buf[0]) {5092 case DISCONNECT:5093 case SAVE_POINTERS:5094 case COMMAND_COMPLETE:5095 case RESTORE_POINTERS:5096 case IGNORE_WIDE_RESIDUE:5097 /*5098 * End our message loop as these are messages5099 * the sequencer handles on its own.5100 */5101 done = MSGLOOP_TERMINATED;5102 break;5103 case MESSAGE_REJECT:5104 response = ahd_handle_msg_reject(ahd, devinfo);5105 fallthrough;5106 case NOP:5107 done = MSGLOOP_MSGCOMPLETE;5108 break;5109 case EXTENDED_MESSAGE:5110 {5111 /* Wait for enough of the message to begin validation */5112 if (ahd->msgin_index < 2)5113 break;5114 switch (ahd->msgin_buf[2]) {5115 case EXTENDED_SDTR:5116 {5117 u_int period;5118 u_int ppr_options;5119 u_int offset;5120 u_int saved_offset;5121 5122 if (ahd->msgin_buf[1] != MSG_EXT_SDTR_LEN) {5123 reject = TRUE;5124 break;5125 }5126 5127 /*5128 * Wait until we have both args before validating5129 * and acting on this message.5130 *5131 * Add one to MSG_EXT_SDTR_LEN to account for5132 * the extended message preamble.5133 */5134 if (ahd->msgin_index < (MSG_EXT_SDTR_LEN + 1))5135 break;5136 5137 period = ahd->msgin_buf[3];5138 ppr_options = 0;5139 saved_offset = offset = ahd->msgin_buf[4];5140 ahd_devlimited_syncrate(ahd, tinfo, &period,5141 &ppr_options, devinfo->role);5142 ahd_validate_offset(ahd, tinfo, period, &offset,5143 tinfo->curr.width, devinfo->role);5144 if (bootverbose) {5145 printk("(%s:%c:%d:%d): Received "5146 "SDTR period %x, offset %x\n\t"5147 "Filtered to period %x, offset %x\n",5148 ahd_name(ahd), devinfo->channel,5149 devinfo->target, devinfo->lun,5150 ahd->msgin_buf[3], saved_offset,5151 period, offset);5152 }5153 ahd_set_syncrate(ahd, devinfo, period,5154 offset, ppr_options,5155 AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,5156 /*paused*/TRUE);5157 5158 /*5159 * See if we initiated Sync Negotiation5160 * and didn't have to fall down to async5161 * transfers.5162 */5163 if (ahd_sent_msg(ahd, AHDMSG_EXT, EXTENDED_SDTR, TRUE)) {5164 /* We started it */5165 if (saved_offset != offset) {5166 /* Went too low - force async */5167 reject = TRUE;5168 }5169 } else {5170 /*5171 * Send our own SDTR in reply5172 */5173 if (bootverbose5174 && devinfo->role == ROLE_INITIATOR) {5175 printk("(%s:%c:%d:%d): Target "5176 "Initiated SDTR\n",5177 ahd_name(ahd), devinfo->channel,5178 devinfo->target, devinfo->lun);5179 }5180 ahd->msgout_index = 0;5181 ahd->msgout_len = 0;5182 ahd_construct_sdtr(ahd, devinfo,5183 period, offset);5184 ahd->msgout_index = 0;5185 response = TRUE;5186 }5187 done = MSGLOOP_MSGCOMPLETE;5188 break;5189 }5190 case EXTENDED_WDTR:5191 {5192 u_int bus_width;5193 u_int saved_width;5194 u_int sending_reply;5195 5196 sending_reply = FALSE;5197 if (ahd->msgin_buf[1] != MSG_EXT_WDTR_LEN) {5198 reject = TRUE;5199 break;5200 }5201 5202 /*5203 * Wait until we have our arg before validating5204 * and acting on this message.5205 *5206 * Add one to MSG_EXT_WDTR_LEN to account for5207 * the extended message preamble.5208 */5209 if (ahd->msgin_index < (MSG_EXT_WDTR_LEN + 1))5210 break;5211 5212 bus_width = ahd->msgin_buf[3];5213 saved_width = bus_width;5214 ahd_validate_width(ahd, tinfo, &bus_width,5215 devinfo->role);5216 if (bootverbose) {5217 printk("(%s:%c:%d:%d): Received WDTR "5218 "%x filtered to %x\n",5219 ahd_name(ahd), devinfo->channel,5220 devinfo->target, devinfo->lun,5221 saved_width, bus_width);5222 }5223 5224 if (ahd_sent_msg(ahd, AHDMSG_EXT, EXTENDED_WDTR, TRUE)) {5225 /*5226 * Don't send a WDTR back to the5227 * target, since we asked first.5228 * If the width went higher than our5229 * request, reject it.5230 */5231 if (saved_width > bus_width) {5232 reject = TRUE;5233 printk("(%s:%c:%d:%d): requested %dBit "5234 "transfers. Rejecting...\n",5235 ahd_name(ahd), devinfo->channel,5236 devinfo->target, devinfo->lun,5237 8 * (0x01 << bus_width));5238 bus_width = 0;5239 }5240 } else {5241 /*5242 * Send our own WDTR in reply5243 */5244 if (bootverbose5245 && devinfo->role == ROLE_INITIATOR) {5246 printk("(%s:%c:%d:%d): Target "5247 "Initiated WDTR\n",5248 ahd_name(ahd), devinfo->channel,5249 devinfo->target, devinfo->lun);5250 }5251 ahd->msgout_index = 0;5252 ahd->msgout_len = 0;5253 ahd_construct_wdtr(ahd, devinfo, bus_width);5254 ahd->msgout_index = 0;5255 response = TRUE;5256 sending_reply = TRUE;5257 }5258 /*5259 * After a wide message, we are async, but5260 * some devices don't seem to honor this portion5261 * of the spec. Force a renegotiation of the5262 * sync component of our transfer agreement even5263 * if our goal is async. By updating our width5264 * after forcing the negotiation, we avoid5265 * renegotiating for width.5266 */5267 ahd_update_neg_request(ahd, devinfo, tstate,5268 tinfo, AHD_NEG_ALWAYS);5269 ahd_set_width(ahd, devinfo, bus_width,5270 AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,5271 /*paused*/TRUE);5272 if (sending_reply == FALSE && reject == FALSE) {5273 5274 /*5275 * We will always have an SDTR to send.5276 */5277 ahd->msgout_index = 0;5278 ahd->msgout_len = 0;5279 ahd_build_transfer_msg(ahd, devinfo);5280 ahd->msgout_index = 0;5281 response = TRUE;5282 }5283 done = MSGLOOP_MSGCOMPLETE;5284 break;5285 }5286 case EXTENDED_PPR:5287 {5288 u_int period;5289 u_int offset;5290 u_int bus_width;5291 u_int ppr_options;5292 u_int saved_width;5293 u_int saved_offset;5294 u_int saved_ppr_options;5295 5296 if (ahd->msgin_buf[1] != MSG_EXT_PPR_LEN) {5297 reject = TRUE;5298 break;5299 }5300 5301 /*5302 * Wait until we have all args before validating5303 * and acting on this message.5304 *5305 * Add one to MSG_EXT_PPR_LEN to account for5306 * the extended message preamble.5307 */5308 if (ahd->msgin_index < (MSG_EXT_PPR_LEN + 1))5309 break;5310 5311 period = ahd->msgin_buf[3];5312 offset = ahd->msgin_buf[5];5313 bus_width = ahd->msgin_buf[6];5314 saved_width = bus_width;5315 ppr_options = ahd->msgin_buf[7];5316 /*5317 * According to the spec, a DT only5318 * period factor with no DT option5319 * set implies async.5320 */5321 if ((ppr_options & MSG_EXT_PPR_DT_REQ) == 05322 && period <= 9)5323 offset = 0;5324 saved_ppr_options = ppr_options;5325 saved_offset = offset;5326 5327 /*5328 * Transfer options are only available if we5329 * are negotiating wide.5330 */5331 if (bus_width == 0)5332 ppr_options &= MSG_EXT_PPR_QAS_REQ;5333 5334 ahd_validate_width(ahd, tinfo, &bus_width,5335 devinfo->role);5336 ahd_devlimited_syncrate(ahd, tinfo, &period,5337 &ppr_options, devinfo->role);5338 ahd_validate_offset(ahd, tinfo, period, &offset,5339 bus_width, devinfo->role);5340 5341 if (ahd_sent_msg(ahd, AHDMSG_EXT, EXTENDED_PPR, TRUE)) {5342 /*5343 * If we are unable to do any of the5344 * requested options (we went too low),5345 * then we'll have to reject the message.5346 */5347 if (saved_width > bus_width5348 || saved_offset != offset5349 || saved_ppr_options != ppr_options) {5350 reject = TRUE;5351 period = 0;5352 offset = 0;5353 bus_width = 0;5354 ppr_options = 0;5355 }5356 } else {5357 if (devinfo->role != ROLE_TARGET)5358 printk("(%s:%c:%d:%d): Target "5359 "Initiated PPR\n",5360 ahd_name(ahd), devinfo->channel,5361 devinfo->target, devinfo->lun);5362 else5363 printk("(%s:%c:%d:%d): Initiator "5364 "Initiated PPR\n",5365 ahd_name(ahd), devinfo->channel,5366 devinfo->target, devinfo->lun);5367 ahd->msgout_index = 0;5368 ahd->msgout_len = 0;5369 ahd_construct_ppr(ahd, devinfo, period, offset,5370 bus_width, ppr_options);5371 ahd->msgout_index = 0;5372 response = TRUE;5373 }5374 if (bootverbose) {5375 printk("(%s:%c:%d:%d): Received PPR width %x, "5376 "period %x, offset %x,options %x\n"5377 "\tFiltered to width %x, period %x, "5378 "offset %x, options %x\n",5379 ahd_name(ahd), devinfo->channel,5380 devinfo->target, devinfo->lun,5381 saved_width, ahd->msgin_buf[3],5382 saved_offset, saved_ppr_options,5383 bus_width, period, offset, ppr_options);5384 }5385 ahd_set_width(ahd, devinfo, bus_width,5386 AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,5387 /*paused*/TRUE);5388 ahd_set_syncrate(ahd, devinfo, period,5389 offset, ppr_options,5390 AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,5391 /*paused*/TRUE);5392 5393 done = MSGLOOP_MSGCOMPLETE;5394 break;5395 }5396 default:5397 /* Unknown extended message. Reject it. */5398 reject = TRUE;5399 break;5400 }5401 break;5402 }5403#ifdef AHD_TARGET_MODE5404 case TARGET_RESET:5405 ahd_handle_devreset(ahd, devinfo, CAM_LUN_WILDCARD,5406 CAM_BDR_SENT,5407 "Bus Device Reset Received",5408 /*verbose_level*/0);5409 ahd_restart(ahd);5410 done = MSGLOOP_TERMINATED;5411 break;5412 case ABORT_TASK:5413 case ABORT_TASK_SET:5414 case CLEAR_TASK_SET:5415 {5416 int tag;5417 5418 /* Target mode messages */5419 if (devinfo->role != ROLE_TARGET) {5420 reject = TRUE;5421 break;5422 }5423 tag = SCB_LIST_NULL;5424 if (ahd->msgin_buf[0] == ABORT_TASK)5425 tag = ahd_inb(ahd, INITIATOR_TAG);5426 ahd_abort_scbs(ahd, devinfo->target, devinfo->channel,5427 devinfo->lun, tag, ROLE_TARGET,5428 CAM_REQ_ABORTED);5429 5430 tstate = ahd->enabled_targets[devinfo->our_scsiid];5431 if (tstate != NULL) {5432 struct ahd_tmode_lstate* lstate;5433 5434 lstate = tstate->enabled_luns[devinfo->lun];5435 if (lstate != NULL) {5436 ahd_queue_lstate_event(ahd, lstate,5437 devinfo->our_scsiid,5438 ahd->msgin_buf[0],5439 /*arg*/tag);5440 ahd_send_lstate_events(ahd, lstate);5441 }5442 }5443 ahd_restart(ahd);5444 done = MSGLOOP_TERMINATED;5445 break;5446 }5447#endif5448 case QAS_REQUEST:5449#ifdef AHD_DEBUG5450 if ((ahd_debug & AHD_SHOW_MESSAGES) != 0)5451 printk("%s: QAS request. SCSISIGI == 0x%x\n",5452 ahd_name(ahd), ahd_inb(ahd, SCSISIGI));5453#endif5454 ahd->msg_flags |= MSG_FLAG_EXPECT_QASREJ_BUSFREE;5455 fallthrough;5456 case TERMINATE_IO_PROC:5457 default:5458 reject = TRUE;5459 break;5460 }5461 5462 if (reject) {5463 /*5464 * Setup to reject the message.5465 */5466 ahd->msgout_index = 0;5467 ahd->msgout_len = 1;5468 ahd->msgout_buf[0] = MESSAGE_REJECT;5469 done = MSGLOOP_MSGCOMPLETE;5470 response = TRUE;5471 }5472 5473 if (done != MSGLOOP_IN_PROG && !response)5474 /* Clear the outgoing message buffer */5475 ahd->msgout_len = 0;5476 5477 return (done);5478}5479 5480/*5481 * Process a message reject message.5482 */5483static int5484ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)5485{5486 /*5487 * What we care about here is if we had an5488 * outstanding SDTR or WDTR message for this5489 * target. If we did, this is a signal that5490 * the target is refusing negotiation.5491 */5492 struct scb *scb;5493 struct ahd_initiator_tinfo *tinfo;5494 struct ahd_tmode_tstate *tstate;5495 u_int scb_index;5496 u_int last_msg;5497 int response = 0;5498 5499 scb_index = ahd_get_scbptr(ahd);5500 scb = ahd_lookup_scb(ahd, scb_index);5501 tinfo = ahd_fetch_transinfo(ahd, devinfo->channel,5502 devinfo->our_scsiid,5503 devinfo->target, &tstate);5504 /* Might be necessary */5505 last_msg = ahd_inb(ahd, LAST_MSG);5506 5507 if (ahd_sent_msg(ahd, AHDMSG_EXT, EXTENDED_PPR, /*full*/FALSE)) {5508 if (ahd_sent_msg(ahd, AHDMSG_EXT, EXTENDED_PPR, /*full*/TRUE)5509 && tinfo->goal.period <= AHD_SYNCRATE_PACED) {5510 /*5511 * Target may not like our SPI-4 PPR Options.5512 * Attempt to negotiate 80MHz which will turn5513 * off these options.5514 */5515 if (bootverbose) {5516 printk("(%s:%c:%d:%d): PPR Rejected. "5517 "Trying simple U160 PPR\n",5518 ahd_name(ahd), devinfo->channel,5519 devinfo->target, devinfo->lun);5520 }5521 tinfo->goal.period = AHD_SYNCRATE_DT;5522 tinfo->goal.ppr_options &= MSG_EXT_PPR_IU_REQ5523 | MSG_EXT_PPR_QAS_REQ5524 | MSG_EXT_PPR_DT_REQ;5525 } else {5526 /*5527 * Target does not support the PPR message.5528 * Attempt to negotiate SPI-2 style.5529 */5530 if (bootverbose) {5531 printk("(%s:%c:%d:%d): PPR Rejected. "5532 "Trying WDTR/SDTR\n",5533 ahd_name(ahd), devinfo->channel,5534 devinfo->target, devinfo->lun);5535 }5536 tinfo->goal.ppr_options = 0;5537 tinfo->curr.transport_version = 2;5538 tinfo->goal.transport_version = 2;5539 }5540 ahd->msgout_index = 0;5541 ahd->msgout_len = 0;5542 ahd_build_transfer_msg(ahd, devinfo);5543 ahd->msgout_index = 0;5544 response = 1;5545 } else if (ahd_sent_msg(ahd, AHDMSG_EXT, EXTENDED_WDTR, /*full*/FALSE)) {5546 5547 /* note 8bit xfers */5548 printk("(%s:%c:%d:%d): refuses WIDE negotiation. Using "5549 "8bit transfers\n", ahd_name(ahd),5550 devinfo->channel, devinfo->target, devinfo->lun);5551 ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT,5552 AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,5553 /*paused*/TRUE);5554 /*5555 * No need to clear the sync rate. If the target5556 * did not accept the command, our syncrate is5557 * unaffected. If the target started the negotiation,5558 * but rejected our response, we already cleared the5559 * sync rate before sending our WDTR.5560 */5561 if (tinfo->goal.offset != tinfo->curr.offset) {5562 5563 /* Start the sync negotiation */5564 ahd->msgout_index = 0;5565 ahd->msgout_len = 0;5566 ahd_build_transfer_msg(ahd, devinfo);5567 ahd->msgout_index = 0;5568 response = 1;5569 }5570 } else if (ahd_sent_msg(ahd, AHDMSG_EXT, EXTENDED_SDTR, /*full*/FALSE)) {5571 /* note asynch xfers and clear flag */5572 ahd_set_syncrate(ahd, devinfo, /*period*/0,5573 /*offset*/0, /*ppr_options*/0,5574 AHD_TRANS_ACTIVE|AHD_TRANS_GOAL,5575 /*paused*/TRUE);5576 printk("(%s:%c:%d:%d): refuses synchronous negotiation. "5577 "Using asynchronous transfers\n",5578 ahd_name(ahd), devinfo->channel,5579 devinfo->target, devinfo->lun);5580 } else if ((scb->hscb->control & SIMPLE_QUEUE_TAG) != 0) {5581 int tag_type;5582 int mask;5583 5584 tag_type = (scb->hscb->control & SIMPLE_QUEUE_TAG);5585 5586 if (tag_type == SIMPLE_QUEUE_TAG) {5587 printk("(%s:%c:%d:%d): refuses tagged commands. "5588 "Performing non-tagged I/O\n", ahd_name(ahd),5589 devinfo->channel, devinfo->target, devinfo->lun);5590 ahd_set_tags(ahd, scb->io_ctx, devinfo, AHD_QUEUE_NONE);5591 mask = ~0x23;5592 } else {5593 printk("(%s:%c:%d:%d): refuses %s tagged commands. "5594 "Performing simple queue tagged I/O only\n",5595 ahd_name(ahd), devinfo->channel, devinfo->target,5596 devinfo->lun, tag_type == ORDERED_QUEUE_TAG5597 ? "ordered" : "head of queue");5598 ahd_set_tags(ahd, scb->io_ctx, devinfo, AHD_QUEUE_BASIC);5599 mask = ~0x03;5600 }5601 5602 /*5603 * Resend the identify for this CCB as the target5604 * may believe that the selection is invalid otherwise.5605 */5606 ahd_outb(ahd, SCB_CONTROL,5607 ahd_inb_scbram(ahd, SCB_CONTROL) & mask);5608 scb->hscb->control &= mask;5609 ahd_set_transaction_tag(scb, /*enabled*/FALSE,5610 /*type*/SIMPLE_QUEUE_TAG);5611 ahd_outb(ahd, MSG_OUT, MSG_IDENTIFYFLAG);5612 ahd_assert_atn(ahd);5613 ahd_busy_tcl(ahd, BUILD_TCL(scb->hscb->scsiid, devinfo->lun),5614 SCB_GET_TAG(scb));5615 5616 /*5617 * Requeue all tagged commands for this target5618 * currently in our possession so they can be5619 * converted to untagged commands.5620 */5621 ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),5622 SCB_GET_CHANNEL(ahd, scb),5623 SCB_GET_LUN(scb), /*tag*/SCB_LIST_NULL,5624 ROLE_INITIATOR, CAM_REQUEUE_REQ,5625 SEARCH_COMPLETE);5626 } else if (ahd_sent_msg(ahd, AHDMSG_1B, MSG_IDENTIFYFLAG, TRUE)) {5627 /*5628 * Most likely the device believes that we had5629 * previously negotiated packetized.5630 */5631 ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE5632 | MSG_FLAG_IU_REQ_CHANGED;5633 5634 ahd_force_renegotiation(ahd, devinfo);5635 ahd->msgout_index = 0;5636 ahd->msgout_len = 0;5637 ahd_build_transfer_msg(ahd, devinfo);5638 ahd->msgout_index = 0;5639 response = 1;5640 } else {5641 /*5642 * Otherwise, we ignore it.5643 */5644 printk("%s:%c:%d: Message reject for %x -- ignored\n",5645 ahd_name(ahd), devinfo->channel, devinfo->target,5646 last_msg);5647 }5648 return (response);5649}5650 5651/*5652 * Process an ingnore wide residue message.5653 */5654static void5655ahd_handle_ign_wide_residue(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)5656{5657 u_int scb_index;5658 struct scb *scb;5659 5660 scb_index = ahd_get_scbptr(ahd);5661 scb = ahd_lookup_scb(ahd, scb_index);5662 /*5663 * XXX Actually check data direction in the sequencer?5664 * Perhaps add datadir to some spare bits in the hscb?5665 */5666 if ((ahd_inb(ahd, SEQ_FLAGS) & DPHASE) == 05667 || ahd_get_transfer_dir(scb) != CAM_DIR_IN) {5668 /*5669 * Ignore the message if we haven't5670 * seen an appropriate data phase yet.5671 */5672 } else {5673 /*5674 * If the residual occurred on the last5675 * transfer and the transfer request was5676 * expected to end on an odd count, do5677 * nothing. Otherwise, subtract a byte5678 * and update the residual count accordingly.5679 */5680 uint32_t sgptr;5681 5682 sgptr = ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR);5683 if ((sgptr & SG_LIST_NULL) != 05684 && (ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE)5685 & SCB_XFERLEN_ODD) != 0) {5686 /*5687 * If the residual occurred on the last5688 * transfer and the transfer request was5689 * expected to end on an odd count, do5690 * nothing.5691 */5692 } else {5693 uint32_t data_cnt;5694 uint64_t data_addr;5695 uint32_t sglen;5696 5697 /* Pull in the rest of the sgptr */5698 sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);5699 data_cnt = ahd_inl_scbram(ahd, SCB_RESIDUAL_DATACNT);5700 if ((sgptr & SG_LIST_NULL) != 0) {5701 /*5702 * The residual data count is not updated5703 * for the command run to completion case.5704 * Explicitly zero the count.5705 */5706 data_cnt &= ~AHD_SG_LEN_MASK;5707 }5708 data_addr = ahd_inq(ahd, SHADDR);5709 data_cnt += 1;5710 data_addr -= 1;5711 sgptr &= SG_PTR_MASK;5712 if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {5713 struct ahd_dma64_seg *sg;5714 5715 sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);5716 5717 /*5718 * The residual sg ptr points to the next S/G5719 * to load so we must go back one.5720 */5721 sg--;5722 sglen = ahd_le32toh(sg->len) & AHD_SG_LEN_MASK;5723 if (sg != scb->sg_list5724 && sglen < (data_cnt & AHD_SG_LEN_MASK)) {5725 5726 sg--;5727 sglen = ahd_le32toh(sg->len);5728 /*5729 * Preserve High Address and SG_LIST5730 * bits while setting the count to 1.5731 */5732 data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK));5733 data_addr = ahd_le64toh(sg->addr)5734 + (sglen & AHD_SG_LEN_MASK)5735 - 1;5736 5737 /*5738 * Increment sg so it points to the5739 * "next" sg.5740 */5741 sg++;5742 sgptr = ahd_sg_virt_to_bus(ahd, scb,5743 sg);5744 }5745 } else {5746 struct ahd_dma_seg *sg;5747 5748 sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);5749 5750 /*5751 * The residual sg ptr points to the next S/G5752 * to load so we must go back one.5753 */5754 sg--;5755 sglen = ahd_le32toh(sg->len) & AHD_SG_LEN_MASK;5756 if (sg != scb->sg_list5757 && sglen < (data_cnt & AHD_SG_LEN_MASK)) {5758 5759 sg--;5760 sglen = ahd_le32toh(sg->len);5761 /*5762 * Preserve High Address and SG_LIST5763 * bits while setting the count to 1.5764 */5765 data_cnt = 1|(sglen&(~AHD_SG_LEN_MASK));5766 data_addr = ahd_le32toh(sg->addr)5767 + (sglen & AHD_SG_LEN_MASK)5768 - 1;5769 5770 /*5771 * Increment sg so it points to the5772 * "next" sg.5773 */5774 sg++;5775 sgptr = ahd_sg_virt_to_bus(ahd, scb,5776 sg);5777 }5778 }5779 /*5780 * Toggle the "oddness" of the transfer length5781 * to handle this mid-transfer ignore wide5782 * residue. This ensures that the oddness is5783 * correct for subsequent data transfers.5784 */5785 ahd_outb(ahd, SCB_TASK_ATTRIBUTE,5786 ahd_inb_scbram(ahd, SCB_TASK_ATTRIBUTE)5787 ^ SCB_XFERLEN_ODD);5788 5789 ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);5790 ahd_outl(ahd, SCB_RESIDUAL_DATACNT, data_cnt);5791 /*5792 * The FIFO's pointers will be updated if/when the5793 * sequencer re-enters a data phase.5794 */5795 }5796 }5797}5798 5799 5800/*5801 * Reinitialize the data pointers for the active transfer5802 * based on its current residual.5803 */5804static void5805ahd_reinitialize_dataptrs(struct ahd_softc *ahd)5806{5807 struct scb *scb;5808 ahd_mode_state saved_modes;5809 u_int scb_index;5810 u_int wait;5811 uint32_t sgptr;5812 uint32_t resid;5813 uint64_t dataptr;5814 5815 AHD_ASSERT_MODES(ahd, AHD_MODE_DFF0_MSK|AHD_MODE_DFF1_MSK,5816 AHD_MODE_DFF0_MSK|AHD_MODE_DFF1_MSK);5817 5818 scb_index = ahd_get_scbptr(ahd);5819 scb = ahd_lookup_scb(ahd, scb_index);5820 5821 /*5822 * Release and reacquire the FIFO so we5823 * have a clean slate.5824 */5825 ahd_outb(ahd, DFFSXFRCTL, CLRCHN);5826 wait = 1000;5827 while (--wait && !(ahd_inb(ahd, MDFFSTAT) & FIFOFREE))5828 ahd_delay(100);5829 if (wait == 0) {5830 ahd_print_path(ahd, scb);5831 printk("ahd_reinitialize_dataptrs: Forcing FIFO free.\n");5832 ahd_outb(ahd, DFFSXFRCTL, RSTCHN|CLRSHCNT);5833 }5834 saved_modes = ahd_save_modes(ahd);5835 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);5836 ahd_outb(ahd, DFFSTAT,5837 ahd_inb(ahd, DFFSTAT)5838 | (saved_modes == 0x11 ? CURRFIFO_1 : CURRFIFO_0));5839 5840 /*5841 * Determine initial values for data_addr and data_cnt5842 * for resuming the data phase.5843 */5844 sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);5845 sgptr &= SG_PTR_MASK;5846 5847 resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16)5848 | (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 1) << 8)5849 | ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT);5850 5851 if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) {5852 struct ahd_dma64_seg *sg;5853 5854 sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);5855 5856 /* The residual sg_ptr always points to the next sg */5857 sg--;5858 5859 dataptr = ahd_le64toh(sg->addr)5860 + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK)5861 - resid;5862 ahd_outl(ahd, HADDR + 4, dataptr >> 32);5863 } else {5864 struct ahd_dma_seg *sg;5865 5866 sg = ahd_sg_bus_to_virt(ahd, scb, sgptr);5867 5868 /* The residual sg_ptr always points to the next sg */5869 sg--;5870 5871 dataptr = ahd_le32toh(sg->addr)5872 + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK)5873 - resid;5874 ahd_outb(ahd, HADDR + 4,5875 (ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24);5876 }5877 ahd_outl(ahd, HADDR, dataptr);5878 ahd_outb(ahd, HCNT + 2, resid >> 16);5879 ahd_outb(ahd, HCNT + 1, resid >> 8);5880 ahd_outb(ahd, HCNT, resid);5881}5882 5883/*5884 * Handle the effects of issuing a bus device reset message.5885 */5886static void5887ahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,5888 u_int lun, cam_status status, char *message,5889 int verbose_level)5890{5891#ifdef AHD_TARGET_MODE5892 struct ahd_tmode_tstate* tstate;5893#endif5894 int found;5895 5896 found = ahd_abort_scbs(ahd, devinfo->target, devinfo->channel,5897 lun, SCB_LIST_NULL, devinfo->role,5898 status);5899 5900#ifdef AHD_TARGET_MODE5901 /*5902 * Send an immediate notify ccb to all target mord peripheral5903 * drivers affected by this action.5904 */5905 tstate = ahd->enabled_targets[devinfo->our_scsiid];5906 if (tstate != NULL) {5907 u_int cur_lun;5908 u_int max_lun;5909 5910 if (lun != CAM_LUN_WILDCARD) {5911 cur_lun = 0;5912 max_lun = AHD_NUM_LUNS - 1;5913 } else {5914 cur_lun = lun;5915 max_lun = lun;5916 }5917 for (;cur_lun <= max_lun; cur_lun++) {5918 struct ahd_tmode_lstate* lstate;5919 5920 lstate = tstate->enabled_luns[cur_lun];5921 if (lstate == NULL)5922 continue;5923 5924 ahd_queue_lstate_event(ahd, lstate, devinfo->our_scsiid,5925 TARGET_RESET, /*arg*/0);5926 ahd_send_lstate_events(ahd, lstate);5927 }5928 }5929#endif5930 5931 /*5932 * Go back to async/narrow transfers and renegotiate.5933 */5934 ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT,5935 AHD_TRANS_CUR, /*paused*/TRUE);5936 ahd_set_syncrate(ahd, devinfo, /*period*/0, /*offset*/0,5937 /*ppr_options*/0, AHD_TRANS_CUR,5938 /*paused*/TRUE);5939 5940 if (status != CAM_SEL_TIMEOUT)5941 ahd_send_async(ahd, devinfo->channel, devinfo->target,5942 CAM_LUN_WILDCARD, AC_SENT_BDR);5943 5944 if (message != NULL && bootverbose)5945 printk("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd),5946 message, devinfo->channel, devinfo->target, found);5947}5948 5949#ifdef AHD_TARGET_MODE5950static void5951ahd_setup_target_msgin(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,5952 struct scb *scb)5953{5954 5955 /*5956 * To facilitate adding multiple messages together,5957 * each routine should increment the index and len5958 * variables instead of setting them explicitly.5959 */5960 ahd->msgout_index = 0;5961 ahd->msgout_len = 0;5962 5963 if (scb != NULL && (scb->flags & SCB_AUTO_NEGOTIATE) != 0)5964 ahd_build_transfer_msg(ahd, devinfo);5965 else5966 panic("ahd_intr: AWAITING target message with no message");5967 5968 ahd->msgout_index = 0;5969 ahd->msg_type = MSG_TYPE_TARGET_MSGIN;5970}5971#endif5972/**************************** Initialization **********************************/5973static u_int5974ahd_sglist_size(struct ahd_softc *ahd)5975{5976 bus_size_t list_size;5977 5978 list_size = sizeof(struct ahd_dma_seg) * AHD_NSEG;5979 if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)5980 list_size = sizeof(struct ahd_dma64_seg) * AHD_NSEG;5981 return (list_size);5982}5983 5984/*5985 * Calculate the optimum S/G List allocation size. S/G elements used5986 * for a given transaction must be physically contiguous. Assume the5987 * OS will allocate full pages to us, so it doesn't make sense to request5988 * less than a page.5989 */5990static u_int5991ahd_sglist_allocsize(struct ahd_softc *ahd)5992{5993 bus_size_t sg_list_increment;5994 bus_size_t sg_list_size;5995 bus_size_t max_list_size;5996 bus_size_t best_list_size;5997 5998 /* Start out with the minimum required for AHD_NSEG. */5999 sg_list_increment = ahd_sglist_size(ahd);6000 sg_list_size = sg_list_increment;6001 6002 /* Get us as close as possible to a page in size. */6003 while ((sg_list_size + sg_list_increment) <= PAGE_SIZE)6004 sg_list_size += sg_list_increment;6005 6006 /*6007 * Try to reduce the amount of wastage by allocating6008 * multiple pages.6009 */6010 best_list_size = sg_list_size;6011 max_list_size = roundup(sg_list_increment, PAGE_SIZE);6012 if (max_list_size < 4 * PAGE_SIZE)6013 max_list_size = 4 * PAGE_SIZE;6014 if (max_list_size > (AHD_SCB_MAX_ALLOC * sg_list_increment))6015 max_list_size = (AHD_SCB_MAX_ALLOC * sg_list_increment);6016 while ((sg_list_size + sg_list_increment) <= max_list_size6017 && (sg_list_size % PAGE_SIZE) != 0) {6018 bus_size_t new_mod;6019 bus_size_t best_mod;6020 6021 sg_list_size += sg_list_increment;6022 new_mod = sg_list_size % PAGE_SIZE;6023 best_mod = best_list_size % PAGE_SIZE;6024 if (new_mod > best_mod || new_mod == 0) {6025 best_list_size = sg_list_size;6026 }6027 }6028 return (best_list_size);6029}6030 6031/*6032 * Allocate a controller structure for a new device6033 * and perform initial initializion.6034 */6035struct ahd_softc *6036ahd_alloc(void *platform_arg, char *name)6037{6038 struct ahd_softc *ahd;6039 6040 ahd = kzalloc(sizeof(*ahd), GFP_ATOMIC);6041 if (!ahd) {6042 printk("aic7xxx: cannot malloc softc!\n");6043 kfree(name);6044 return NULL;6045 }6046 6047 ahd->seep_config = kmalloc(sizeof(*ahd->seep_config), GFP_ATOMIC);6048 if (ahd->seep_config == NULL) {6049 kfree(ahd);6050 kfree(name);6051 return (NULL);6052 }6053 LIST_INIT(&ahd->pending_scbs);6054 /* We don't know our unit number until the OSM sets it */6055 ahd->name = name;6056 ahd->unit = -1;6057 ahd->description = NULL;6058 ahd->bus_description = NULL;6059 ahd->channel = 'A';6060 ahd->chip = AHD_NONE;6061 ahd->features = AHD_FENONE;6062 ahd->bugs = AHD_BUGNONE;6063 ahd->flags = AHD_SPCHK_ENB_A|AHD_RESET_BUS_A|AHD_TERM_ENB_A6064 | AHD_EXTENDED_TRANS_A|AHD_STPWLEVEL_A;6065 timer_setup(&ahd->stat_timer, ahd_stat_timer, 0);6066 ahd->int_coalescing_timer = AHD_INT_COALESCING_TIMER_DEFAULT;6067 ahd->int_coalescing_maxcmds = AHD_INT_COALESCING_MAXCMDS_DEFAULT;6068 ahd->int_coalescing_mincmds = AHD_INT_COALESCING_MINCMDS_DEFAULT;6069 ahd->int_coalescing_threshold = AHD_INT_COALESCING_THRESHOLD_DEFAULT;6070 ahd->int_coalescing_stop_threshold =6071 AHD_INT_COALESCING_STOP_THRESHOLD_DEFAULT;6072 6073#ifdef AHD_DEBUG6074 if ((ahd_debug & AHD_SHOW_MEMORY) != 0) {6075 printk("%s: scb size = 0x%x, hscb size = 0x%x\n",6076 ahd_name(ahd), (u_int)sizeof(struct scb),6077 (u_int)sizeof(struct hardware_scb));6078 }6079#endif6080 if (ahd_platform_alloc(ahd, platform_arg) != 0) {6081 ahd_free(ahd);6082 ahd = NULL;6083 }6084 return (ahd);6085}6086 6087int6088ahd_softc_init(struct ahd_softc *ahd)6089{6090 6091 ahd->unpause = 0;6092 ahd->pause = PAUSE;6093 return (0);6094}6095 6096void6097ahd_set_unit(struct ahd_softc *ahd, int unit)6098{6099 ahd->unit = unit;6100}6101 6102void6103ahd_set_name(struct ahd_softc *ahd, char *name)6104{6105 kfree(ahd->name);6106 ahd->name = name;6107}6108 6109void6110ahd_free(struct ahd_softc *ahd)6111{6112 int i;6113 6114 switch (ahd->init_level) {6115 default:6116 case 5:6117 ahd_shutdown(ahd);6118 fallthrough;6119 case 4:6120 ahd_dmamap_unload(ahd, ahd->shared_data_dmat,6121 ahd->shared_data_map.dmamap);6122 fallthrough;6123 case 3:6124 ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo,6125 ahd->shared_data_map.dmamap);6126 ahd_dmamap_destroy(ahd, ahd->shared_data_dmat,6127 ahd->shared_data_map.dmamap);6128 fallthrough;6129 case 2:6130 ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat);6131 break;6132 case 1:6133 break;6134 case 0:6135 break;6136 }6137 6138 ahd_platform_free(ahd);6139 ahd_fini_scbdata(ahd);6140 for (i = 0; i < AHD_NUM_TARGETS; i++) {6141 struct ahd_tmode_tstate *tstate;6142 6143 tstate = ahd->enabled_targets[i];6144 if (tstate != NULL) {6145#ifdef AHD_TARGET_MODE6146 int j;6147 6148 for (j = 0; j < AHD_NUM_LUNS; j++) {6149 struct ahd_tmode_lstate *lstate;6150 6151 lstate = tstate->enabled_luns[j];6152 if (lstate != NULL) {6153 xpt_free_path(lstate->path);6154 kfree(lstate);6155 }6156 }6157#endif6158 kfree(tstate);6159 }6160 }6161#ifdef AHD_TARGET_MODE6162 if (ahd->black_hole != NULL) {6163 xpt_free_path(ahd->black_hole->path);6164 kfree(ahd->black_hole);6165 }6166#endif6167 kfree(ahd->name);6168 kfree(ahd->seep_config);6169 kfree(ahd->saved_stack);6170 kfree(ahd);6171 return;6172}6173 6174static void6175ahd_shutdown(void *arg)6176{6177 struct ahd_softc *ahd;6178 6179 ahd = (struct ahd_softc *)arg;6180 6181 /*6182 * Stop periodic timer callbacks.6183 */6184 del_timer_sync(&ahd->stat_timer);6185 6186 /* This will reset most registers to 0, but not all */6187 ahd_reset(ahd, /*reinit*/FALSE);6188}6189 6190/*6191 * Reset the controller and record some information about it6192 * that is only available just after a reset. If "reinit" is6193 * non-zero, this reset occurred after initial configuration6194 * and the caller requests that the chip be fully reinitialized6195 * to a runable state. Chip interrupts are *not* enabled after6196 * a reinitialization. The caller must enable interrupts via6197 * ahd_intr_enable().6198 */6199int6200ahd_reset(struct ahd_softc *ahd, int reinit)6201{6202 u_int sxfrctl1;6203 int wait;6204 uint32_t cmd;6205 6206 /*6207 * Preserve the value of the SXFRCTL1 register for all channels.6208 * It contains settings that affect termination and we don't want6209 * to disturb the integrity of the bus.6210 */6211 ahd_pause(ahd);6212 ahd_update_modes(ahd);6213 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);6214 sxfrctl1 = ahd_inb(ahd, SXFRCTL1);6215 6216 cmd = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);6217 if ((ahd->bugs & AHD_PCIX_CHIPRST_BUG) != 0) {6218 uint32_t mod_cmd;6219 6220 /*6221 * A4 Razor #6326222 * During the assertion of CHIPRST, the chip6223 * does not disable its parity logic prior to6224 * the start of the reset. This may cause a6225 * parity error to be detected and thus a6226 * spurious SERR or PERR assertion. Disable6227 * PERR and SERR responses during the CHIPRST.6228 */6229 mod_cmd = cmd & ~(PCIM_CMD_PERRESPEN|PCIM_CMD_SERRESPEN);6230 ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,6231 mod_cmd, /*bytes*/2);6232 }6233 ahd_outb(ahd, HCNTRL, CHIPRST | ahd->pause);6234 6235 /*6236 * Ensure that the reset has finished. We delay 1000us6237 * prior to reading the register to make sure the chip6238 * has sufficiently completed its reset to handle register6239 * accesses.6240 */6241 wait = 1000;6242 do {6243 ahd_delay(1000);6244 } while (--wait && !(ahd_inb(ahd, HCNTRL) & CHIPRSTACK));6245 6246 if (wait == 0) {6247 printk("%s: WARNING - Failed chip reset! "6248 "Trying to initialize anyway.\n", ahd_name(ahd));6249 }6250 ahd_outb(ahd, HCNTRL, ahd->pause);6251 6252 if ((ahd->bugs & AHD_PCIX_CHIPRST_BUG) != 0) {6253 /*6254 * Clear any latched PCI error status and restore6255 * previous SERR and PERR response enables.6256 */6257 ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,6258 0xFF, /*bytes*/1);6259 ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,6260 cmd, /*bytes*/2);6261 }6262 6263 /*6264 * Mode should be SCSI after a chip reset, but lets6265 * set it just to be safe. We touch the MODE_PTR6266 * register directly so as to bypass the lazy update6267 * code in ahd_set_modes().6268 */6269 ahd_known_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);6270 ahd_outb(ahd, MODE_PTR,6271 ahd_build_mode_state(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI));6272 6273 /*6274 * Restore SXFRCTL1.6275 *6276 * We must always initialize STPWEN to 1 before we6277 * restore the saved values. STPWEN is initialized6278 * to a tri-state condition which can only be cleared6279 * by turning it on.6280 */6281 ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN);6282 ahd_outb(ahd, SXFRCTL1, sxfrctl1);6283 6284 /* Determine chip configuration */6285 ahd->features &= ~AHD_WIDE;6286 if ((ahd_inb(ahd, SBLKCTL) & SELWIDE) != 0)6287 ahd->features |= AHD_WIDE;6288 6289 /*6290 * If a recovery action has forced a chip reset,6291 * re-initialize the chip to our liking.6292 */6293 if (reinit != 0)6294 ahd_chip_init(ahd);6295 6296 return (0);6297}6298 6299/*6300 * Determine the number of SCBs available on the controller6301 */6302static int6303ahd_probe_scbs(struct ahd_softc *ahd) {6304 int i;6305 6306 AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK),6307 ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK));6308 for (i = 0; i < AHD_SCB_MAX; i++) {6309 int j;6310 6311 ahd_set_scbptr(ahd, i);6312 ahd_outw(ahd, SCB_BASE, i);6313 for (j = 2; j < 64; j++)6314 ahd_outb(ahd, SCB_BASE+j, 0);6315 /* Start out life as unallocated (needing an abort) */6316 ahd_outb(ahd, SCB_CONTROL, MK_MESSAGE);6317 if (ahd_inw_scbram(ahd, SCB_BASE) != i)6318 break;6319 ahd_set_scbptr(ahd, 0);6320 if (ahd_inw_scbram(ahd, SCB_BASE) != 0)6321 break;6322 }6323 return (i);6324}6325 6326static void6327ahd_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 6328{6329 dma_addr_t *baddr;6330 6331 baddr = (dma_addr_t *)arg;6332 *baddr = segs->ds_addr;6333}6334 6335static void6336ahd_initialize_hscbs(struct ahd_softc *ahd)6337{6338 int i;6339 6340 for (i = 0; i < ahd->scb_data.maxhscbs; i++) {6341 ahd_set_scbptr(ahd, i);6342 6343 /* Clear the control byte. */6344 ahd_outb(ahd, SCB_CONTROL, 0);6345 6346 /* Set the next pointer */6347 ahd_outw(ahd, SCB_NEXT, SCB_LIST_NULL);6348 }6349}6350 6351static int6352ahd_init_scbdata(struct ahd_softc *ahd)6353{6354 struct scb_data *scb_data;6355 int i;6356 6357 scb_data = &ahd->scb_data;6358 TAILQ_INIT(&scb_data->free_scbs);6359 for (i = 0; i < AHD_NUM_TARGETS * AHD_NUM_LUNS_NONPKT; i++)6360 LIST_INIT(&scb_data->free_scb_lists[i]);6361 LIST_INIT(&scb_data->any_dev_free_scb_list);6362 SLIST_INIT(&scb_data->hscb_maps);6363 SLIST_INIT(&scb_data->sg_maps);6364 SLIST_INIT(&scb_data->sense_maps);6365 6366 /* Determine the number of hardware SCBs and initialize them */6367 scb_data->maxhscbs = ahd_probe_scbs(ahd);6368 if (scb_data->maxhscbs == 0) {6369 printk("%s: No SCB space found\n", ahd_name(ahd));6370 return (ENXIO);6371 }6372 6373 ahd_initialize_hscbs(ahd);6374 6375 /*6376 * Create our DMA tags. These tags define the kinds of device6377 * accessible memory allocations and memory mappings we will6378 * need to perform during normal operation.6379 *6380 * Unless we need to further restrict the allocation, we rely6381 * on the restrictions of the parent dmat, hence the common6382 * use of MAXADDR and MAXSIZE.6383 */6384 6385 /* DMA tag for our hardware scb structures */6386 if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,6387 /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,6388 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,6389 /*highaddr*/BUS_SPACE_MAXADDR,6390 /*filter*/NULL, /*filterarg*/NULL,6391 PAGE_SIZE, /*nsegments*/1,6392 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,6393 /*flags*/0, &scb_data->hscb_dmat) != 0) {6394 goto error_exit;6395 }6396 6397 scb_data->init_level++;6398 6399 /* DMA tag for our S/G structures. */6400 if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/8,6401 /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,6402 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,6403 /*highaddr*/BUS_SPACE_MAXADDR,6404 /*filter*/NULL, /*filterarg*/NULL,6405 ahd_sglist_allocsize(ahd), /*nsegments*/1,6406 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,6407 /*flags*/0, &scb_data->sg_dmat) != 0) {6408 goto error_exit;6409 }6410#ifdef AHD_DEBUG6411 if ((ahd_debug & AHD_SHOW_MEMORY) != 0)6412 printk("%s: ahd_sglist_allocsize = 0x%x\n", ahd_name(ahd),6413 ahd_sglist_allocsize(ahd));6414#endif6415 6416 scb_data->init_level++;6417 6418 /* DMA tag for our sense buffers. We allocate in page sized chunks */6419 if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,6420 /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,6421 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,6422 /*highaddr*/BUS_SPACE_MAXADDR,6423 /*filter*/NULL, /*filterarg*/NULL,6424 PAGE_SIZE, /*nsegments*/1,6425 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,6426 /*flags*/0, &scb_data->sense_dmat) != 0) {6427 goto error_exit;6428 }6429 6430 scb_data->init_level++;6431 6432 /* Perform initial CCB allocation */6433 ahd_alloc_scbs(ahd);6434 6435 if (scb_data->numscbs == 0) {6436 printk("%s: ahd_init_scbdata - "6437 "Unable to allocate initial scbs\n",6438 ahd_name(ahd));6439 goto error_exit;6440 }6441 6442 /*6443 * Note that we were successful6444 */6445 return (0);6446 6447error_exit:6448 6449 return (ENOMEM);6450}6451 6452static struct scb *6453ahd_find_scb_by_tag(struct ahd_softc *ahd, u_int tag)6454{6455 struct scb *scb;6456 6457 /*6458 * Look on the pending list.6459 */6460 LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {6461 if (SCB_GET_TAG(scb) == tag)6462 return (scb);6463 }6464 6465 /*6466 * Then on all of the collision free lists.6467 */6468 TAILQ_FOREACH(scb, &ahd->scb_data.free_scbs, links.tqe) {6469 struct scb *list_scb;6470 6471 list_scb = scb;6472 do {6473 if (SCB_GET_TAG(list_scb) == tag)6474 return (list_scb);6475 list_scb = LIST_NEXT(list_scb, collision_links);6476 } while (list_scb);6477 }6478 6479 /*6480 * And finally on the generic free list.6481 */6482 LIST_FOREACH(scb, &ahd->scb_data.any_dev_free_scb_list, links.le) {6483 if (SCB_GET_TAG(scb) == tag)6484 return (scb);6485 }6486 6487 return (NULL);6488}6489 6490static void6491ahd_fini_scbdata(struct ahd_softc *ahd)6492{6493 struct scb_data *scb_data;6494 6495 scb_data = &ahd->scb_data;6496 if (scb_data == NULL)6497 return;6498 6499 switch (scb_data->init_level) {6500 default:6501 case 7:6502 {6503 struct map_node *sns_map;6504 6505 while ((sns_map = SLIST_FIRST(&scb_data->sense_maps)) != NULL) {6506 SLIST_REMOVE_HEAD(&scb_data->sense_maps, links);6507 ahd_dmamap_unload(ahd, scb_data->sense_dmat,6508 sns_map->dmamap);6509 ahd_dmamem_free(ahd, scb_data->sense_dmat,6510 sns_map->vaddr, sns_map->dmamap);6511 kfree(sns_map);6512 }6513 ahd_dma_tag_destroy(ahd, scb_data->sense_dmat);6514 }6515 fallthrough;6516 case 6:6517 {6518 struct map_node *sg_map;6519 6520 while ((sg_map = SLIST_FIRST(&scb_data->sg_maps)) != NULL) {6521 SLIST_REMOVE_HEAD(&scb_data->sg_maps, links);6522 ahd_dmamap_unload(ahd, scb_data->sg_dmat,6523 sg_map->dmamap);6524 ahd_dmamem_free(ahd, scb_data->sg_dmat,6525 sg_map->vaddr, sg_map->dmamap);6526 kfree(sg_map);6527 }6528 ahd_dma_tag_destroy(ahd, scb_data->sg_dmat);6529 }6530 fallthrough;6531 case 5:6532 {6533 struct map_node *hscb_map;6534 6535 while ((hscb_map = SLIST_FIRST(&scb_data->hscb_maps)) != NULL) {6536 SLIST_REMOVE_HEAD(&scb_data->hscb_maps, links);6537 ahd_dmamap_unload(ahd, scb_data->hscb_dmat,6538 hscb_map->dmamap);6539 ahd_dmamem_free(ahd, scb_data->hscb_dmat,6540 hscb_map->vaddr, hscb_map->dmamap);6541 kfree(hscb_map);6542 }6543 ahd_dma_tag_destroy(ahd, scb_data->hscb_dmat);6544 }6545 fallthrough;6546 case 4:6547 case 3:6548 case 2:6549 case 1:6550 case 0:6551 break;6552 }6553}6554 6555/*6556 * DSP filter Bypass must be enabled until the first selection6557 * after a change in bus mode (Razor #491 and #493).6558 */6559static void6560ahd_setup_iocell_workaround(struct ahd_softc *ahd)6561{6562 ahd_mode_state saved_modes;6563 6564 saved_modes = ahd_save_modes(ahd);6565 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);6566 ahd_outb(ahd, DSPDATACTL, ahd_inb(ahd, DSPDATACTL)6567 | BYPASSENAB | RCVROFFSTDIS | XMITOFFSTDIS);6568 ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) | (ENSELDO|ENSELDI));6569#ifdef AHD_DEBUG6570 if ((ahd_debug & AHD_SHOW_MISC) != 0)6571 printk("%s: Setting up iocell workaround\n", ahd_name(ahd));6572#endif6573 ahd_restore_modes(ahd, saved_modes);6574 ahd->flags &= ~AHD_HAD_FIRST_SEL;6575}6576 6577static void6578ahd_iocell_first_selection(struct ahd_softc *ahd)6579{6580 ahd_mode_state saved_modes;6581 u_int sblkctl;6582 6583 if ((ahd->flags & AHD_HAD_FIRST_SEL) != 0)6584 return;6585 saved_modes = ahd_save_modes(ahd);6586 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);6587 sblkctl = ahd_inb(ahd, SBLKCTL);6588 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);6589#ifdef AHD_DEBUG6590 if ((ahd_debug & AHD_SHOW_MISC) != 0)6591 printk("%s: iocell first selection\n", ahd_name(ahd));6592#endif6593 if ((sblkctl & ENAB40) != 0) {6594 ahd_outb(ahd, DSPDATACTL,6595 ahd_inb(ahd, DSPDATACTL) & ~BYPASSENAB);6596#ifdef AHD_DEBUG6597 if ((ahd_debug & AHD_SHOW_MISC) != 0)6598 printk("%s: BYPASS now disabled\n", ahd_name(ahd));6599#endif6600 }6601 ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) & ~(ENSELDO|ENSELDI));6602 ahd_outb(ahd, CLRINT, CLRSCSIINT);6603 ahd_restore_modes(ahd, saved_modes);6604 ahd->flags |= AHD_HAD_FIRST_SEL;6605}6606 6607/*************************** SCB Management ***********************************/6608static void6609ahd_add_col_list(struct ahd_softc *ahd, struct scb *scb, u_int col_idx)6610{6611 struct scb_list *free_list;6612 struct scb_tailq *free_tailq;6613 struct scb *first_scb;6614 6615 scb->flags |= SCB_ON_COL_LIST;6616 AHD_SET_SCB_COL_IDX(scb, col_idx);6617 free_list = &ahd->scb_data.free_scb_lists[col_idx];6618 free_tailq = &ahd->scb_data.free_scbs;6619 first_scb = LIST_FIRST(free_list);6620 if (first_scb != NULL) {6621 LIST_INSERT_AFTER(first_scb, scb, collision_links);6622 } else {6623 LIST_INSERT_HEAD(free_list, scb, collision_links);6624 TAILQ_INSERT_TAIL(free_tailq, scb, links.tqe);6625 }6626}6627 6628static void6629ahd_rem_col_list(struct ahd_softc *ahd, struct scb *scb)6630{6631 struct scb_list *free_list;6632 struct scb_tailq *free_tailq;6633 struct scb *first_scb;6634 u_int col_idx;6635 6636 scb->flags &= ~SCB_ON_COL_LIST;6637 col_idx = AHD_GET_SCB_COL_IDX(ahd, scb);6638 free_list = &ahd->scb_data.free_scb_lists[col_idx];6639 free_tailq = &ahd->scb_data.free_scbs;6640 first_scb = LIST_FIRST(free_list);6641 if (first_scb == scb) {6642 struct scb *next_scb;6643 6644 /*6645 * Maintain order in the collision free6646 * lists for fairness if this device has6647 * other colliding tags active.6648 */6649 next_scb = LIST_NEXT(scb, collision_links);6650 if (next_scb != NULL) {6651 TAILQ_INSERT_AFTER(free_tailq, scb,6652 next_scb, links.tqe);6653 }6654 TAILQ_REMOVE(free_tailq, scb, links.tqe);6655 }6656 LIST_REMOVE(scb, collision_links);6657}6658 6659/*6660 * Get a free scb. If there are none, see if we can allocate a new SCB.6661 */6662struct scb *6663ahd_get_scb(struct ahd_softc *ahd, u_int col_idx)6664{6665 struct scb *scb;6666 int tries;6667 6668 tries = 0;6669look_again:6670 TAILQ_FOREACH(scb, &ahd->scb_data.free_scbs, links.tqe) {6671 if (AHD_GET_SCB_COL_IDX(ahd, scb) != col_idx) {6672 ahd_rem_col_list(ahd, scb);6673 goto found;6674 }6675 }6676 if ((scb = LIST_FIRST(&ahd->scb_data.any_dev_free_scb_list)) == NULL) {6677 6678 if (tries++ != 0)6679 return (NULL);6680 ahd_alloc_scbs(ahd);6681 goto look_again;6682 }6683 LIST_REMOVE(scb, links.le);6684 if (col_idx != AHD_NEVER_COL_IDX6685 && (scb->col_scb != NULL)6686 && (scb->col_scb->flags & SCB_ACTIVE) == 0) {6687 LIST_REMOVE(scb->col_scb, links.le);6688 ahd_add_col_list(ahd, scb->col_scb, col_idx);6689 }6690found:6691 scb->flags |= SCB_ACTIVE;6692 return (scb);6693}6694 6695/*6696 * Return an SCB resource to the free list.6697 */6698void6699ahd_free_scb(struct ahd_softc *ahd, struct scb *scb)6700{6701 /* Clean up for the next user */6702 scb->flags = SCB_FLAG_NONE;6703 scb->hscb->control = 0;6704 ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = NULL;6705 6706 if (scb->col_scb == NULL) {6707 6708 /*6709 * No collision possible. Just free normally.6710 */6711 LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,6712 scb, links.le);6713 } else if ((scb->col_scb->flags & SCB_ON_COL_LIST) != 0) {6714 6715 /*6716 * The SCB we might have collided with is on6717 * a free collision list. Put both SCBs on6718 * the generic list.6719 */6720 ahd_rem_col_list(ahd, scb->col_scb);6721 LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,6722 scb, links.le);6723 LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,6724 scb->col_scb, links.le);6725 } else if ((scb->col_scb->flags6726 & (SCB_PACKETIZED|SCB_ACTIVE)) == SCB_ACTIVE6727 && (scb->col_scb->hscb->control & TAG_ENB) != 0) {6728 6729 /*6730 * The SCB we might collide with on the next allocation6731 * is still active in a non-packetized, tagged, context.6732 * Put us on the SCB collision list.6733 */6734 ahd_add_col_list(ahd, scb,6735 AHD_GET_SCB_COL_IDX(ahd, scb->col_scb));6736 } else {6737 /*6738 * The SCB we might collide with on the next allocation6739 * is either active in a packetized context, or free.6740 * Since we can't collide, put this SCB on the generic6741 * free list.6742 */6743 LIST_INSERT_HEAD(&ahd->scb_data.any_dev_free_scb_list,6744 scb, links.le);6745 }6746 6747 ahd_platform_scb_free(ahd, scb);6748}6749 6750static void6751ahd_alloc_scbs(struct ahd_softc *ahd)6752{6753 struct scb_data *scb_data;6754 struct scb *next_scb;6755 struct hardware_scb *hscb;6756 struct map_node *hscb_map;6757 struct map_node *sg_map;6758 struct map_node *sense_map;6759 uint8_t *segs;6760 uint8_t *sense_data;6761 dma_addr_t hscb_busaddr;6762 dma_addr_t sg_busaddr;6763 dma_addr_t sense_busaddr;6764 int newcount;6765 int i;6766 6767 scb_data = &ahd->scb_data;6768 if (scb_data->numscbs >= AHD_SCB_MAX_ALLOC)6769 /* Can't allocate any more */6770 return;6771 6772 if (scb_data->scbs_left != 0) {6773 int offset;6774 6775 offset = (PAGE_SIZE / sizeof(*hscb)) - scb_data->scbs_left;6776 hscb_map = SLIST_FIRST(&scb_data->hscb_maps);6777 hscb = &((struct hardware_scb *)hscb_map->vaddr)[offset];6778 hscb_busaddr = hscb_map->physaddr + (offset * sizeof(*hscb));6779 } else {6780 hscb_map = kmalloc(sizeof(*hscb_map), GFP_ATOMIC);6781 6782 if (hscb_map == NULL)6783 return;6784 6785 /* Allocate the next batch of hardware SCBs */6786 if (ahd_dmamem_alloc(ahd, scb_data->hscb_dmat,6787 (void **)&hscb_map->vaddr,6788 BUS_DMA_NOWAIT, &hscb_map->dmamap) != 0) {6789 kfree(hscb_map);6790 return;6791 }6792 6793 SLIST_INSERT_HEAD(&scb_data->hscb_maps, hscb_map, links);6794 6795 ahd_dmamap_load(ahd, scb_data->hscb_dmat, hscb_map->dmamap,6796 hscb_map->vaddr, PAGE_SIZE, ahd_dmamap_cb,6797 &hscb_map->physaddr, /*flags*/0);6798 6799 hscb = (struct hardware_scb *)hscb_map->vaddr;6800 hscb_busaddr = hscb_map->physaddr;6801 scb_data->scbs_left = PAGE_SIZE / sizeof(*hscb);6802 }6803 6804 if (scb_data->sgs_left != 0) {6805 int offset;6806 6807 offset = ((ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd))6808 - scb_data->sgs_left) * ahd_sglist_size(ahd);6809 sg_map = SLIST_FIRST(&scb_data->sg_maps);6810 segs = sg_map->vaddr + offset;6811 sg_busaddr = sg_map->physaddr + offset;6812 } else {6813 sg_map = kmalloc(sizeof(*sg_map), GFP_ATOMIC);6814 6815 if (sg_map == NULL)6816 return;6817 6818 /* Allocate the next batch of S/G lists */6819 if (ahd_dmamem_alloc(ahd, scb_data->sg_dmat,6820 (void **)&sg_map->vaddr,6821 BUS_DMA_NOWAIT, &sg_map->dmamap) != 0) {6822 kfree(sg_map);6823 return;6824 }6825 6826 SLIST_INSERT_HEAD(&scb_data->sg_maps, sg_map, links);6827 6828 ahd_dmamap_load(ahd, scb_data->sg_dmat, sg_map->dmamap,6829 sg_map->vaddr, ahd_sglist_allocsize(ahd),6830 ahd_dmamap_cb, &sg_map->physaddr, /*flags*/0);6831 6832 segs = sg_map->vaddr;6833 sg_busaddr = sg_map->physaddr;6834 scb_data->sgs_left =6835 ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd);6836#ifdef AHD_DEBUG6837 if (ahd_debug & AHD_SHOW_MEMORY)6838 printk("Mapped SG data\n");6839#endif6840 }6841 6842 if (scb_data->sense_left != 0) {6843 int offset;6844 6845 offset = PAGE_SIZE - (AHD_SENSE_BUFSIZE * scb_data->sense_left);6846 sense_map = SLIST_FIRST(&scb_data->sense_maps);6847 sense_data = sense_map->vaddr + offset;6848 sense_busaddr = sense_map->physaddr + offset;6849 } else {6850 sense_map = kmalloc(sizeof(*sense_map), GFP_ATOMIC);6851 6852 if (sense_map == NULL)6853 return;6854 6855 /* Allocate the next batch of sense buffers */6856 if (ahd_dmamem_alloc(ahd, scb_data->sense_dmat,6857 (void **)&sense_map->vaddr,6858 BUS_DMA_NOWAIT, &sense_map->dmamap) != 0) {6859 kfree(sense_map);6860 return;6861 }6862 6863 SLIST_INSERT_HEAD(&scb_data->sense_maps, sense_map, links);6864 6865 ahd_dmamap_load(ahd, scb_data->sense_dmat, sense_map->dmamap,6866 sense_map->vaddr, PAGE_SIZE, ahd_dmamap_cb,6867 &sense_map->physaddr, /*flags*/0);6868 6869 sense_data = sense_map->vaddr;6870 sense_busaddr = sense_map->physaddr;6871 scb_data->sense_left = PAGE_SIZE / AHD_SENSE_BUFSIZE;6872#ifdef AHD_DEBUG6873 if (ahd_debug & AHD_SHOW_MEMORY)6874 printk("Mapped sense data\n");6875#endif6876 }6877 6878 newcount = min(scb_data->sense_left, scb_data->scbs_left);6879 newcount = min(newcount, scb_data->sgs_left);6880 newcount = min(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs));6881 for (i = 0; i < newcount; i++) {6882 struct scb_platform_data *pdata;6883 u_int col_tag;6884 6885 next_scb = kmalloc(sizeof(*next_scb), GFP_ATOMIC);6886 if (next_scb == NULL)6887 break;6888 6889 pdata = kmalloc(sizeof(*pdata), GFP_ATOMIC);6890 if (pdata == NULL) {6891 kfree(next_scb);6892 break;6893 }6894 next_scb->platform_data = pdata;6895 next_scb->hscb_map = hscb_map;6896 next_scb->sg_map = sg_map;6897 next_scb->sense_map = sense_map;6898 next_scb->sg_list = segs;6899 next_scb->sense_data = sense_data;6900 next_scb->sense_busaddr = sense_busaddr;6901 memset(hscb, 0, sizeof(*hscb));6902 next_scb->hscb = hscb;6903 hscb->hscb_busaddr = ahd_htole32(hscb_busaddr);6904 6905 /*6906 * The sequencer always starts with the second entry.6907 * The first entry is embedded in the scb.6908 */6909 next_scb->sg_list_busaddr = sg_busaddr;6910 if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)6911 next_scb->sg_list_busaddr6912 += sizeof(struct ahd_dma64_seg);6913 else6914 next_scb->sg_list_busaddr += sizeof(struct ahd_dma_seg);6915 next_scb->ahd_softc = ahd;6916 next_scb->flags = SCB_FLAG_NONE;6917 next_scb->hscb->tag = ahd_htole16(scb_data->numscbs);6918 col_tag = scb_data->numscbs ^ 0x100;6919 next_scb->col_scb = ahd_find_scb_by_tag(ahd, col_tag);6920 if (next_scb->col_scb != NULL)6921 next_scb->col_scb->col_scb = next_scb;6922 ahd_free_scb(ahd, next_scb);6923 hscb++;6924 hscb_busaddr += sizeof(*hscb);6925 segs += ahd_sglist_size(ahd);6926 sg_busaddr += ahd_sglist_size(ahd);6927 sense_data += AHD_SENSE_BUFSIZE;6928 sense_busaddr += AHD_SENSE_BUFSIZE;6929 scb_data->numscbs++;6930 scb_data->sense_left--;6931 scb_data->scbs_left--;6932 scb_data->sgs_left--;6933 }6934}6935 6936void6937ahd_controller_info(struct ahd_softc *ahd, char *buf)6938{6939 const char *speed;6940 const char *type;6941 int len;6942 6943 len = sprintf(buf, "%s: ", ahd_chip_names[ahd->chip & AHD_CHIPID_MASK]);6944 buf += len;6945 6946 speed = "Ultra320 ";6947 if ((ahd->features & AHD_WIDE) != 0) {6948 type = "Wide ";6949 } else {6950 type = "Single ";6951 }6952 len = sprintf(buf, "%s%sChannel %c, SCSI Id=%d, ",6953 speed, type, ahd->channel, ahd->our_id);6954 buf += len;6955 6956 sprintf(buf, "%s, %d SCBs", ahd->bus_description,6957 ahd->scb_data.maxhscbs);6958}6959 6960static const char *channel_strings[] = {6961 "Primary Low",6962 "Primary High",6963 "Secondary Low",6964 "Secondary High"6965};6966 6967static const char *termstat_strings[] = {6968 "Terminated Correctly",6969 "Over Terminated",6970 "Under Terminated",6971 "Not Configured"6972};6973 6974/***************************** Timer Facilities *******************************/6975static void6976ahd_timer_reset(struct timer_list *timer, int usec)6977{6978 del_timer(timer);6979 timer->expires = jiffies + (usec * HZ)/1000000;6980 add_timer(timer);6981}6982 6983/*6984 * Start the board, ready for normal operation6985 */6986int6987ahd_init(struct ahd_softc *ahd)6988{6989 uint8_t *next_vaddr;6990 dma_addr_t next_baddr;6991 size_t driver_data_size;6992 int i;6993 int error;6994 u_int warn_user;6995 uint8_t current_sensing;6996 uint8_t fstat;6997 6998 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);6999 7000 ahd->stack_size = ahd_probe_stack_size(ahd);7001 ahd->saved_stack = kmalloc_array(ahd->stack_size, sizeof(uint16_t),7002 GFP_ATOMIC);7003 if (ahd->saved_stack == NULL)7004 return (ENOMEM);7005 7006 /*7007 * Verify that the compiler hasn't over-aggressively7008 * padded important structures.7009 */7010 if (sizeof(struct hardware_scb) != 64)7011 panic("Hardware SCB size is incorrect");7012 7013#ifdef AHD_DEBUG7014 if ((ahd_debug & AHD_DEBUG_SEQUENCER) != 0)7015 ahd->flags |= AHD_SEQUENCER_DEBUG;7016#endif7017 7018 /*7019 * Default to allowing initiator operations.7020 */7021 ahd->flags |= AHD_INITIATORROLE;7022 7023 /*7024 * Only allow target mode features if this unit has them enabled.7025 */7026 if ((AHD_TMODE_ENABLE & (0x1 << ahd->unit)) == 0)7027 ahd->features &= ~AHD_TARGETMODE;7028 7029 ahd->init_level++;7030 7031 /*7032 * DMA tag for our command fifos and other data in system memory7033 * the card's sequencer must be able to access. For initiator7034 * roles, we need to allocate space for the qoutfifo. When providing7035 * for the target mode role, we must additionally provide space for7036 * the incoming target command fifo.7037 */7038 driver_data_size = AHD_SCB_MAX * sizeof(*ahd->qoutfifo)7039 + sizeof(struct hardware_scb);7040 if ((ahd->features & AHD_TARGETMODE) != 0)7041 driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd);7042 if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0)7043 driver_data_size += PKT_OVERRUN_BUFSIZE;7044 if (ahd_dma_tag_create(ahd, ahd->parent_dmat, /*alignment*/1,7045 /*boundary*/BUS_SPACE_MAXADDR_32BIT + 1,7046 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,7047 /*highaddr*/BUS_SPACE_MAXADDR,7048 /*filter*/NULL, /*filterarg*/NULL,7049 driver_data_size,7050 /*nsegments*/1,7051 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,7052 /*flags*/0, &ahd->shared_data_dmat) != 0) {7053 return (ENOMEM);7054 }7055 7056 ahd->init_level++;7057 7058 /* Allocation of driver data */7059 if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat,7060 (void **)&ahd->shared_data_map.vaddr,7061 BUS_DMA_NOWAIT,7062 &ahd->shared_data_map.dmamap) != 0) {7063 return (ENOMEM);7064 }7065 7066 ahd->init_level++;7067 7068 /* And permanently map it in */7069 ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,7070 ahd->shared_data_map.vaddr, driver_data_size,7071 ahd_dmamap_cb, &ahd->shared_data_map.physaddr,7072 /*flags*/0);7073 ahd->qoutfifo = (struct ahd_completion *)ahd->shared_data_map.vaddr;7074 next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE];7075 next_baddr = ahd->shared_data_map.physaddr7076 + AHD_QOUT_SIZE*sizeof(struct ahd_completion);7077 if ((ahd->features & AHD_TARGETMODE) != 0) {7078 ahd->targetcmds = (struct target_cmd *)next_vaddr;7079 next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd);7080 next_baddr += AHD_TMODE_CMDS * sizeof(struct target_cmd);7081 }7082 7083 if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) {7084 ahd->overrun_buf = next_vaddr;7085 next_vaddr += PKT_OVERRUN_BUFSIZE;7086 next_baddr += PKT_OVERRUN_BUFSIZE;7087 }7088 7089 /*7090 * We need one SCB to serve as the "next SCB". Since the7091 * tag identifier in this SCB will never be used, there is7092 * no point in using a valid HSCB tag from an SCB pulled from7093 * the standard free pool. So, we allocate this "sentinel"7094 * specially from the DMA safe memory chunk used for the QOUTFIFO.7095 */7096 ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr;7097 ahd->next_queued_hscb_map = &ahd->shared_data_map;7098 ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr);7099 7100 ahd->init_level++;7101 7102 /* Allocate SCB data now that buffer_dmat is initialized */7103 if (ahd_init_scbdata(ahd) != 0)7104 return (ENOMEM);7105 7106 if ((ahd->flags & AHD_INITIATORROLE) == 0)7107 ahd->flags &= ~AHD_RESET_BUS_A;7108 7109 /*7110 * Before committing these settings to the chip, give7111 * the OSM one last chance to modify our configuration.7112 */7113 ahd_platform_init(ahd);7114 7115 /* Bring up the chip. */7116 ahd_chip_init(ahd);7117 7118 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);7119 7120 if ((ahd->flags & AHD_CURRENT_SENSING) == 0)7121 goto init_done;7122 7123 /*7124 * Verify termination based on current draw and7125 * warn user if the bus is over/under terminated.7126 */7127 error = ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL,7128 CURSENSE_ENB);7129 if (error != 0) {7130 printk("%s: current sensing timeout 1\n", ahd_name(ahd));7131 goto init_done;7132 }7133 for (i = 20, fstat = FLX_FSTAT_BUSY;7134 (fstat & FLX_FSTAT_BUSY) != 0 && i; i--) {7135 error = ahd_read_flexport(ahd, FLXADDR_FLEXSTAT, &fstat);7136 if (error != 0) {7137 printk("%s: current sensing timeout 2\n",7138 ahd_name(ahd));7139 goto init_done;7140 }7141 }7142 if (i == 0) {7143 printk("%s: Timedout during current-sensing test\n",7144 ahd_name(ahd));7145 goto init_done;7146 }7147 7148 /* Latch Current Sensing status. */7149 error = ahd_read_flexport(ahd, FLXADDR_CURRENT_STAT, ¤t_sensing);7150 if (error != 0) {7151 printk("%s: current sensing timeout 3\n", ahd_name(ahd));7152 goto init_done;7153 }7154 7155 /* Diable current sensing. */7156 ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, 0);7157 7158#ifdef AHD_DEBUG7159 if ((ahd_debug & AHD_SHOW_TERMCTL) != 0) {7160 printk("%s: current_sensing == 0x%x\n",7161 ahd_name(ahd), current_sensing);7162 }7163#endif7164 warn_user = 0;7165 for (i = 0; i < 4; i++, current_sensing >>= FLX_CSTAT_SHIFT) {7166 u_int term_stat;7167 7168 term_stat = (current_sensing & FLX_CSTAT_MASK);7169 switch (term_stat) {7170 case FLX_CSTAT_OVER:7171 case FLX_CSTAT_UNDER:7172 warn_user++;7173 fallthrough;7174 case FLX_CSTAT_INVALID:7175 case FLX_CSTAT_OKAY:7176 if (warn_user == 0 && bootverbose == 0)7177 break;7178 printk("%s: %s Channel %s\n", ahd_name(ahd),7179 channel_strings[i], termstat_strings[term_stat]);7180 break;7181 }7182 }7183 if (warn_user) {7184 printk("%s: WARNING. Termination is not configured correctly.\n"7185 "%s: WARNING. SCSI bus operations may FAIL.\n",7186 ahd_name(ahd), ahd_name(ahd));7187 }7188init_done:7189 ahd_restart(ahd);7190 ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US);7191 return (0);7192}7193 7194/*7195 * (Re)initialize chip state after a chip reset.7196 */7197static void7198ahd_chip_init(struct ahd_softc *ahd)7199{7200 uint32_t busaddr;7201 u_int sxfrctl1;7202 u_int scsiseq_template;7203 u_int wait;7204 u_int i;7205 u_int target;7206 7207 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);7208 /*7209 * Take the LED out of diagnostic mode7210 */7211 ahd_outb(ahd, SBLKCTL, ahd_inb(ahd, SBLKCTL) & ~(DIAGLEDEN|DIAGLEDON));7212 7213 /*7214 * Return HS_MAILBOX to its default value.7215 */7216 ahd->hs_mailbox = 0;7217 ahd_outb(ahd, HS_MAILBOX, 0);7218 7219 /* Set the SCSI Id, SXFRCTL0, SXFRCTL1, and SIMODE1. */7220 ahd_outb(ahd, IOWNID, ahd->our_id);7221 ahd_outb(ahd, TOWNID, ahd->our_id);7222 sxfrctl1 = (ahd->flags & AHD_TERM_ENB_A) != 0 ? STPWEN : 0;7223 sxfrctl1 |= (ahd->flags & AHD_SPCHK_ENB_A) != 0 ? ENSPCHK : 0;7224 if ((ahd->bugs & AHD_LONG_SETIMO_BUG)7225 && (ahd->seltime != STIMESEL_MIN)) {7226 /*7227 * The selection timer duration is twice as long7228 * as it should be. Halve it by adding "1" to7229 * the user specified setting.7230 */7231 sxfrctl1 |= ahd->seltime + STIMESEL_BUG_ADJ;7232 } else {7233 sxfrctl1 |= ahd->seltime;7234 }7235 7236 ahd_outb(ahd, SXFRCTL0, DFON);7237 ahd_outb(ahd, SXFRCTL1, sxfrctl1|ahd->seltime|ENSTIMER|ACTNEGEN);7238 ahd_outb(ahd, SIMODE1, ENSELTIMO|ENSCSIRST|ENSCSIPERR);7239 7240 /*7241 * Now that termination is set, wait for up7242 * to 500ms for our transceivers to settle. If7243 * the adapter does not have a cable attached,7244 * the transceivers may never settle, so don't7245 * complain if we fail here.7246 */7247 for (wait = 10000;7248 (ahd_inb(ahd, SBLKCTL) & (ENAB40|ENAB20)) == 0 && wait;7249 wait--)7250 ahd_delay(100);7251 7252 /* Clear any false bus resets due to the transceivers settling */7253 ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI);7254 ahd_outb(ahd, CLRINT, CLRSCSIINT);7255 7256 /* Initialize mode specific S/G state. */7257 for (i = 0; i < 2; i++) {7258 ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i);7259 ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);7260 ahd_outb(ahd, SG_STATE, 0);7261 ahd_outb(ahd, CLRSEQINTSRC, 0xFF);7262 ahd_outb(ahd, SEQIMODE,7263 ENSAVEPTRS|ENCFG4DATA|ENCFG4ISTAT7264 |ENCFG4TSTAT|ENCFG4ICMD|ENCFG4TCMD);7265 }7266 7267 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);7268 ahd_outb(ahd, DSCOMMAND0, ahd_inb(ahd, DSCOMMAND0)|MPARCKEN|CACHETHEN);7269 ahd_outb(ahd, DFF_THRSH, RD_DFTHRSH_75|WR_DFTHRSH_75);7270 ahd_outb(ahd, SIMODE0, ENIOERR|ENOVERRUN);7271 ahd_outb(ahd, SIMODE3, ENNTRAMPERR|ENOSRAMPERR);7272 if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {7273 ahd_outb(ahd, OPTIONMODE, AUTOACKEN|AUTO_MSGOUT_DE);7274 } else {7275 ahd_outb(ahd, OPTIONMODE, AUTOACKEN|BUSFREEREV|AUTO_MSGOUT_DE);7276 }7277 ahd_outb(ahd, SCSCHKN, CURRFIFODEF|WIDERESEN|SHVALIDSTDIS);7278 if ((ahd->chip & AHD_BUS_MASK) == AHD_PCIX)7279 /*7280 * Do not issue a target abort when a split completion7281 * error occurs. Let our PCIX interrupt handler deal7282 * with it instead. H2A4 Razor #6257283 */7284 ahd_outb(ahd, PCIXCTL, ahd_inb(ahd, PCIXCTL) | SPLTSTADIS);7285 7286 if ((ahd->bugs & AHD_LQOOVERRUN_BUG) != 0)7287 ahd_outb(ahd, LQOSCSCTL, LQONOCHKOVER);7288 7289 /*7290 * Tweak IOCELL settings.7291 */7292 if ((ahd->flags & AHD_HP_BOARD) != 0) {7293 for (i = 0; i < NUMDSPS; i++) {7294 ahd_outb(ahd, DSPSELECT, i);7295 ahd_outb(ahd, WRTBIASCTL, WRTBIASCTL_HP_DEFAULT);7296 }7297#ifdef AHD_DEBUG7298 if ((ahd_debug & AHD_SHOW_MISC) != 0)7299 printk("%s: WRTBIASCTL now 0x%x\n", ahd_name(ahd),7300 WRTBIASCTL_HP_DEFAULT);7301#endif7302 }7303 ahd_setup_iocell_workaround(ahd);7304 7305 /*7306 * Enable LQI Manager interrupts.7307 */7308 ahd_outb(ahd, LQIMODE1, ENLQIPHASE_LQ|ENLQIPHASE_NLQ|ENLIQABORT7309 | ENLQICRCI_LQ|ENLQICRCI_NLQ|ENLQIBADLQI7310 | ENLQIOVERI_LQ|ENLQIOVERI_NLQ);7311 ahd_outb(ahd, LQOMODE0, ENLQOATNLQ|ENLQOATNPKT|ENLQOTCRC);7312 /*7313 * We choose to have the sequencer catch LQOPHCHGINPKT errors7314 * manually for the command phase at the start of a packetized7315 * selection case. ENLQOBUSFREE should be made redundant by7316 * the BUSFREE interrupt, but it seems that some LQOBUSFREE7317 * events fail to assert the BUSFREE interrupt so we must7318 * also enable LQOBUSFREE interrupts.7319 */7320 ahd_outb(ahd, LQOMODE1, ENLQOBUSFREE);7321 7322 /*7323 * Setup sequencer interrupt handlers.7324 */7325 ahd_outw(ahd, INTVEC1_ADDR, ahd_resolve_seqaddr(ahd, LABEL_seq_isr));7326 ahd_outw(ahd, INTVEC2_ADDR, ahd_resolve_seqaddr(ahd, LABEL_timer_isr));7327 7328 /*7329 * Setup SCB Offset registers.7330 */7331 if ((ahd->bugs & AHD_PKT_LUN_BUG) != 0) {7332 ahd_outb(ahd, LUNPTR, offsetof(struct hardware_scb,7333 pkt_long_lun));7334 } else {7335 ahd_outb(ahd, LUNPTR, offsetof(struct hardware_scb, lun));7336 }7337 ahd_outb(ahd, CMDLENPTR, offsetof(struct hardware_scb, cdb_len));7338 ahd_outb(ahd, ATTRPTR, offsetof(struct hardware_scb, task_attribute));7339 ahd_outb(ahd, FLAGPTR, offsetof(struct hardware_scb, task_management));7340 ahd_outb(ahd, CMDPTR, offsetof(struct hardware_scb,7341 shared_data.idata.cdb));7342 ahd_outb(ahd, QNEXTPTR,7343 offsetof(struct hardware_scb, next_hscb_busaddr));7344 ahd_outb(ahd, ABRTBITPTR, MK_MESSAGE_BIT_OFFSET);7345 ahd_outb(ahd, ABRTBYTEPTR, offsetof(struct hardware_scb, control));7346 if ((ahd->bugs & AHD_PKT_LUN_BUG) != 0) {7347 ahd_outb(ahd, LUNLEN,7348 sizeof(ahd->next_queued_hscb->pkt_long_lun) - 1);7349 } else {7350 ahd_outb(ahd, LUNLEN, LUNLEN_SINGLE_LEVEL_LUN);7351 }7352 ahd_outb(ahd, CDBLIMIT, SCB_CDB_LEN_PTR - 1);7353 ahd_outb(ahd, MAXCMD, 0xFF);7354 ahd_outb(ahd, SCBAUTOPTR,7355 AUSCBPTR_EN | offsetof(struct hardware_scb, tag));7356 7357 /* We haven't been enabled for target mode yet. */7358 ahd_outb(ahd, MULTARGID, 0);7359 ahd_outb(ahd, MULTARGID + 1, 0);7360 7361 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);7362 /* Initialize the negotiation table. */7363 if ((ahd->features & AHD_NEW_IOCELL_OPTS) == 0) {7364 /*7365 * Clear the spare bytes in the neg table to avoid7366 * spurious parity errors.7367 */7368 for (target = 0; target < AHD_NUM_TARGETS; target++) {7369 ahd_outb(ahd, NEGOADDR, target);7370 ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PER_DEV0);7371 for (i = 0; i < AHD_NUM_PER_DEV_ANNEXCOLS; i++)7372 ahd_outb(ahd, ANNEXDAT, 0);7373 }7374 }7375 for (target = 0; target < AHD_NUM_TARGETS; target++) {7376 struct ahd_devinfo devinfo;7377 struct ahd_initiator_tinfo *tinfo;7378 struct ahd_tmode_tstate *tstate;7379 7380 tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,7381 target, &tstate);7382 ahd_compile_devinfo(&devinfo, ahd->our_id,7383 target, CAM_LUN_WILDCARD,7384 'A', ROLE_INITIATOR);7385 ahd_update_neg_table(ahd, &devinfo, &tinfo->curr);7386 }7387 7388 ahd_outb(ahd, CLRSINT3, NTRAMPERR|OSRAMPERR);7389 ahd_outb(ahd, CLRINT, CLRSCSIINT);7390 7391#ifdef NEEDS_MORE_TESTING7392 /*7393 * Always enable abort on incoming L_Qs if this feature is7394 * supported. We use this to catch invalid SCB references.7395 */7396 if ((ahd->bugs & AHD_ABORT_LQI_BUG) == 0)7397 ahd_outb(ahd, LQCTL1, ABORTPENDING);7398 else7399#endif7400 ahd_outb(ahd, LQCTL1, 0);7401 7402 /* All of our queues are empty */7403 ahd->qoutfifonext = 0;7404 ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID;7405 ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID);7406 for (i = 0; i < AHD_QOUT_SIZE; i++)7407 ahd->qoutfifo[i].valid_tag = 0;7408 ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD);7409 7410 ahd->qinfifonext = 0;7411 for (i = 0; i < AHD_QIN_SIZE; i++)7412 ahd->qinfifo[i] = SCB_LIST_NULL;7413 7414 if ((ahd->features & AHD_TARGETMODE) != 0) {7415 /* All target command blocks start out invalid. */7416 for (i = 0; i < AHD_TMODE_CMDS; i++)7417 ahd->targetcmds[i].cmd_valid = 0;7418 ahd_sync_tqinfifo(ahd, BUS_DMASYNC_PREREAD);7419 ahd->tqinfifonext = 1;7420 ahd_outb(ahd, KERNEL_TQINPOS, ahd->tqinfifonext - 1);7421 ahd_outb(ahd, TQINPOS, ahd->tqinfifonext);7422 }7423 7424 /* Initialize Scratch Ram. */7425 ahd_outb(ahd, SEQ_FLAGS, 0);7426 ahd_outb(ahd, SEQ_FLAGS2, 0);7427 7428 /* We don't have any waiting selections */7429 ahd_outw(ahd, WAITING_TID_HEAD, SCB_LIST_NULL);7430 ahd_outw(ahd, WAITING_TID_TAIL, SCB_LIST_NULL);7431 ahd_outw(ahd, MK_MESSAGE_SCB, SCB_LIST_NULL);7432 ahd_outw(ahd, MK_MESSAGE_SCSIID, 0xFF);7433 for (i = 0; i < AHD_NUM_TARGETS; i++)7434 ahd_outw(ahd, WAITING_SCB_TAILS + (2 * i), SCB_LIST_NULL);7435 7436 /*7437 * Nobody is waiting to be DMAed into the QOUTFIFO.7438 */7439 ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);7440 ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL);7441 ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);7442 ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);7443 ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);7444 7445 /*7446 * The Freeze Count is 0.7447 */7448 ahd->qfreeze_cnt = 0;7449 ahd_outw(ahd, QFREEZE_COUNT, 0);7450 ahd_outw(ahd, KERNEL_QFREEZE_COUNT, 0);7451 7452 /*7453 * Tell the sequencer where it can find our arrays in memory.7454 */7455 busaddr = ahd->shared_data_map.physaddr;7456 ahd_outl(ahd, SHARED_DATA_ADDR, busaddr);7457 ahd_outl(ahd, QOUTFIFO_NEXT_ADDR, busaddr);7458 7459 /*7460 * Setup the allowed SCSI Sequences based on operational mode.7461 * If we are a target, we'll enable select in operations once7462 * we've had a lun enabled.7463 */7464 scsiseq_template = ENAUTOATNP;7465 if ((ahd->flags & AHD_INITIATORROLE) != 0)7466 scsiseq_template |= ENRSELI;7467 ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq_template);7468 7469 /* There are no busy SCBs yet. */7470 for (target = 0; target < AHD_NUM_TARGETS; target++) {7471 int lun;7472 7473 for (lun = 0; lun < AHD_NUM_LUNS_NONPKT; lun++)7474 ahd_unbusy_tcl(ahd, BUILD_TCL_RAW(target, 'A', lun));7475 }7476 7477 /*7478 * Initialize the group code to command length table.7479 * Vendor Unique codes are set to 0 so we only capture7480 * the first byte of the cdb. These can be overridden7481 * when target mode is enabled.7482 */7483 ahd_outb(ahd, CMDSIZE_TABLE, 5);7484 ahd_outb(ahd, CMDSIZE_TABLE + 1, 9);7485 ahd_outb(ahd, CMDSIZE_TABLE + 2, 9);7486 ahd_outb(ahd, CMDSIZE_TABLE + 3, 0);7487 ahd_outb(ahd, CMDSIZE_TABLE + 4, 15);7488 ahd_outb(ahd, CMDSIZE_TABLE + 5, 11);7489 ahd_outb(ahd, CMDSIZE_TABLE + 6, 0);7490 ahd_outb(ahd, CMDSIZE_TABLE + 7, 0);7491 7492 /* Tell the sequencer of our initial queue positions */7493 ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);7494 ahd_outb(ahd, QOFF_CTLSTA, SCB_QSIZE_512);7495 ahd->qinfifonext = 0;7496 ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);7497 ahd_set_hescb_qoff(ahd, 0);7498 ahd_set_snscb_qoff(ahd, 0);7499 ahd_set_sescb_qoff(ahd, 0);7500 ahd_set_sdscb_qoff(ahd, 0);7501 7502 /*7503 * Tell the sequencer which SCB will be the next one it receives.7504 */7505 busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);7506 ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);7507 7508 /*7509 * Default to coalescing disabled.7510 */7511 ahd_outw(ahd, INT_COALESCING_CMDCOUNT, 0);7512 ahd_outw(ahd, CMDS_PENDING, 0);7513 ahd_update_coalescing_values(ahd, ahd->int_coalescing_timer,7514 ahd->int_coalescing_maxcmds,7515 ahd->int_coalescing_mincmds);7516 ahd_enable_coalescing(ahd, FALSE);7517 7518 ahd_loadseq(ahd);7519 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);7520 7521 if (ahd->features & AHD_AIC79XXB_SLOWCRC) {7522 u_int negodat3 = ahd_inb(ahd, NEGCONOPTS);7523 7524 negodat3 |= ENSLOWCRC;7525 ahd_outb(ahd, NEGCONOPTS, negodat3);7526 negodat3 = ahd_inb(ahd, NEGCONOPTS);7527 if (!(negodat3 & ENSLOWCRC))7528 printk("aic79xx: failed to set the SLOWCRC bit\n");7529 else7530 printk("aic79xx: SLOWCRC bit set\n");7531 }7532}7533 7534/*7535 * Setup default device and controller settings.7536 * This should only be called if our probe has7537 * determined that no configuration data is available.7538 */7539int7540ahd_default_config(struct ahd_softc *ahd)7541{7542 int targ;7543 7544 ahd->our_id = 7;7545 7546 /*7547 * Allocate a tstate to house information for our7548 * initiator presence on the bus as well as the user7549 * data for any target mode initiator.7550 */7551 if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL) {7552 printk("%s: unable to allocate ahd_tmode_tstate. "7553 "Failing attach\n", ahd_name(ahd));7554 return (ENOMEM);7555 }7556 7557 for (targ = 0; targ < AHD_NUM_TARGETS; targ++) {7558 struct ahd_devinfo devinfo;7559 struct ahd_initiator_tinfo *tinfo;7560 struct ahd_tmode_tstate *tstate;7561 uint16_t target_mask;7562 7563 tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,7564 targ, &tstate);7565 /*7566 * We support SPC2 and SPI4.7567 */7568 tinfo->user.protocol_version = 4;7569 tinfo->user.transport_version = 4;7570 7571 target_mask = 0x01 << targ;7572 ahd->user_discenable |= target_mask;7573 tstate->discenable |= target_mask;7574 ahd->user_tagenable |= target_mask;7575#ifdef AHD_FORCE_1607576 tinfo->user.period = AHD_SYNCRATE_DT;7577#else7578 tinfo->user.period = AHD_SYNCRATE_160;7579#endif7580 tinfo->user.offset = MAX_OFFSET;7581 tinfo->user.ppr_options = MSG_EXT_PPR_RD_STRM7582 | MSG_EXT_PPR_WR_FLOW7583 | MSG_EXT_PPR_HOLD_MCS7584 | MSG_EXT_PPR_IU_REQ7585 | MSG_EXT_PPR_QAS_REQ7586 | MSG_EXT_PPR_DT_REQ;7587 if ((ahd->features & AHD_RTI) != 0)7588 tinfo->user.ppr_options |= MSG_EXT_PPR_RTI;7589 7590 tinfo->user.width = MSG_EXT_WDTR_BUS_16_BIT;7591 7592 /*7593 * Start out Async/Narrow/Untagged and with7594 * conservative protocol support.7595 */7596 tinfo->goal.protocol_version = 2;7597 tinfo->goal.transport_version = 2;7598 tinfo->curr.protocol_version = 2;7599 tinfo->curr.transport_version = 2;7600 ahd_compile_devinfo(&devinfo, ahd->our_id,7601 targ, CAM_LUN_WILDCARD,7602 'A', ROLE_INITIATOR);7603 tstate->tagenable &= ~target_mask;7604 ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,7605 AHD_TRANS_CUR|AHD_TRANS_GOAL, /*paused*/TRUE);7606 ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0,7607 /*ppr_options*/0, AHD_TRANS_CUR|AHD_TRANS_GOAL,7608 /*paused*/TRUE);7609 }7610 return (0);7611}7612 7613/*7614 * Parse device configuration information.7615 */7616int7617ahd_parse_cfgdata(struct ahd_softc *ahd, struct seeprom_config *sc)7618{7619 int targ;7620 int max_targ;7621 7622 max_targ = sc->max_targets & CFMAXTARG;7623 ahd->our_id = sc->brtime_id & CFSCSIID;7624 7625 /*7626 * Allocate a tstate to house information for our7627 * initiator presence on the bus as well as the user7628 * data for any target mode initiator.7629 */7630 if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL) {7631 printk("%s: unable to allocate ahd_tmode_tstate. "7632 "Failing attach\n", ahd_name(ahd));7633 return (ENOMEM);7634 }7635 7636 for (targ = 0; targ < max_targ; targ++) {7637 struct ahd_devinfo devinfo;7638 struct ahd_initiator_tinfo *tinfo;7639 struct ahd_transinfo *user_tinfo;7640 struct ahd_tmode_tstate *tstate;7641 uint16_t target_mask;7642 7643 tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,7644 targ, &tstate);7645 user_tinfo = &tinfo->user;7646 7647 /*7648 * We support SPC2 and SPI4.7649 */7650 tinfo->user.protocol_version = 4;7651 tinfo->user.transport_version = 4;7652 7653 target_mask = 0x01 << targ;7654 ahd->user_discenable &= ~target_mask;7655 tstate->discenable &= ~target_mask;7656 ahd->user_tagenable &= ~target_mask;7657 if (sc->device_flags[targ] & CFDISC) {7658 tstate->discenable |= target_mask;7659 ahd->user_discenable |= target_mask;7660 ahd->user_tagenable |= target_mask;7661 } else {7662 /*7663 * Cannot be packetized without disconnection.7664 */7665 sc->device_flags[targ] &= ~CFPACKETIZED;7666 }7667 7668 user_tinfo->ppr_options = 0;7669 user_tinfo->period = (sc->device_flags[targ] & CFXFER);7670 if (user_tinfo->period < CFXFER_ASYNC) {7671 if (user_tinfo->period <= AHD_PERIOD_10MHz)7672 user_tinfo->ppr_options |= MSG_EXT_PPR_DT_REQ;7673 user_tinfo->offset = MAX_OFFSET;7674 } else {7675 user_tinfo->offset = 0;7676 user_tinfo->period = AHD_ASYNC_XFER_PERIOD;7677 }7678#ifdef AHD_FORCE_1607679 if (user_tinfo->period <= AHD_SYNCRATE_160)7680 user_tinfo->period = AHD_SYNCRATE_DT;7681#endif7682 7683 if ((sc->device_flags[targ] & CFPACKETIZED) != 0) {7684 user_tinfo->ppr_options |= MSG_EXT_PPR_RD_STRM7685 | MSG_EXT_PPR_WR_FLOW7686 | MSG_EXT_PPR_HOLD_MCS7687 | MSG_EXT_PPR_IU_REQ;7688 if ((ahd->features & AHD_RTI) != 0)7689 user_tinfo->ppr_options |= MSG_EXT_PPR_RTI;7690 }7691 7692 if ((sc->device_flags[targ] & CFQAS) != 0)7693 user_tinfo->ppr_options |= MSG_EXT_PPR_QAS_REQ;7694 7695 if ((sc->device_flags[targ] & CFWIDEB) != 0)7696 user_tinfo->width = MSG_EXT_WDTR_BUS_16_BIT;7697 else7698 user_tinfo->width = MSG_EXT_WDTR_BUS_8_BIT;7699#ifdef AHD_DEBUG7700 if ((ahd_debug & AHD_SHOW_MISC) != 0)7701 printk("(%d): %x:%x:%x:%x\n", targ, user_tinfo->width,7702 user_tinfo->period, user_tinfo->offset,7703 user_tinfo->ppr_options);7704#endif7705 /*7706 * Start out Async/Narrow/Untagged and with7707 * conservative protocol support.7708 */7709 tstate->tagenable &= ~target_mask;7710 tinfo->goal.protocol_version = 2;7711 tinfo->goal.transport_version = 2;7712 tinfo->curr.protocol_version = 2;7713 tinfo->curr.transport_version = 2;7714 ahd_compile_devinfo(&devinfo, ahd->our_id,7715 targ, CAM_LUN_WILDCARD,7716 'A', ROLE_INITIATOR);7717 ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,7718 AHD_TRANS_CUR|AHD_TRANS_GOAL, /*paused*/TRUE);7719 ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0,7720 /*ppr_options*/0, AHD_TRANS_CUR|AHD_TRANS_GOAL,7721 /*paused*/TRUE);7722 }7723 7724 ahd->flags &= ~AHD_SPCHK_ENB_A;7725 if (sc->bios_control & CFSPARITY)7726 ahd->flags |= AHD_SPCHK_ENB_A;7727 7728 ahd->flags &= ~AHD_RESET_BUS_A;7729 if (sc->bios_control & CFRESETB)7730 ahd->flags |= AHD_RESET_BUS_A;7731 7732 ahd->flags &= ~AHD_EXTENDED_TRANS_A;7733 if (sc->bios_control & CFEXTEND)7734 ahd->flags |= AHD_EXTENDED_TRANS_A;7735 7736 ahd->flags &= ~AHD_BIOS_ENABLED;7737 if ((sc->bios_control & CFBIOSSTATE) == CFBS_ENABLED)7738 ahd->flags |= AHD_BIOS_ENABLED;7739 7740 ahd->flags &= ~AHD_STPWLEVEL_A;7741 if ((sc->adapter_control & CFSTPWLEVEL) != 0)7742 ahd->flags |= AHD_STPWLEVEL_A;7743 7744 return (0);7745}7746 7747/*7748 * Parse device configuration information.7749 */7750int7751ahd_parse_vpddata(struct ahd_softc *ahd, struct vpd_config *vpd)7752{7753 int error;7754 7755 error = ahd_verify_vpd_cksum(vpd);7756 if (error == 0)7757 return (EINVAL);7758 if ((vpd->bios_flags & VPDBOOTHOST) != 0)7759 ahd->flags |= AHD_BOOT_CHANNEL;7760 return (0);7761}7762 7763void7764ahd_intr_enable(struct ahd_softc *ahd, int enable)7765{7766 u_int hcntrl;7767 7768 hcntrl = ahd_inb(ahd, HCNTRL);7769 hcntrl &= ~INTEN;7770 ahd->pause &= ~INTEN;7771 ahd->unpause &= ~INTEN;7772 if (enable) {7773 hcntrl |= INTEN;7774 ahd->pause |= INTEN;7775 ahd->unpause |= INTEN;7776 }7777 ahd_outb(ahd, HCNTRL, hcntrl);7778}7779 7780static void7781ahd_update_coalescing_values(struct ahd_softc *ahd, u_int timer, u_int maxcmds,7782 u_int mincmds)7783{7784 if (timer > AHD_TIMER_MAX_US)7785 timer = AHD_TIMER_MAX_US;7786 ahd->int_coalescing_timer = timer;7787 7788 if (maxcmds > AHD_INT_COALESCING_MAXCMDS_MAX)7789 maxcmds = AHD_INT_COALESCING_MAXCMDS_MAX;7790 if (mincmds > AHD_INT_COALESCING_MINCMDS_MAX)7791 mincmds = AHD_INT_COALESCING_MINCMDS_MAX;7792 ahd->int_coalescing_maxcmds = maxcmds;7793 ahd_outw(ahd, INT_COALESCING_TIMER, timer / AHD_TIMER_US_PER_TICK);7794 ahd_outb(ahd, INT_COALESCING_MAXCMDS, -maxcmds);7795 ahd_outb(ahd, INT_COALESCING_MINCMDS, -mincmds);7796}7797 7798static void7799ahd_enable_coalescing(struct ahd_softc *ahd, int enable)7800{7801 7802 ahd->hs_mailbox &= ~ENINT_COALESCE;7803 if (enable)7804 ahd->hs_mailbox |= ENINT_COALESCE;7805 ahd_outb(ahd, HS_MAILBOX, ahd->hs_mailbox);7806 ahd_flush_device_writes(ahd);7807 ahd_run_qoutfifo(ahd);7808}7809 7810/*7811 * Ensure that the card is paused in a location7812 * outside of all critical sections and that all7813 * pending work is completed prior to returning.7814 * This routine should only be called from outside7815 * an interrupt context.7816 */7817void7818ahd_pause_and_flushwork(struct ahd_softc *ahd)7819{7820 u_int intstat;7821 u_int maxloops;7822 7823 maxloops = 1000;7824 ahd->flags |= AHD_ALL_INTERRUPTS;7825 ahd_pause(ahd);7826 /*7827 * Freeze the outgoing selections. We do this only7828 * until we are safely paused without further selections7829 * pending.7830 */7831 ahd->qfreeze_cnt--;7832 ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);7833 ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN);7834 do {7835 7836 ahd_unpause(ahd);7837 /*7838 * Give the sequencer some time to service7839 * any active selections.7840 */7841 ahd_delay(500);7842 7843 ahd_intr(ahd);7844 ahd_pause(ahd);7845 intstat = ahd_inb(ahd, INTSTAT);7846 if ((intstat & INT_PEND) == 0) {7847 ahd_clear_critical_section(ahd);7848 intstat = ahd_inb(ahd, INTSTAT);7849 }7850 } while (--maxloops7851 && (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0)7852 && ((intstat & INT_PEND) != 07853 || (ahd_inb(ahd, SCSISEQ0) & ENSELO) != 07854 || (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0));7855 7856 if (maxloops == 0) {7857 printk("Infinite interrupt loop, INTSTAT = %x",7858 ahd_inb(ahd, INTSTAT));7859 }7860 ahd->qfreeze_cnt++;7861 ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);7862 7863 ahd_flush_qoutfifo(ahd);7864 7865 ahd->flags &= ~AHD_ALL_INTERRUPTS;7866}7867 7868int __maybe_unused7869ahd_suspend(struct ahd_softc *ahd)7870{7871 ahd_pause_and_flushwork(ahd);7872 7873 if (LIST_FIRST(&ahd->pending_scbs) != NULL) {7874 ahd_unpause(ahd);7875 return (EBUSY);7876 }7877 ahd_shutdown(ahd);7878 return (0);7879}7880 7881void __maybe_unused7882ahd_resume(struct ahd_softc *ahd)7883{7884 ahd_reset(ahd, /*reinit*/TRUE);7885 ahd_intr_enable(ahd, TRUE);7886 ahd_restart(ahd);7887}7888 7889/************************** Busy Target Table *********************************/7890/*7891 * Set SCBPTR to the SCB that contains the busy7892 * table entry for TCL. Return the offset into7893 * the SCB that contains the entry for TCL.7894 * saved_scbid is dereferenced and set to the7895 * scbid that should be restored once manipualtion7896 * of the TCL entry is complete.7897 */7898static inline u_int7899ahd_index_busy_tcl(struct ahd_softc *ahd, u_int *saved_scbid, u_int tcl)7900{7901 /*7902 * Index to the SCB that contains the busy entry.7903 */7904 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);7905 *saved_scbid = ahd_get_scbptr(ahd);7906 ahd_set_scbptr(ahd, TCL_LUN(tcl)7907 | ((TCL_TARGET_OFFSET(tcl) & 0xC) << 4));7908 7909 /*7910 * And now calculate the SCB offset to the entry.7911 * Each entry is 2 bytes wide, hence the7912 * multiplication by 2.7913 */7914 return (((TCL_TARGET_OFFSET(tcl) & 0x3) << 1) + SCB_DISCONNECTED_LISTS);7915}7916 7917/*7918 * Return the untagged transaction id for a given target/channel lun.7919 */7920static u_int7921ahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl)7922{7923 u_int scbid;7924 u_int scb_offset;7925 u_int saved_scbptr;7926 7927 scb_offset = ahd_index_busy_tcl(ahd, &saved_scbptr, tcl);7928 scbid = ahd_inw_scbram(ahd, scb_offset);7929 ahd_set_scbptr(ahd, saved_scbptr);7930 return (scbid);7931}7932 7933static void7934ahd_busy_tcl(struct ahd_softc *ahd, u_int tcl, u_int scbid)7935{7936 u_int scb_offset;7937 u_int saved_scbptr;7938 7939 scb_offset = ahd_index_busy_tcl(ahd, &saved_scbptr, tcl);7940 ahd_outw(ahd, scb_offset, scbid);7941 ahd_set_scbptr(ahd, saved_scbptr);7942}7943 7944/************************** SCB and SCB queue management **********************/7945static int7946ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, int target,7947 char channel, int lun, u_int tag, role_t role)7948{7949 int targ = SCB_GET_TARGET(ahd, scb);7950 char chan = SCB_GET_CHANNEL(ahd, scb);7951 int slun = SCB_GET_LUN(scb);7952 int match;7953 7954 match = ((chan == channel) || (channel == ALL_CHANNELS));7955 if (match != 0)7956 match = ((targ == target) || (target == CAM_TARGET_WILDCARD));7957 if (match != 0)7958 match = ((lun == slun) || (lun == CAM_LUN_WILDCARD));7959 if (match != 0) {7960#ifdef AHD_TARGET_MODE7961 int group;7962 7963 group = XPT_FC_GROUP(scb->io_ctx->ccb_h.func_code);7964 if (role == ROLE_INITIATOR) {7965 match = (group != XPT_FC_GROUP_TMODE)7966 && ((tag == SCB_GET_TAG(scb))7967 || (tag == SCB_LIST_NULL));7968 } else if (role == ROLE_TARGET) {7969 match = (group == XPT_FC_GROUP_TMODE)7970 && ((tag == scb->io_ctx->csio.tag_id)7971 || (tag == SCB_LIST_NULL));7972 }7973#else /* !AHD_TARGET_MODE */7974 match = ((tag == SCB_GET_TAG(scb)) || (tag == SCB_LIST_NULL));7975#endif /* AHD_TARGET_MODE */7976 }7977 7978 return match;7979}7980 7981static void7982ahd_freeze_devq(struct ahd_softc *ahd, struct scb *scb)7983{7984 int target;7985 char channel;7986 int lun;7987 7988 target = SCB_GET_TARGET(ahd, scb);7989 lun = SCB_GET_LUN(scb);7990 channel = SCB_GET_CHANNEL(ahd, scb);7991 7992 ahd_search_qinfifo(ahd, target, channel, lun,7993 /*tag*/SCB_LIST_NULL, ROLE_UNKNOWN,7994 CAM_REQUEUE_REQ, SEARCH_COMPLETE);7995 7996 ahd_platform_freeze_devq(ahd, scb);7997}7998 7999void8000ahd_qinfifo_requeue_tail(struct ahd_softc *ahd, struct scb *scb)8001{8002 struct scb *prev_scb;8003 ahd_mode_state saved_modes;8004 8005 saved_modes = ahd_save_modes(ahd);8006 ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);8007 prev_scb = NULL;8008 if (ahd_qinfifo_count(ahd) != 0) {8009 u_int prev_tag;8010 u_int prev_pos;8011 8012 prev_pos = AHD_QIN_WRAP(ahd->qinfifonext - 1);8013 prev_tag = ahd->qinfifo[prev_pos];8014 prev_scb = ahd_lookup_scb(ahd, prev_tag);8015 }8016 ahd_qinfifo_requeue(ahd, prev_scb, scb);8017 ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);8018 ahd_restore_modes(ahd, saved_modes);8019}8020 8021static void8022ahd_qinfifo_requeue(struct ahd_softc *ahd, struct scb *prev_scb,8023 struct scb *scb)8024{8025 if (prev_scb == NULL) {8026 uint32_t busaddr;8027 8028 busaddr = ahd_le32toh(scb->hscb->hscb_busaddr);8029 ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);8030 } else {8031 prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr;8032 ahd_sync_scb(ahd, prev_scb,8033 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);8034 }8035 ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb);8036 ahd->qinfifonext++;8037 scb->hscb->next_hscb_busaddr = ahd->next_queued_hscb->hscb_busaddr;8038 ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);8039}8040 8041static int8042ahd_qinfifo_count(struct ahd_softc *ahd)8043{8044 u_int qinpos;8045 u_int wrap_qinpos;8046 u_int wrap_qinfifonext;8047 8048 AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK);8049 qinpos = ahd_get_snscb_qoff(ahd);8050 wrap_qinpos = AHD_QIN_WRAP(qinpos);8051 wrap_qinfifonext = AHD_QIN_WRAP(ahd->qinfifonext);8052 if (wrap_qinfifonext >= wrap_qinpos)8053 return (wrap_qinfifonext - wrap_qinpos);8054 else8055 return (wrap_qinfifonext8056 + ARRAY_SIZE(ahd->qinfifo) - wrap_qinpos);8057}8058 8059static void8060ahd_reset_cmds_pending(struct ahd_softc *ahd)8061{8062 struct scb *scb;8063 ahd_mode_state saved_modes;8064 u_int pending_cmds;8065 8066 saved_modes = ahd_save_modes(ahd);8067 ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);8068 8069 /*8070 * Don't count any commands as outstanding that the8071 * sequencer has already marked for completion.8072 */8073 ahd_flush_qoutfifo(ahd);8074 8075 pending_cmds = 0;8076 LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {8077 pending_cmds++;8078 }8079 ahd_outw(ahd, CMDS_PENDING, pending_cmds - ahd_qinfifo_count(ahd));8080 ahd_restore_modes(ahd, saved_modes);8081 ahd->flags &= ~AHD_UPDATE_PEND_CMDS;8082}8083 8084static void8085ahd_done_with_status(struct ahd_softc *ahd, struct scb *scb, uint32_t status)8086{8087 cam_status ostat;8088 cam_status cstat;8089 8090 ostat = ahd_get_transaction_status(scb);8091 if (ostat == CAM_REQ_INPROG)8092 ahd_set_transaction_status(scb, status);8093 cstat = ahd_get_transaction_status(scb);8094 if (cstat != CAM_REQ_CMP)8095 ahd_freeze_scb(scb);8096 ahd_done(ahd, scb);8097}8098 8099int8100ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,8101 int lun, u_int tag, role_t role, uint32_t status,8102 ahd_search_action action)8103{8104 struct scb *scb;8105 struct scb *mk_msg_scb;8106 struct scb *prev_scb;8107 ahd_mode_state saved_modes;8108 u_int qinstart;8109 u_int qinpos;8110 u_int qintail;8111 u_int tid_next;8112 u_int tid_prev;8113 u_int scbid;8114 u_int seq_flags2;8115 u_int savedscbptr;8116 uint32_t busaddr;8117 int found;8118 int targets;8119 8120 /* Must be in CCHAN mode */8121 saved_modes = ahd_save_modes(ahd);8122 ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);8123 8124 /*8125 * Halt any pending SCB DMA. The sequencer will reinitiate8126 * this dma if the qinfifo is not empty once we unpause.8127 */8128 if ((ahd_inb(ahd, CCSCBCTL) & (CCARREN|CCSCBEN|CCSCBDIR))8129 == (CCARREN|CCSCBEN|CCSCBDIR)) {8130 ahd_outb(ahd, CCSCBCTL,8131 ahd_inb(ahd, CCSCBCTL) & ~(CCARREN|CCSCBEN));8132 while ((ahd_inb(ahd, CCSCBCTL) & (CCARREN|CCSCBEN)) != 0)8133 ;8134 }8135 /* Determine sequencer's position in the qinfifo. */8136 qintail = AHD_QIN_WRAP(ahd->qinfifonext);8137 qinstart = ahd_get_snscb_qoff(ahd);8138 qinpos = AHD_QIN_WRAP(qinstart);8139 found = 0;8140 prev_scb = NULL;8141 8142 if (action == SEARCH_PRINT) {8143 printk("qinstart = %d qinfifonext = %d\nQINFIFO:",8144 qinstart, ahd->qinfifonext);8145 }8146 8147 /*8148 * Start with an empty queue. Entries that are not chosen8149 * for removal will be re-added to the queue as we go.8150 */8151 ahd->qinfifonext = qinstart;8152 busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);8153 ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr);8154 8155 while (qinpos != qintail) {8156 scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]);8157 if (scb == NULL) {8158 printk("qinpos = %d, SCB index = %d\n",8159 qinpos, ahd->qinfifo[qinpos]);8160 panic("Loop 1\n");8161 }8162 8163 if (ahd_match_scb(ahd, scb, target, channel, lun, tag, role)) {8164 /*8165 * We found an scb that needs to be acted on.8166 */8167 found++;8168 switch (action) {8169 case SEARCH_COMPLETE:8170 if ((scb->flags & SCB_ACTIVE) == 0)8171 printk("Inactive SCB in qinfifo\n");8172 ahd_done_with_status(ahd, scb, status);8173 fallthrough;8174 case SEARCH_REMOVE:8175 break;8176 case SEARCH_PRINT:8177 printk(" 0x%x", ahd->qinfifo[qinpos]);8178 fallthrough;8179 case SEARCH_COUNT:8180 ahd_qinfifo_requeue(ahd, prev_scb, scb);8181 prev_scb = scb;8182 break;8183 }8184 } else {8185 ahd_qinfifo_requeue(ahd, prev_scb, scb);8186 prev_scb = scb;8187 }8188 qinpos = AHD_QIN_WRAP(qinpos+1);8189 }8190 8191 ahd_set_hnscb_qoff(ahd, ahd->qinfifonext);8192 8193 if (action == SEARCH_PRINT)8194 printk("\nWAITING_TID_QUEUES:\n");8195 8196 /*8197 * Search waiting for selection lists. We traverse the8198 * list of "their ids" waiting for selection and, if8199 * appropriate, traverse the SCBs of each "their id"8200 * looking for matches.8201 */8202 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);8203 seq_flags2 = ahd_inb(ahd, SEQ_FLAGS2);8204 if ((seq_flags2 & PENDING_MK_MESSAGE) != 0) {8205 scbid = ahd_inw(ahd, MK_MESSAGE_SCB);8206 mk_msg_scb = ahd_lookup_scb(ahd, scbid);8207 } else8208 mk_msg_scb = NULL;8209 savedscbptr = ahd_get_scbptr(ahd);8210 tid_next = ahd_inw(ahd, WAITING_TID_HEAD);8211 tid_prev = SCB_LIST_NULL;8212 targets = 0;8213 for (scbid = tid_next; !SCBID_IS_NULL(scbid); scbid = tid_next) {8214 u_int tid_head;8215 u_int tid_tail;8216 8217 targets++;8218 if (targets > AHD_NUM_TARGETS)8219 panic("TID LIST LOOP");8220 8221 if (scbid >= ahd->scb_data.numscbs) {8222 printk("%s: Waiting TID List inconsistency. "8223 "SCB index == 0x%x, yet numscbs == 0x%x.",8224 ahd_name(ahd), scbid, ahd->scb_data.numscbs);8225 ahd_dump_card_state(ahd);8226 panic("for safety");8227 }8228 scb = ahd_lookup_scb(ahd, scbid);8229 if (scb == NULL) {8230 printk("%s: SCB = 0x%x Not Active!\n",8231 ahd_name(ahd), scbid);8232 panic("Waiting TID List traversal\n");8233 }8234 ahd_set_scbptr(ahd, scbid);8235 tid_next = ahd_inw_scbram(ahd, SCB_NEXT2);8236 if (ahd_match_scb(ahd, scb, target, channel, CAM_LUN_WILDCARD,8237 SCB_LIST_NULL, ROLE_UNKNOWN) == 0) {8238 tid_prev = scbid;8239 continue;8240 }8241 8242 /*8243 * We found a list of scbs that needs to be searched.8244 */8245 if (action == SEARCH_PRINT)8246 printk(" %d ( ", SCB_GET_TARGET(ahd, scb));8247 tid_head = scbid;8248 found += ahd_search_scb_list(ahd, target, channel,8249 lun, tag, role, status,8250 action, &tid_head, &tid_tail,8251 SCB_GET_TARGET(ahd, scb));8252 /*8253 * Check any MK_MESSAGE SCB that is still waiting to8254 * enter this target's waiting for selection queue.8255 */8256 if (mk_msg_scb != NULL8257 && ahd_match_scb(ahd, mk_msg_scb, target, channel,8258 lun, tag, role)) {8259 8260 /*8261 * We found an scb that needs to be acted on.8262 */8263 found++;8264 switch (action) {8265 case SEARCH_COMPLETE:8266 if ((mk_msg_scb->flags & SCB_ACTIVE) == 0)8267 printk("Inactive SCB pending MK_MSG\n");8268 ahd_done_with_status(ahd, mk_msg_scb, status);8269 fallthrough;8270 case SEARCH_REMOVE:8271 {8272 u_int tail_offset;8273 8274 printk("Removing MK_MSG scb\n");8275 8276 /*8277 * Reset our tail to the tail of the8278 * main per-target list.8279 */8280 tail_offset = WAITING_SCB_TAILS8281 + (2 * SCB_GET_TARGET(ahd, mk_msg_scb));8282 ahd_outw(ahd, tail_offset, tid_tail);8283 8284 seq_flags2 &= ~PENDING_MK_MESSAGE;8285 ahd_outb(ahd, SEQ_FLAGS2, seq_flags2);8286 ahd_outw(ahd, CMDS_PENDING,8287 ahd_inw(ahd, CMDS_PENDING)-1);8288 mk_msg_scb = NULL;8289 break;8290 }8291 case SEARCH_PRINT:8292 printk(" 0x%x", SCB_GET_TAG(scb));8293 fallthrough;8294 case SEARCH_COUNT:8295 break;8296 }8297 }8298 8299 if (mk_msg_scb != NULL8300 && SCBID_IS_NULL(tid_head)8301 && ahd_match_scb(ahd, scb, target, channel, CAM_LUN_WILDCARD,8302 SCB_LIST_NULL, ROLE_UNKNOWN)) {8303 8304 /*8305 * When removing the last SCB for a target8306 * queue with a pending MK_MESSAGE scb, we8307 * must queue the MK_MESSAGE scb.8308 */8309 printk("Queueing mk_msg_scb\n");8310 tid_head = ahd_inw(ahd, MK_MESSAGE_SCB);8311 seq_flags2 &= ~PENDING_MK_MESSAGE;8312 ahd_outb(ahd, SEQ_FLAGS2, seq_flags2);8313 mk_msg_scb = NULL;8314 }8315 if (tid_head != scbid)8316 ahd_stitch_tid_list(ahd, tid_prev, tid_head, tid_next);8317 if (!SCBID_IS_NULL(tid_head))8318 tid_prev = tid_head;8319 if (action == SEARCH_PRINT)8320 printk(")\n");8321 }8322 8323 /* Restore saved state. */8324 ahd_set_scbptr(ahd, savedscbptr);8325 ahd_restore_modes(ahd, saved_modes);8326 return (found);8327}8328 8329static int8330ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel,8331 int lun, u_int tag, role_t role, uint32_t status,8332 ahd_search_action action, u_int *list_head,8333 u_int *list_tail, u_int tid)8334{8335 struct scb *scb;8336 u_int scbid;8337 u_int next;8338 u_int prev;8339 int found;8340 8341 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);8342 found = 0;8343 prev = SCB_LIST_NULL;8344 next = *list_head;8345 *list_tail = SCB_LIST_NULL;8346 for (scbid = next; !SCBID_IS_NULL(scbid); scbid = next) {8347 if (scbid >= ahd->scb_data.numscbs) {8348 printk("%s:SCB List inconsistency. "8349 "SCB == 0x%x, yet numscbs == 0x%x.",8350 ahd_name(ahd), scbid, ahd->scb_data.numscbs);8351 ahd_dump_card_state(ahd);8352 panic("for safety");8353 }8354 scb = ahd_lookup_scb(ahd, scbid);8355 if (scb == NULL) {8356 printk("%s: SCB = %d Not Active!\n",8357 ahd_name(ahd), scbid);8358 panic("Waiting List traversal\n");8359 }8360 ahd_set_scbptr(ahd, scbid);8361 *list_tail = scbid;8362 next = ahd_inw_scbram(ahd, SCB_NEXT);8363 if (ahd_match_scb(ahd, scb, target, channel,8364 lun, SCB_LIST_NULL, role) == 0) {8365 prev = scbid;8366 continue;8367 }8368 found++;8369 switch (action) {8370 case SEARCH_COMPLETE:8371 if ((scb->flags & SCB_ACTIVE) == 0)8372 printk("Inactive SCB in Waiting List\n");8373 ahd_done_with_status(ahd, scb, status);8374 fallthrough;8375 case SEARCH_REMOVE:8376 ahd_rem_wscb(ahd, scbid, prev, next, tid);8377 *list_tail = prev;8378 if (SCBID_IS_NULL(prev))8379 *list_head = next;8380 break;8381 case SEARCH_PRINT:8382 printk("0x%x ", scbid);8383 fallthrough;8384 case SEARCH_COUNT:8385 prev = scbid;8386 break;8387 }8388 if (found > AHD_SCB_MAX)8389 panic("SCB LIST LOOP");8390 }8391 if (action == SEARCH_COMPLETE8392 || action == SEARCH_REMOVE)8393 ahd_outw(ahd, CMDS_PENDING, ahd_inw(ahd, CMDS_PENDING) - found);8394 return (found);8395}8396 8397static void8398ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev,8399 u_int tid_cur, u_int tid_next)8400{8401 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);8402 8403 if (SCBID_IS_NULL(tid_cur)) {8404 8405 /* Bypass current TID list */8406 if (SCBID_IS_NULL(tid_prev)) {8407 ahd_outw(ahd, WAITING_TID_HEAD, tid_next);8408 } else {8409 ahd_set_scbptr(ahd, tid_prev);8410 ahd_outw(ahd, SCB_NEXT2, tid_next);8411 }8412 if (SCBID_IS_NULL(tid_next))8413 ahd_outw(ahd, WAITING_TID_TAIL, tid_prev);8414 } else {8415 8416 /* Stitch through tid_cur */8417 if (SCBID_IS_NULL(tid_prev)) {8418 ahd_outw(ahd, WAITING_TID_HEAD, tid_cur);8419 } else {8420 ahd_set_scbptr(ahd, tid_prev);8421 ahd_outw(ahd, SCB_NEXT2, tid_cur);8422 }8423 ahd_set_scbptr(ahd, tid_cur);8424 ahd_outw(ahd, SCB_NEXT2, tid_next);8425 8426 if (SCBID_IS_NULL(tid_next))8427 ahd_outw(ahd, WAITING_TID_TAIL, tid_cur);8428 }8429}8430 8431/*8432 * Manipulate the waiting for selection list and return the8433 * scb that follows the one that we remove.8434 */8435static u_int8436ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid,8437 u_int prev, u_int next, u_int tid)8438{8439 u_int tail_offset;8440 8441 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);8442 if (!SCBID_IS_NULL(prev)) {8443 ahd_set_scbptr(ahd, prev);8444 ahd_outw(ahd, SCB_NEXT, next);8445 }8446 8447 /*8448 * SCBs that have MK_MESSAGE set in them may8449 * cause the tail pointer to be updated without8450 * setting the next pointer of the previous tail.8451 * Only clear the tail if the removed SCB was8452 * the tail.8453 */8454 tail_offset = WAITING_SCB_TAILS + (2 * tid);8455 if (SCBID_IS_NULL(next)8456 && ahd_inw(ahd, tail_offset) == scbid)8457 ahd_outw(ahd, tail_offset, prev);8458 8459 ahd_add_scb_to_free_list(ahd, scbid);8460 return (next);8461}8462 8463/*8464 * Add the SCB as selected by SCBPTR onto the on chip list of8465 * free hardware SCBs. This list is empty/unused if we are not8466 * performing SCB paging.8467 */8468static void8469ahd_add_scb_to_free_list(struct ahd_softc *ahd, u_int scbid)8470{8471/* XXX Need some other mechanism to designate "free". */8472 /*8473 * Invalidate the tag so that our abort8474 * routines don't think it's active.8475 ahd_outb(ahd, SCB_TAG, SCB_LIST_NULL);8476 */8477}8478 8479/******************************** Error Handling ******************************/8480/*8481 * Abort all SCBs that match the given description (target/channel/lun/tag),8482 * setting their status to the passed in status if the status has not already8483 * been modified from CAM_REQ_INPROG. This routine assumes that the sequencer8484 * is paused before it is called.8485 */8486static int8487ahd_abort_scbs(struct ahd_softc *ahd, int target, char channel,8488 int lun, u_int tag, role_t role, uint32_t status)8489{8490 struct scb *scbp;8491 struct scb *scbp_next;8492 u_int i, j;8493 u_int maxtarget;8494 u_int minlun;8495 u_int maxlun;8496 int found;8497 ahd_mode_state saved_modes;8498 8499 /* restore this when we're done */8500 saved_modes = ahd_save_modes(ahd);8501 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);8502 8503 found = ahd_search_qinfifo(ahd, target, channel, lun, SCB_LIST_NULL,8504 role, CAM_REQUEUE_REQ, SEARCH_COMPLETE);8505 8506 /*8507 * Clean out the busy target table for any untagged commands.8508 */8509 i = 0;8510 maxtarget = 16;8511 if (target != CAM_TARGET_WILDCARD) {8512 i = target;8513 if (channel == 'B')8514 i += 8;8515 maxtarget = i + 1;8516 }8517 8518 if (lun == CAM_LUN_WILDCARD) {8519 minlun = 0;8520 maxlun = AHD_NUM_LUNS_NONPKT;8521 } else if (lun >= AHD_NUM_LUNS_NONPKT) {8522 minlun = maxlun = 0;8523 } else {8524 minlun = lun;8525 maxlun = lun + 1;8526 }8527 8528 if (role != ROLE_TARGET) {8529 for (;i < maxtarget; i++) {8530 for (j = minlun;j < maxlun; j++) {8531 u_int scbid;8532 u_int tcl;8533 8534 tcl = BUILD_TCL_RAW(i, 'A', j);8535 scbid = ahd_find_busy_tcl(ahd, tcl);8536 scbp = ahd_lookup_scb(ahd, scbid);8537 if (scbp == NULL8538 || ahd_match_scb(ahd, scbp, target, channel,8539 lun, tag, role) == 0)8540 continue;8541 ahd_unbusy_tcl(ahd, BUILD_TCL_RAW(i, 'A', j));8542 }8543 }8544 }8545 8546 /*8547 * Don't abort commands that have already completed,8548 * but haven't quite made it up to the host yet.8549 */8550 ahd_flush_qoutfifo(ahd);8551 8552 /*8553 * Go through the pending CCB list and look for8554 * commands for this target that are still active.8555 * These are other tagged commands that were8556 * disconnected when the reset occurred.8557 */8558 scbp_next = LIST_FIRST(&ahd->pending_scbs);8559 while (scbp_next != NULL) {8560 scbp = scbp_next;8561 scbp_next = LIST_NEXT(scbp, pending_links);8562 if (ahd_match_scb(ahd, scbp, target, channel, lun, tag, role)) {8563 cam_status ostat;8564 8565 ostat = ahd_get_transaction_status(scbp);8566 if (ostat == CAM_REQ_INPROG)8567 ahd_set_transaction_status(scbp, status);8568 if (ahd_get_transaction_status(scbp) != CAM_REQ_CMP)8569 ahd_freeze_scb(scbp);8570 if ((scbp->flags & SCB_ACTIVE) == 0)8571 printk("Inactive SCB on pending list\n");8572 ahd_done(ahd, scbp);8573 found++;8574 }8575 }8576 ahd_restore_modes(ahd, saved_modes);8577 ahd_platform_abort_scbs(ahd, target, channel, lun, tag, role, status);8578 ahd->flags |= AHD_UPDATE_PEND_CMDS;8579 return found;8580}8581 8582static void8583ahd_reset_current_bus(struct ahd_softc *ahd)8584{8585 uint8_t scsiseq;8586 8587 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);8588 ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) & ~ENSCSIRST);8589 scsiseq = ahd_inb(ahd, SCSISEQ0) & ~(ENSELO|ENARBO|SCSIRSTO);8590 ahd_outb(ahd, SCSISEQ0, scsiseq | SCSIRSTO);8591 ahd_flush_device_writes(ahd);8592 ahd_delay(AHD_BUSRESET_DELAY);8593 /* Turn off the bus reset */8594 ahd_outb(ahd, SCSISEQ0, scsiseq);8595 ahd_flush_device_writes(ahd);8596 ahd_delay(AHD_BUSRESET_DELAY);8597 if ((ahd->bugs & AHD_SCSIRST_BUG) != 0) {8598 /*8599 * 2A Razor #4748600 * Certain chip state is not cleared for8601 * SCSI bus resets that we initiate, so8602 * we must reset the chip.8603 */8604 ahd_reset(ahd, /*reinit*/TRUE);8605 ahd_intr_enable(ahd, /*enable*/TRUE);8606 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);8607 }8608 8609 ahd_clear_intstat(ahd);8610}8611 8612int8613ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset)8614{8615 struct ahd_devinfo caminfo;8616 u_int initiator;8617 u_int target;8618 u_int max_scsiid;8619 int found;8620 u_int fifo;8621 u_int next_fifo;8622 uint8_t scsiseq;8623 8624 /*8625 * Check if the last bus reset is cleared8626 */8627 if (ahd->flags & AHD_BUS_RESET_ACTIVE) {8628 printk("%s: bus reset still active\n",8629 ahd_name(ahd));8630 return 0;8631 }8632 ahd->flags |= AHD_BUS_RESET_ACTIVE;8633 8634 ahd->pending_device = NULL;8635 8636 ahd_compile_devinfo(&caminfo,8637 CAM_TARGET_WILDCARD,8638 CAM_TARGET_WILDCARD,8639 CAM_LUN_WILDCARD,8640 channel, ROLE_UNKNOWN);8641 ahd_pause(ahd);8642 8643 /* Make sure the sequencer is in a safe location. */8644 ahd_clear_critical_section(ahd);8645 8646 /*8647 * Run our command complete fifos to ensure that we perform8648 * completion processing on any commands that 'completed'8649 * before the reset occurred.8650 */8651 ahd_run_qoutfifo(ahd);8652#ifdef AHD_TARGET_MODE8653 if ((ahd->flags & AHD_TARGETROLE) != 0) {8654 ahd_run_tqinfifo(ahd, /*paused*/TRUE);8655 }8656#endif8657 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);8658 8659 /*8660 * Disable selections so no automatic hardware8661 * functions will modify chip state.8662 */8663 ahd_outb(ahd, SCSISEQ0, 0);8664 ahd_outb(ahd, SCSISEQ1, 0);8665 8666 /*8667 * Safely shut down our DMA engines. Always start with8668 * the FIFO that is not currently active (if any are8669 * actively connected).8670 */8671 next_fifo = fifo = ahd_inb(ahd, DFFSTAT) & CURRFIFO;8672 if (next_fifo > CURRFIFO_1)8673 /* If disconneced, arbitrarily start with FIFO1. */8674 next_fifo = fifo = 0;8675 do {8676 next_fifo ^= CURRFIFO_1;8677 ahd_set_modes(ahd, next_fifo, next_fifo);8678 ahd_outb(ahd, DFCNTRL,8679 ahd_inb(ahd, DFCNTRL) & ~(SCSIEN|HDMAEN));8680 while ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0)8681 ahd_delay(10);8682 /*8683 * Set CURRFIFO to the now inactive channel.8684 */8685 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);8686 ahd_outb(ahd, DFFSTAT, next_fifo);8687 } while (next_fifo != fifo);8688 8689 /*8690 * Reset the bus if we are initiating this reset8691 */8692 ahd_clear_msg_state(ahd);8693 ahd_outb(ahd, SIMODE1,8694 ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST));8695 8696 if (initiate_reset)8697 ahd_reset_current_bus(ahd);8698 8699 ahd_clear_intstat(ahd);8700 8701 /*8702 * Clean up all the state information for the8703 * pending transactions on this bus.8704 */8705 found = ahd_abort_scbs(ahd, CAM_TARGET_WILDCARD, channel,8706 CAM_LUN_WILDCARD, SCB_LIST_NULL,8707 ROLE_UNKNOWN, CAM_SCSI_BUS_RESET);8708 8709 /*8710 * Cleanup anything left in the FIFOs.8711 */8712 ahd_clear_fifo(ahd, 0);8713 ahd_clear_fifo(ahd, 1);8714 8715 /*8716 * Clear SCSI interrupt status8717 */8718 ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI);8719 8720 /*8721 * Reenable selections8722 */8723 ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST);8724 scsiseq = ahd_inb(ahd, SCSISEQ_TEMPLATE);8725 ahd_outb(ahd, SCSISEQ1, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP));8726 8727 max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7;8728#ifdef AHD_TARGET_MODE8729 /*8730 * Send an immediate notify ccb to all target more peripheral8731 * drivers affected by this action.8732 */8733 for (target = 0; target <= max_scsiid; target++) {8734 struct ahd_tmode_tstate* tstate;8735 u_int lun;8736 8737 tstate = ahd->enabled_targets[target];8738 if (tstate == NULL)8739 continue;8740 for (lun = 0; lun < AHD_NUM_LUNS; lun++) {8741 struct ahd_tmode_lstate* lstate;8742 8743 lstate = tstate->enabled_luns[lun];8744 if (lstate == NULL)8745 continue;8746 8747 ahd_queue_lstate_event(ahd, lstate, CAM_TARGET_WILDCARD,8748 EVENT_TYPE_BUS_RESET, /*arg*/0);8749 ahd_send_lstate_events(ahd, lstate);8750 }8751 }8752#endif8753 /*8754 * Revert to async/narrow transfers until we renegotiate.8755 */8756 for (target = 0; target <= max_scsiid; target++) {8757 8758 if (ahd->enabled_targets[target] == NULL)8759 continue;8760 for (initiator = 0; initiator <= max_scsiid; initiator++) {8761 struct ahd_devinfo devinfo;8762 8763 ahd_compile_devinfo(&devinfo, target, initiator,8764 CAM_LUN_WILDCARD,8765 'A', ROLE_UNKNOWN);8766 ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,8767 AHD_TRANS_CUR, /*paused*/TRUE);8768 ahd_set_syncrate(ahd, &devinfo, /*period*/0,8769 /*offset*/0, /*ppr_options*/0,8770 AHD_TRANS_CUR, /*paused*/TRUE);8771 }8772 }8773 8774 /* Notify the XPT that a bus reset occurred */8775 ahd_send_async(ahd, caminfo.channel, CAM_TARGET_WILDCARD,8776 CAM_LUN_WILDCARD, AC_BUS_RESET);8777 8778 ahd_restart(ahd);8779 8780 return (found);8781}8782 8783/**************************** Statistics Processing ***************************/8784static void8785ahd_stat_timer(struct timer_list *t)8786{8787 struct ahd_softc *ahd = from_timer(ahd, t, stat_timer);8788 u_long s;8789 int enint_coal;8790 8791 ahd_lock(ahd, &s);8792 8793 enint_coal = ahd->hs_mailbox & ENINT_COALESCE;8794 if (ahd->cmdcmplt_total > ahd->int_coalescing_threshold)8795 enint_coal |= ENINT_COALESCE;8796 else if (ahd->cmdcmplt_total < ahd->int_coalescing_stop_threshold)8797 enint_coal &= ~ENINT_COALESCE;8798 8799 if (enint_coal != (ahd->hs_mailbox & ENINT_COALESCE)) {8800 ahd_enable_coalescing(ahd, enint_coal);8801#ifdef AHD_DEBUG8802 if ((ahd_debug & AHD_SHOW_INT_COALESCING) != 0)8803 printk("%s: Interrupt coalescing "8804 "now %sabled. Cmds %d\n",8805 ahd_name(ahd),8806 (enint_coal & ENINT_COALESCE) ? "en" : "dis",8807 ahd->cmdcmplt_total);8808#endif8809 }8810 8811 ahd->cmdcmplt_bucket = (ahd->cmdcmplt_bucket+1) & (AHD_STAT_BUCKETS-1);8812 ahd->cmdcmplt_total -= ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket];8813 ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket] = 0;8814 ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US);8815 ahd_unlock(ahd, &s);8816}8817 8818/****************************** Status Processing *****************************/8819 8820static void8821ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)8822{8823 struct hardware_scb *hscb;8824 int paused;8825 8826 /*8827 * The sequencer freezes its select-out queue8828 * anytime a SCSI status error occurs. We must8829 * handle the error and increment our qfreeze count8830 * to allow the sequencer to continue. We don't8831 * bother clearing critical sections here since all8832 * operations are on data structures that the sequencer8833 * is not touching once the queue is frozen.8834 */8835 hscb = scb->hscb;8836 8837 if (ahd_is_paused(ahd)) {8838 paused = 1;8839 } else {8840 paused = 0;8841 ahd_pause(ahd);8842 }8843 8844 /* Freeze the queue until the client sees the error. */8845 ahd_freeze_devq(ahd, scb);8846 ahd_freeze_scb(scb);8847 ahd->qfreeze_cnt++;8848 ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);8849 8850 if (paused == 0)8851 ahd_unpause(ahd);8852 8853 /* Don't want to clobber the original sense code */8854 if ((scb->flags & SCB_SENSE) != 0) {8855 /*8856 * Clear the SCB_SENSE Flag and perform8857 * a normal command completion.8858 */8859 scb->flags &= ~SCB_SENSE;8860 ahd_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);8861 ahd_done(ahd, scb);8862 return;8863 }8864 ahd_set_transaction_status(scb, CAM_SCSI_STATUS_ERROR);8865 ahd_set_scsi_status(scb, hscb->shared_data.istatus.scsi_status);8866 switch (hscb->shared_data.istatus.scsi_status) {8867 case STATUS_PKT_SENSE:8868 {8869 struct scsi_status_iu_header *siu;8870 8871 ahd_sync_sense(ahd, scb, BUS_DMASYNC_POSTREAD);8872 siu = (struct scsi_status_iu_header *)scb->sense_data;8873 ahd_set_scsi_status(scb, siu->status);8874#ifdef AHD_DEBUG8875 if ((ahd_debug & AHD_SHOW_SENSE) != 0) {8876 ahd_print_path(ahd, scb);8877 printk("SCB 0x%x Received PKT Status of 0x%x\n",8878 SCB_GET_TAG(scb), siu->status);8879 printk("\tflags = 0x%x, sense len = 0x%x, "8880 "pktfail = 0x%x\n",8881 siu->flags, scsi_4btoul(siu->sense_length),8882 scsi_4btoul(siu->pkt_failures_length));8883 }8884#endif8885 if ((siu->flags & SIU_RSPVALID) != 0) {8886 ahd_print_path(ahd, scb);8887 if (scsi_4btoul(siu->pkt_failures_length) < 4) {8888 printk("Unable to parse pkt_failures\n");8889 } else {8890 8891 switch (SIU_PKTFAIL_CODE(siu)) {8892 case SIU_PFC_NONE:8893 printk("No packet failure found\n");8894 break;8895 case SIU_PFC_CIU_FIELDS_INVALID:8896 printk("Invalid Command IU Field\n");8897 break;8898 case SIU_PFC_TMF_NOT_SUPPORTED:8899 printk("TMF not supported\n");8900 break;8901 case SIU_PFC_TMF_FAILED:8902 printk("TMF failed\n");8903 break;8904 case SIU_PFC_INVALID_TYPE_CODE:8905 printk("Invalid L_Q Type code\n");8906 break;8907 case SIU_PFC_ILLEGAL_REQUEST:8908 printk("Illegal request\n");8909 break;8910 default:8911 break;8912 }8913 }8914 if (siu->status == SAM_STAT_GOOD)8915 ahd_set_transaction_status(scb,8916 CAM_REQ_CMP_ERR);8917 }8918 if ((siu->flags & SIU_SNSVALID) != 0) {8919 scb->flags |= SCB_PKT_SENSE;8920#ifdef AHD_DEBUG8921 if ((ahd_debug & AHD_SHOW_SENSE) != 0)8922 printk("Sense data available\n");8923#endif8924 }8925 ahd_done(ahd, scb);8926 break;8927 }8928 case SAM_STAT_COMMAND_TERMINATED:8929 case SAM_STAT_CHECK_CONDITION:8930 {8931 struct ahd_devinfo devinfo;8932 struct ahd_dma_seg *sg;8933 struct scsi_sense *sc;8934 struct ahd_initiator_tinfo *targ_info;8935 struct ahd_tmode_tstate *tstate;8936 struct ahd_transinfo *tinfo;8937#ifdef AHD_DEBUG8938 if (ahd_debug & AHD_SHOW_SENSE) {8939 ahd_print_path(ahd, scb);8940 printk("SCB %d: requests Check Status\n",8941 SCB_GET_TAG(scb));8942 }8943#endif8944 8945 if (ahd_perform_autosense(scb) == 0)8946 break;8947 8948 ahd_compile_devinfo(&devinfo, SCB_GET_OUR_ID(scb),8949 SCB_GET_TARGET(ahd, scb),8950 SCB_GET_LUN(scb),8951 SCB_GET_CHANNEL(ahd, scb),8952 ROLE_INITIATOR);8953 targ_info = ahd_fetch_transinfo(ahd,8954 devinfo.channel,8955 devinfo.our_scsiid,8956 devinfo.target,8957 &tstate);8958 tinfo = &targ_info->curr;8959 sg = scb->sg_list;8960 sc = (struct scsi_sense *)hscb->shared_data.idata.cdb;8961 /*8962 * Save off the residual if there is one.8963 */8964 ahd_update_residual(ahd, scb);8965#ifdef AHD_DEBUG8966 if (ahd_debug & AHD_SHOW_SENSE) {8967 ahd_print_path(ahd, scb);8968 printk("Sending Sense\n");8969 }8970#endif8971 scb->sg_count = 0;8972 sg = ahd_sg_setup(ahd, scb, sg, ahd_get_sense_bufaddr(ahd, scb),8973 ahd_get_sense_bufsize(ahd, scb),8974 /*last*/TRUE);8975 sc->opcode = REQUEST_SENSE;8976 sc->byte2 = 0;8977 if (tinfo->protocol_version <= SCSI_REV_28978 && SCB_GET_LUN(scb) < 8)8979 sc->byte2 = SCB_GET_LUN(scb) << 5;8980 sc->unused[0] = 0;8981 sc->unused[1] = 0;8982 sc->length = ahd_get_sense_bufsize(ahd, scb);8983 sc->control = 0;8984 8985 /*8986 * We can't allow the target to disconnect.8987 * This will be an untagged transaction and8988 * having the target disconnect will make this8989 * transaction indestinguishable from outstanding8990 * tagged transactions.8991 */8992 hscb->control = 0;8993 8994 /*8995 * This request sense could be because the8996 * the device lost power or in some other8997 * way has lost our transfer negotiations.8998 * Renegotiate if appropriate. Unit attention8999 * errors will be reported before any data9000 * phases occur.9001 */9002 if (ahd_get_residual(scb) == ahd_get_transfer_length(scb)) {9003 ahd_update_neg_request(ahd, &devinfo,9004 tstate, targ_info,9005 AHD_NEG_IF_NON_ASYNC);9006 }9007 if (tstate->auto_negotiate & devinfo.target_mask) {9008 hscb->control |= MK_MESSAGE;9009 scb->flags &=9010 ~(SCB_NEGOTIATE|SCB_ABORT|SCB_DEVICE_RESET);9011 scb->flags |= SCB_AUTO_NEGOTIATE;9012 }9013 hscb->cdb_len = sizeof(*sc);9014 ahd_setup_data_scb(ahd, scb);9015 scb->flags |= SCB_SENSE;9016 ahd_queue_scb(ahd, scb);9017 break;9018 }9019 case SAM_STAT_GOOD:9020 printk("%s: Interrupted for status of 0???\n",9021 ahd_name(ahd));9022 fallthrough;9023 default:9024 ahd_done(ahd, scb);9025 break;9026 }9027}9028 9029static void9030ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb)9031{9032 if (scb->hscb->shared_data.istatus.scsi_status != 0) {9033 ahd_handle_scsi_status(ahd, scb);9034 } else {9035 ahd_calc_residual(ahd, scb);9036 ahd_done(ahd, scb);9037 }9038}9039 9040/*9041 * Calculate the residual for a just completed SCB.9042 */9043static void9044ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb)9045{9046 struct hardware_scb *hscb;9047 struct initiator_status *spkt;9048 uint32_t sgptr;9049 uint32_t resid_sgptr;9050 uint32_t resid;9051 9052 /*9053 * 5 cases.9054 * 1) No residual.9055 * SG_STATUS_VALID clear in sgptr.9056 * 2) Transferless command9057 * 3) Never performed any transfers.9058 * sgptr has SG_FULL_RESID set.9059 * 4) No residual but target did not9060 * save data pointers after the9061 * last transfer, so sgptr was9062 * never updated.9063 * 5) We have a partial residual.9064 * Use residual_sgptr to determine9065 * where we are.9066 */9067 9068 hscb = scb->hscb;9069 sgptr = ahd_le32toh(hscb->sgptr);9070 if ((sgptr & SG_STATUS_VALID) == 0)9071 /* Case 1 */9072 return;9073 sgptr &= ~SG_STATUS_VALID;9074 9075 if ((sgptr & SG_LIST_NULL) != 0)9076 /* Case 2 */9077 return;9078 9079 /*9080 * Residual fields are the same in both9081 * target and initiator status packets,9082 * so we can always use the initiator fields9083 * regardless of the role for this SCB.9084 */9085 spkt = &hscb->shared_data.istatus;9086 resid_sgptr = ahd_le32toh(spkt->residual_sgptr);9087 if ((sgptr & SG_FULL_RESID) != 0) {9088 /* Case 3 */9089 resid = ahd_get_transfer_length(scb);9090 } else if ((resid_sgptr & SG_LIST_NULL) != 0) {9091 /* Case 4 */9092 return;9093 } else if ((resid_sgptr & SG_OVERRUN_RESID) != 0) {9094 ahd_print_path(ahd, scb);9095 printk("data overrun detected Tag == 0x%x.\n",9096 SCB_GET_TAG(scb));9097 ahd_freeze_devq(ahd, scb);9098 ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR);9099 ahd_freeze_scb(scb);9100 return;9101 } else if ((resid_sgptr & ~SG_PTR_MASK) != 0) {9102 panic("Bogus resid sgptr value 0x%x\n", resid_sgptr);9103 /* NOTREACHED */9104 } else {9105 struct ahd_dma_seg *sg;9106 9107 /*9108 * Remainder of the SG where the transfer9109 * stopped.9110 */9111 resid = ahd_le32toh(spkt->residual_datacnt) & AHD_SG_LEN_MASK;9112 sg = ahd_sg_bus_to_virt(ahd, scb, resid_sgptr & SG_PTR_MASK);9113 9114 /* The residual sg_ptr always points to the next sg */9115 sg--;9116 9117 /*9118 * Add up the contents of all residual9119 * SG segments that are after the SG where9120 * the transfer stopped.9121 */9122 while ((ahd_le32toh(sg->len) & AHD_DMA_LAST_SEG) == 0) {9123 sg++;9124 resid += ahd_le32toh(sg->len) & AHD_SG_LEN_MASK;9125 }9126 }9127 if ((scb->flags & SCB_SENSE) == 0)9128 ahd_set_residual(scb, resid);9129 else9130 ahd_set_sense_residual(scb, resid);9131 9132#ifdef AHD_DEBUG9133 if ((ahd_debug & AHD_SHOW_MISC) != 0) {9134 ahd_print_path(ahd, scb);9135 printk("Handled %sResidual of %d bytes\n",9136 (scb->flags & SCB_SENSE) ? "Sense " : "", resid);9137 }9138#endif9139}9140 9141/******************************* Target Mode **********************************/9142#ifdef AHD_TARGET_MODE9143/*9144 * Add a target mode event to this lun's queue9145 */9146static void9147ahd_queue_lstate_event(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate,9148 u_int initiator_id, u_int event_type, u_int event_arg)9149{9150 struct ahd_tmode_event *event;9151 int pending;9152 9153 xpt_freeze_devq(lstate->path, /*count*/1);9154 if (lstate->event_w_idx >= lstate->event_r_idx)9155 pending = lstate->event_w_idx - lstate->event_r_idx;9156 else9157 pending = AHD_TMODE_EVENT_BUFFER_SIZE + 19158 - (lstate->event_r_idx - lstate->event_w_idx);9159 9160 if (event_type == EVENT_TYPE_BUS_RESET9161 || event_type == TARGET_RESET) {9162 /*9163 * Any earlier events are irrelevant, so reset our buffer.9164 * This has the effect of allowing us to deal with reset9165 * floods (an external device holding down the reset line)9166 * without losing the event that is really interesting.9167 */9168 lstate->event_r_idx = 0;9169 lstate->event_w_idx = 0;9170 xpt_release_devq(lstate->path, pending, /*runqueue*/FALSE);9171 }9172 9173 if (pending == AHD_TMODE_EVENT_BUFFER_SIZE) {9174 xpt_print_path(lstate->path);9175 printk("immediate event %x:%x lost\n",9176 lstate->event_buffer[lstate->event_r_idx].event_type,9177 lstate->event_buffer[lstate->event_r_idx].event_arg);9178 lstate->event_r_idx++;9179 if (lstate->event_r_idx == AHD_TMODE_EVENT_BUFFER_SIZE)9180 lstate->event_r_idx = 0;9181 xpt_release_devq(lstate->path, /*count*/1, /*runqueue*/FALSE);9182 }9183 9184 event = &lstate->event_buffer[lstate->event_w_idx];9185 event->initiator_id = initiator_id;9186 event->event_type = event_type;9187 event->event_arg = event_arg;9188 lstate->event_w_idx++;9189 if (lstate->event_w_idx == AHD_TMODE_EVENT_BUFFER_SIZE)9190 lstate->event_w_idx = 0;9191}9192 9193/*9194 * Send any target mode events queued up waiting9195 * for immediate notify resources.9196 */9197void9198ahd_send_lstate_events(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate)9199{9200 struct ccb_hdr *ccbh;9201 struct ccb_immed_notify *inot;9202 9203 while (lstate->event_r_idx != lstate->event_w_idx9204 && (ccbh = SLIST_FIRST(&lstate->immed_notifies)) != NULL) {9205 struct ahd_tmode_event *event;9206 9207 event = &lstate->event_buffer[lstate->event_r_idx];9208 SLIST_REMOVE_HEAD(&lstate->immed_notifies, sim_links.sle);9209 inot = (struct ccb_immed_notify *)ccbh;9210 switch (event->event_type) {9211 case EVENT_TYPE_BUS_RESET:9212 ccbh->status = CAM_SCSI_BUS_RESET|CAM_DEV_QFRZN;9213 break;9214 default:9215 ccbh->status = CAM_MESSAGE_RECV|CAM_DEV_QFRZN;9216 inot->message_args[0] = event->event_type;9217 inot->message_args[1] = event->event_arg;9218 break;9219 }9220 inot->initiator_id = event->initiator_id;9221 inot->sense_len = 0;9222 xpt_done((union ccb *)inot);9223 lstate->event_r_idx++;9224 if (lstate->event_r_idx == AHD_TMODE_EVENT_BUFFER_SIZE)9225 lstate->event_r_idx = 0;9226 }9227}9228#endif9229 9230/******************** Sequencer Program Patching/Download *********************/9231 9232#ifdef AHD_DUMP_SEQ9233void9234ahd_dumpseq(struct ahd_softc* ahd)9235{9236 int i;9237 int max_prog;9238 9239 max_prog = 2048;9240 9241 ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);9242 ahd_outw(ahd, PRGMCNT, 0);9243 for (i = 0; i < max_prog; i++) {9244 uint8_t ins_bytes[4];9245 9246 ahd_insb(ahd, SEQRAM, ins_bytes, 4);9247 printk("0x%08x\n", ins_bytes[0] << 249248 | ins_bytes[1] << 169249 | ins_bytes[2] << 89250 | ins_bytes[3]);9251 }9252}9253#endif9254 9255static void9256ahd_loadseq(struct ahd_softc *ahd)9257{9258 struct cs cs_table[NUM_CRITICAL_SECTIONS];9259 u_int begin_set[NUM_CRITICAL_SECTIONS];9260 u_int end_set[NUM_CRITICAL_SECTIONS];9261 const struct patch *cur_patch;9262 u_int cs_count;9263 u_int cur_cs;9264 u_int i;9265 int downloaded;9266 u_int skip_addr;9267 u_int sg_prefetch_cnt;9268 u_int sg_prefetch_cnt_limit;9269 u_int sg_prefetch_align;9270 u_int sg_size;9271 u_int cacheline_mask;9272 uint8_t download_consts[DOWNLOAD_CONST_COUNT];9273 9274 if (bootverbose)9275 printk("%s: Downloading Sequencer Program...",9276 ahd_name(ahd));9277 9278#if DOWNLOAD_CONST_COUNT != 89279#error "Download Const Mismatch"9280#endif9281 /*9282 * Start out with 0 critical sections9283 * that apply to this firmware load.9284 */9285 cs_count = 0;9286 cur_cs = 0;9287 memset(begin_set, 0, sizeof(begin_set));9288 memset(end_set, 0, sizeof(end_set));9289 9290 /*9291 * Setup downloadable constant table.9292 *9293 * The computation for the S/G prefetch variables is9294 * a bit complicated. We would like to always fetch9295 * in terms of cachelined sized increments. However,9296 * if the cacheline is not an even multiple of the9297 * SG element size or is larger than our SG RAM, using9298 * just the cache size might leave us with only a portion9299 * of an SG element at the tail of a prefetch. If the9300 * cacheline is larger than our S/G prefetch buffer less9301 * the size of an SG element, we may round down to a cacheline9302 * that doesn't contain any or all of the S/G of interest9303 * within the bounds of our S/G ram. Provide variables to9304 * the sequencer that will allow it to handle these edge9305 * cases.9306 */9307 /* Start by aligning to the nearest cacheline. */9308 sg_prefetch_align = ahd->pci_cachesize;9309 if (sg_prefetch_align == 0)9310 sg_prefetch_align = 8;9311 /* Round down to the nearest power of 2. */9312 while (powerof2(sg_prefetch_align) == 0)9313 sg_prefetch_align--;9314 9315 cacheline_mask = sg_prefetch_align - 1;9316 9317 /*9318 * If the cacheline boundary is greater than half our prefetch RAM9319 * we risk not being able to fetch even a single complete S/G9320 * segment if we align to that boundary.9321 */9322 if (sg_prefetch_align > CCSGADDR_MAX/2)9323 sg_prefetch_align = CCSGADDR_MAX/2;9324 /* Start by fetching a single cacheline. */9325 sg_prefetch_cnt = sg_prefetch_align;9326 /*9327 * Increment the prefetch count by cachelines until9328 * at least one S/G element will fit.9329 */9330 sg_size = sizeof(struct ahd_dma_seg);9331 if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)9332 sg_size = sizeof(struct ahd_dma64_seg);9333 while (sg_prefetch_cnt < sg_size)9334 sg_prefetch_cnt += sg_prefetch_align;9335 /*9336 * If the cacheline is not an even multiple of9337 * the S/G size, we may only get a partial S/G when9338 * we align. Add a cacheline if this is the case.9339 */9340 if ((sg_prefetch_align % sg_size) != 09341 && (sg_prefetch_cnt < CCSGADDR_MAX))9342 sg_prefetch_cnt += sg_prefetch_align;9343 /*9344 * Lastly, compute a value that the sequencer can use9345 * to determine if the remainder of the CCSGRAM buffer9346 * has a full S/G element in it.9347 */9348 sg_prefetch_cnt_limit = -(sg_prefetch_cnt - sg_size + 1);9349 download_consts[SG_PREFETCH_CNT] = sg_prefetch_cnt;9350 download_consts[SG_PREFETCH_CNT_LIMIT] = sg_prefetch_cnt_limit;9351 download_consts[SG_PREFETCH_ALIGN_MASK] = ~(sg_prefetch_align - 1);9352 download_consts[SG_PREFETCH_ADDR_MASK] = (sg_prefetch_align - 1);9353 download_consts[SG_SIZEOF] = sg_size;9354 download_consts[PKT_OVERRUN_BUFOFFSET] =9355 (ahd->overrun_buf - (uint8_t *)ahd->qoutfifo) / 256;9356 download_consts[SCB_TRANSFER_SIZE] = SCB_TRANSFER_SIZE_1BYTE_LUN;9357 download_consts[CACHELINE_MASK] = cacheline_mask;9358 cur_patch = patches;9359 downloaded = 0;9360 skip_addr = 0;9361 ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM);9362 ahd_outw(ahd, PRGMCNT, 0);9363 9364 for (i = 0; i < sizeof(seqprog)/4; i++) {9365 if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) {9366 /*9367 * Don't download this instruction as it9368 * is in a patch that was removed.9369 */9370 continue;9371 }9372 /*9373 * Move through the CS table until we find a CS9374 * that might apply to this instruction.9375 */9376 for (; cur_cs < NUM_CRITICAL_SECTIONS; cur_cs++) {9377 if (critical_sections[cur_cs].end <= i) {9378 if (begin_set[cs_count] == TRUE9379 && end_set[cs_count] == FALSE) {9380 cs_table[cs_count].end = downloaded;9381 end_set[cs_count] = TRUE;9382 cs_count++;9383 }9384 continue;9385 }9386 if (critical_sections[cur_cs].begin <= i9387 && begin_set[cs_count] == FALSE) {9388 cs_table[cs_count].begin = downloaded;9389 begin_set[cs_count] = TRUE;9390 }9391 break;9392 }9393 ahd_download_instr(ahd, i, download_consts);9394 downloaded++;9395 }9396 9397 ahd->num_critical_sections = cs_count;9398 if (cs_count != 0) {9399 9400 cs_count *= sizeof(struct cs);9401 ahd->critical_sections = kmemdup(cs_table, cs_count, GFP_ATOMIC);9402 if (ahd->critical_sections == NULL)9403 panic("ahd_loadseq: Could not malloc");9404 }9405 ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE);9406 9407 if (bootverbose) {9408 printk(" %d instructions downloaded\n", downloaded);9409 printk("%s: Features 0x%x, Bugs 0x%x, Flags 0x%x\n",9410 ahd_name(ahd), ahd->features, ahd->bugs, ahd->flags);9411 }9412}9413 9414static int9415ahd_check_patch(struct ahd_softc *ahd, const struct patch **start_patch,9416 u_int start_instr, u_int *skip_addr)9417{9418 const struct patch *cur_patch;9419 const struct patch *last_patch;9420 u_int num_patches;9421 9422 num_patches = ARRAY_SIZE(patches);9423 last_patch = &patches[num_patches];9424 cur_patch = *start_patch;9425 9426 while (cur_patch < last_patch && start_instr == cur_patch->begin) {9427 9428 if (cur_patch->patch_func(ahd) == 0) {9429 9430 /* Start rejecting code */9431 *skip_addr = start_instr + cur_patch->skip_instr;9432 cur_patch += cur_patch->skip_patch;9433 } else {9434 /* Accepted this patch. Advance to the next9435 * one and wait for our intruction pointer to9436 * hit this point.9437 */9438 cur_patch++;9439 }9440 }9441 9442 *start_patch = cur_patch;9443 if (start_instr < *skip_addr)9444 /* Still skipping */9445 return (0);9446 9447 return (1);9448}9449 9450static u_int9451ahd_resolve_seqaddr(struct ahd_softc *ahd, u_int address)9452{9453 const struct patch *cur_patch;9454 int address_offset;9455 u_int skip_addr;9456 u_int i;9457 9458 address_offset = 0;9459 cur_patch = patches;9460 skip_addr = 0;9461 9462 for (i = 0; i < address;) {9463 9464 ahd_check_patch(ahd, &cur_patch, i, &skip_addr);9465 9466 if (skip_addr > i) {9467 int end_addr;9468 9469 end_addr = min(address, skip_addr);9470 address_offset += end_addr - i;9471 i = skip_addr;9472 } else {9473 i++;9474 }9475 }9476 return (address - address_offset);9477}9478 9479static void9480ahd_download_instr(struct ahd_softc *ahd, u_int instrptr, uint8_t *dconsts)9481{9482 union ins_formats instr;9483 struct ins_format1 *fmt1_ins;9484 struct ins_format3 *fmt3_ins;9485 u_int opcode;9486 9487 /*9488 * The firmware is always compiled into a little endian format.9489 */9490 instr.integer = ahd_le32toh(*(uint32_t*)&seqprog[instrptr * 4]);9491 9492 fmt1_ins = &instr.format1;9493 fmt3_ins = NULL;9494 9495 /* Pull the opcode */9496 opcode = instr.format1.opcode;9497 switch (opcode) {9498 case AIC_OP_JMP:9499 case AIC_OP_JC:9500 case AIC_OP_JNC:9501 case AIC_OP_CALL:9502 case AIC_OP_JNE:9503 case AIC_OP_JNZ:9504 case AIC_OP_JE:9505 case AIC_OP_JZ:9506 {9507 fmt3_ins = &instr.format3;9508 fmt3_ins->address = ahd_resolve_seqaddr(ahd, fmt3_ins->address);9509 }9510 fallthrough;9511 case AIC_OP_OR:9512 case AIC_OP_AND:9513 case AIC_OP_XOR:9514 case AIC_OP_ADD:9515 case AIC_OP_ADC:9516 case AIC_OP_BMOV:9517 if (fmt1_ins->parity != 0) {9518 fmt1_ins->immediate = dconsts[fmt1_ins->immediate];9519 }9520 fmt1_ins->parity = 0;9521 fallthrough;9522 case AIC_OP_ROL:9523 {9524 int i, count;9525 9526 /* Calculate odd parity for the instruction */9527 for (i = 0, count = 0; i < 31; i++) {9528 uint32_t mask;9529 9530 mask = 0x01 << i;9531 if ((instr.integer & mask) != 0)9532 count++;9533 }9534 if ((count & 0x01) == 0)9535 instr.format1.parity = 1;9536 9537 /* The sequencer is a little endian cpu */9538 instr.integer = ahd_htole32(instr.integer);9539 ahd_outsb(ahd, SEQRAM, instr.bytes, 4);9540 break;9541 }9542 default:9543 panic("Unknown opcode encountered in seq program");9544 break;9545 }9546}9547 9548static int9549ahd_probe_stack_size(struct ahd_softc *ahd)9550{9551 int last_probe;9552 9553 last_probe = 0;9554 while (1) {9555 int i;9556 9557 /*9558 * We avoid using 0 as a pattern to avoid9559 * confusion if the stack implementation9560 * "back-fills" with zeros when "poping'9561 * entries.9562 */9563 for (i = 1; i <= last_probe+1; i++) {9564 ahd_outb(ahd, STACK, i & 0xFF);9565 ahd_outb(ahd, STACK, (i >> 8) & 0xFF);9566 }9567 9568 /* Verify */9569 for (i = last_probe+1; i > 0; i--) {9570 u_int stack_entry;9571 9572 stack_entry = ahd_inb(ahd, STACK)9573 |(ahd_inb(ahd, STACK) << 8);9574 if (stack_entry != i)9575 goto sized;9576 }9577 last_probe++;9578 }9579sized:9580 return (last_probe);9581}9582 9583int9584ahd_print_register(const ahd_reg_parse_entry_t *table, u_int num_entries,9585 const char *name, u_int address, u_int value,9586 u_int *cur_column, u_int wrap_point)9587{9588 int printed;9589 u_int printed_mask;9590 9591 if (cur_column != NULL && *cur_column >= wrap_point) {9592 printk("\n");9593 *cur_column = 0;9594 }9595 printed = printk("%s[0x%x]", name, value);9596 if (table == NULL) {9597 printed += printk(" ");9598 *cur_column += printed;9599 return (printed);9600 }9601 printed_mask = 0;9602 while (printed_mask != 0xFF) {9603 int entry;9604 9605 for (entry = 0; entry < num_entries; entry++) {9606 if (((value & table[entry].mask)9607 != table[entry].value)9608 || ((printed_mask & table[entry].mask)9609 == table[entry].mask))9610 continue;9611 9612 printed += printk("%s%s",9613 printed_mask == 0 ? ":(" : "|",9614 table[entry].name);9615 printed_mask |= table[entry].mask;9616 9617 break;9618 }9619 if (entry >= num_entries)9620 break;9621 }9622 if (printed_mask != 0)9623 printed += printk(") ");9624 else9625 printed += printk(" ");9626 if (cur_column != NULL)9627 *cur_column += printed;9628 return (printed);9629}9630 9631void9632ahd_dump_card_state(struct ahd_softc *ahd)9633{9634 struct scb *scb;9635 ahd_mode_state saved_modes;9636 u_int dffstat;9637 int paused;9638 u_int scb_index;9639 u_int saved_scb_index;9640 u_int cur_col;9641 int i;9642 9643 if (ahd_is_paused(ahd)) {9644 paused = 1;9645 } else {9646 paused = 0;9647 ahd_pause(ahd);9648 }9649 saved_modes = ahd_save_modes(ahd);9650 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);9651 printk(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n"9652 "%s: Dumping Card State at program address 0x%x Mode 0x%x\n",9653 ahd_name(ahd),9654 ahd_inw(ahd, CURADDR),9655 ahd_build_mode_state(ahd, ahd->saved_src_mode,9656 ahd->saved_dst_mode));9657 if (paused)9658 printk("Card was paused\n");9659 9660 if (ahd_check_cmdcmpltqueues(ahd))9661 printk("Completions are pending\n");9662 9663 /*9664 * Mode independent registers.9665 */9666 cur_col = 0;9667 ahd_intstat_print(ahd_inb(ahd, INTSTAT), &cur_col, 50);9668 ahd_seloid_print(ahd_inb(ahd, SELOID), &cur_col, 50);9669 ahd_selid_print(ahd_inb(ahd, SELID), &cur_col, 50);9670 ahd_hs_mailbox_print(ahd_inb(ahd, LOCAL_HS_MAILBOX), &cur_col, 50);9671 ahd_intctl_print(ahd_inb(ahd, INTCTL), &cur_col, 50);9672 ahd_seqintstat_print(ahd_inb(ahd, SEQINTSTAT), &cur_col, 50);9673 ahd_saved_mode_print(ahd_inb(ahd, SAVED_MODE), &cur_col, 50);9674 ahd_dffstat_print(ahd_inb(ahd, DFFSTAT), &cur_col, 50);9675 ahd_scsisigi_print(ahd_inb(ahd, SCSISIGI), &cur_col, 50);9676 ahd_scsiphase_print(ahd_inb(ahd, SCSIPHASE), &cur_col, 50);9677 ahd_scsibus_print(ahd_inb(ahd, SCSIBUS), &cur_col, 50);9678 ahd_lastphase_print(ahd_inb(ahd, LASTPHASE), &cur_col, 50);9679 ahd_scsiseq0_print(ahd_inb(ahd, SCSISEQ0), &cur_col, 50);9680 ahd_scsiseq1_print(ahd_inb(ahd, SCSISEQ1), &cur_col, 50);9681 ahd_seqctl0_print(ahd_inb(ahd, SEQCTL0), &cur_col, 50);9682 ahd_seqintctl_print(ahd_inb(ahd, SEQINTCTL), &cur_col, 50);9683 ahd_seq_flags_print(ahd_inb(ahd, SEQ_FLAGS), &cur_col, 50);9684 ahd_seq_flags2_print(ahd_inb(ahd, SEQ_FLAGS2), &cur_col, 50);9685 ahd_qfreeze_count_print(ahd_inw(ahd, QFREEZE_COUNT), &cur_col, 50);9686 ahd_kernel_qfreeze_count_print(ahd_inw(ahd, KERNEL_QFREEZE_COUNT),9687 &cur_col, 50);9688 ahd_mk_message_scb_print(ahd_inw(ahd, MK_MESSAGE_SCB), &cur_col, 50);9689 ahd_mk_message_scsiid_print(ahd_inb(ahd, MK_MESSAGE_SCSIID),9690 &cur_col, 50);9691 ahd_sstat0_print(ahd_inb(ahd, SSTAT0), &cur_col, 50);9692 ahd_sstat1_print(ahd_inb(ahd, SSTAT1), &cur_col, 50);9693 ahd_sstat2_print(ahd_inb(ahd, SSTAT2), &cur_col, 50);9694 ahd_sstat3_print(ahd_inb(ahd, SSTAT3), &cur_col, 50);9695 ahd_perrdiag_print(ahd_inb(ahd, PERRDIAG), &cur_col, 50);9696 ahd_simode1_print(ahd_inb(ahd, SIMODE1), &cur_col, 50);9697 ahd_lqistat0_print(ahd_inb(ahd, LQISTAT0), &cur_col, 50);9698 ahd_lqistat1_print(ahd_inb(ahd, LQISTAT1), &cur_col, 50);9699 ahd_lqistat2_print(ahd_inb(ahd, LQISTAT2), &cur_col, 50);9700 ahd_lqostat0_print(ahd_inb(ahd, LQOSTAT0), &cur_col, 50);9701 ahd_lqostat1_print(ahd_inb(ahd, LQOSTAT1), &cur_col, 50);9702 ahd_lqostat2_print(ahd_inb(ahd, LQOSTAT2), &cur_col, 50);9703 printk("\n");9704 printk("\nSCB Count = %d CMDS_PENDING = %d LASTSCB 0x%x "9705 "CURRSCB 0x%x NEXTSCB 0x%x\n",9706 ahd->scb_data.numscbs, ahd_inw(ahd, CMDS_PENDING),9707 ahd_inw(ahd, LASTSCB), ahd_inw(ahd, CURRSCB),9708 ahd_inw(ahd, NEXTSCB));9709 cur_col = 0;9710 /* QINFIFO */9711 ahd_search_qinfifo(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,9712 CAM_LUN_WILDCARD, SCB_LIST_NULL,9713 ROLE_UNKNOWN, /*status*/0, SEARCH_PRINT);9714 saved_scb_index = ahd_get_scbptr(ahd);9715 printk("Pending list:");9716 i = 0;9717 LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {9718 if (i++ > AHD_SCB_MAX)9719 break;9720 cur_col = printk("\n%3d FIFO_USE[0x%x] ", SCB_GET_TAG(scb),9721 ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT));9722 ahd_set_scbptr(ahd, SCB_GET_TAG(scb));9723 ahd_scb_control_print(ahd_inb_scbram(ahd, SCB_CONTROL),9724 &cur_col, 60);9725 ahd_scb_scsiid_print(ahd_inb_scbram(ahd, SCB_SCSIID),9726 &cur_col, 60);9727 }9728 printk("\nTotal %d\n", i);9729 9730 printk("Kernel Free SCB list: ");9731 i = 0;9732 TAILQ_FOREACH(scb, &ahd->scb_data.free_scbs, links.tqe) {9733 struct scb *list_scb;9734 9735 list_scb = scb;9736 do {9737 printk("%d ", SCB_GET_TAG(list_scb));9738 list_scb = LIST_NEXT(list_scb, collision_links);9739 } while (list_scb && i++ < AHD_SCB_MAX);9740 }9741 9742 LIST_FOREACH(scb, &ahd->scb_data.any_dev_free_scb_list, links.le) {9743 if (i++ > AHD_SCB_MAX)9744 break;9745 printk("%d ", SCB_GET_TAG(scb));9746 }9747 printk("\n");9748 9749 printk("Sequencer Complete DMA-inprog list: ");9750 scb_index = ahd_inw(ahd, COMPLETE_SCB_DMAINPROG_HEAD);9751 i = 0;9752 while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {9753 ahd_set_scbptr(ahd, scb_index);9754 printk("%d ", scb_index);9755 scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);9756 }9757 printk("\n");9758 9759 printk("Sequencer Complete list: ");9760 scb_index = ahd_inw(ahd, COMPLETE_SCB_HEAD);9761 i = 0;9762 while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {9763 ahd_set_scbptr(ahd, scb_index);9764 printk("%d ", scb_index);9765 scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);9766 }9767 printk("\n");9768 9769 printk("Sequencer DMA-Up and Complete list: ");9770 scb_index = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);9771 i = 0;9772 while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {9773 ahd_set_scbptr(ahd, scb_index);9774 printk("%d ", scb_index);9775 scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);9776 }9777 printk("\n");9778 printk("Sequencer On QFreeze and Complete list: ");9779 scb_index = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);9780 i = 0;9781 while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) {9782 ahd_set_scbptr(ahd, scb_index);9783 printk("%d ", scb_index);9784 scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);9785 }9786 printk("\n");9787 ahd_set_scbptr(ahd, saved_scb_index);9788 dffstat = ahd_inb(ahd, DFFSTAT);9789 for (i = 0; i < 2; i++) {9790#ifdef AHD_DEBUG9791 struct scb *fifo_scb;9792#endif9793 u_int fifo_scbptr;9794 9795 ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i);9796 fifo_scbptr = ahd_get_scbptr(ahd);9797 printk("\n\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n",9798 ahd_name(ahd), i,9799 (dffstat & (FIFO0FREE << i)) ? "Free" : "Active",9800 ahd_inw(ahd, LONGJMP_ADDR), fifo_scbptr);9801 cur_col = 0;9802 ahd_seqimode_print(ahd_inb(ahd, SEQIMODE), &cur_col, 50);9803 ahd_seqintsrc_print(ahd_inb(ahd, SEQINTSRC), &cur_col, 50);9804 ahd_dfcntrl_print(ahd_inb(ahd, DFCNTRL), &cur_col, 50);9805 ahd_dfstatus_print(ahd_inb(ahd, DFSTATUS), &cur_col, 50);9806 ahd_sg_cache_shadow_print(ahd_inb(ahd, SG_CACHE_SHADOW),9807 &cur_col, 50);9808 ahd_sg_state_print(ahd_inb(ahd, SG_STATE), &cur_col, 50);9809 ahd_dffsxfrctl_print(ahd_inb(ahd, DFFSXFRCTL), &cur_col, 50);9810 ahd_soffcnt_print(ahd_inb(ahd, SOFFCNT), &cur_col, 50);9811 ahd_mdffstat_print(ahd_inb(ahd, MDFFSTAT), &cur_col, 50);9812 if (cur_col > 50) {9813 printk("\n");9814 cur_col = 0;9815 }9816 cur_col += printk("SHADDR = 0x%x%x, SHCNT = 0x%x ",9817 ahd_inl(ahd, SHADDR+4),9818 ahd_inl(ahd, SHADDR),9819 (ahd_inb(ahd, SHCNT)9820 | (ahd_inb(ahd, SHCNT + 1) << 8)9821 | (ahd_inb(ahd, SHCNT + 2) << 16)));9822 if (cur_col > 50) {9823 printk("\n");9824 cur_col = 0;9825 }9826 cur_col += printk("HADDR = 0x%x%x, HCNT = 0x%x ",9827 ahd_inl(ahd, HADDR+4),9828 ahd_inl(ahd, HADDR),9829 (ahd_inb(ahd, HCNT)9830 | (ahd_inb(ahd, HCNT + 1) << 8)9831 | (ahd_inb(ahd, HCNT + 2) << 16)));9832 ahd_ccsgctl_print(ahd_inb(ahd, CCSGCTL), &cur_col, 50);9833#ifdef AHD_DEBUG9834 if ((ahd_debug & AHD_SHOW_SG) != 0) {9835 fifo_scb = ahd_lookup_scb(ahd, fifo_scbptr);9836 if (fifo_scb != NULL)9837 ahd_dump_sglist(fifo_scb);9838 }9839#endif9840 }9841 printk("\nLQIN: ");9842 for (i = 0; i < 20; i++)9843 printk("0x%x ", ahd_inb(ahd, LQIN + i));9844 printk("\n");9845 ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);9846 printk("%s: LQISTATE = 0x%x, LQOSTATE = 0x%x, OPTIONMODE = 0x%x\n",9847 ahd_name(ahd), ahd_inb(ahd, LQISTATE), ahd_inb(ahd, LQOSTATE),9848 ahd_inb(ahd, OPTIONMODE));9849 printk("%s: OS_SPACE_CNT = 0x%x MAXCMDCNT = 0x%x\n",9850 ahd_name(ahd), ahd_inb(ahd, OS_SPACE_CNT),9851 ahd_inb(ahd, MAXCMDCNT));9852 printk("%s: SAVED_SCSIID = 0x%x SAVED_LUN = 0x%x\n",9853 ahd_name(ahd), ahd_inb(ahd, SAVED_SCSIID),9854 ahd_inb(ahd, SAVED_LUN));9855 ahd_simode0_print(ahd_inb(ahd, SIMODE0), &cur_col, 50);9856 printk("\n");9857 ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);9858 cur_col = 0;9859 ahd_ccscbctl_print(ahd_inb(ahd, CCSCBCTL), &cur_col, 50);9860 printk("\n");9861 ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);9862 printk("%s: REG0 == 0x%x, SINDEX = 0x%x, DINDEX = 0x%x\n",9863 ahd_name(ahd), ahd_inw(ahd, REG0), ahd_inw(ahd, SINDEX),9864 ahd_inw(ahd, DINDEX));9865 printk("%s: SCBPTR == 0x%x, SCB_NEXT == 0x%x, SCB_NEXT2 == 0x%x\n",9866 ahd_name(ahd), ahd_get_scbptr(ahd),9867 ahd_inw_scbram(ahd, SCB_NEXT),9868 ahd_inw_scbram(ahd, SCB_NEXT2));9869 printk("CDB %x %x %x %x %x %x\n",9870 ahd_inb_scbram(ahd, SCB_CDB_STORE),9871 ahd_inb_scbram(ahd, SCB_CDB_STORE+1),9872 ahd_inb_scbram(ahd, SCB_CDB_STORE+2),9873 ahd_inb_scbram(ahd, SCB_CDB_STORE+3),9874 ahd_inb_scbram(ahd, SCB_CDB_STORE+4),9875 ahd_inb_scbram(ahd, SCB_CDB_STORE+5));9876 printk("STACK:");9877 for (i = 0; i < ahd->stack_size; i++) {9878 ahd->saved_stack[i] =9879 ahd_inb(ahd, STACK)|(ahd_inb(ahd, STACK) << 8);9880 printk(" 0x%x", ahd->saved_stack[i]);9881 }9882 for (i = ahd->stack_size-1; i >= 0; i--) {9883 ahd_outb(ahd, STACK, ahd->saved_stack[i] & 0xFF);9884 ahd_outb(ahd, STACK, (ahd->saved_stack[i] >> 8) & 0xFF);9885 }9886 printk("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n");9887 ahd_restore_modes(ahd, saved_modes);9888 if (paused == 0)9889 ahd_unpause(ahd);9890}9891 9892#if 09893void9894ahd_dump_scbs(struct ahd_softc *ahd)9895{9896 ahd_mode_state saved_modes;9897 u_int saved_scb_index;9898 int i;9899 9900 saved_modes = ahd_save_modes(ahd);9901 ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);9902 saved_scb_index = ahd_get_scbptr(ahd);9903 for (i = 0; i < AHD_SCB_MAX; i++) {9904 ahd_set_scbptr(ahd, i);9905 printk("%3d", i);9906 printk("(CTRL 0x%x ID 0x%x N 0x%x N2 0x%x SG 0x%x, RSG 0x%x)\n",9907 ahd_inb_scbram(ahd, SCB_CONTROL),9908 ahd_inb_scbram(ahd, SCB_SCSIID),9909 ahd_inw_scbram(ahd, SCB_NEXT),9910 ahd_inw_scbram(ahd, SCB_NEXT2),9911 ahd_inl_scbram(ahd, SCB_SGPTR),9912 ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR));9913 }9914 printk("\n");9915 ahd_set_scbptr(ahd, saved_scb_index);9916 ahd_restore_modes(ahd, saved_modes);9917}9918#endif /* 0 */9919 9920/**************************** Flexport Logic **********************************/9921/*9922 * Read count 16bit words from 16bit word address start_addr from the9923 * SEEPROM attached to the controller, into buf, using the controller's9924 * SEEPROM reading state machine. Optionally treat the data as a byte9925 * stream in terms of byte order.9926 */9927int9928ahd_read_seeprom(struct ahd_softc *ahd, uint16_t *buf,9929 u_int start_addr, u_int count, int bytestream)9930{9931 u_int cur_addr;9932 u_int end_addr;9933 int error;9934 9935 /*9936 * If we never make it through the loop even once,9937 * we were passed invalid arguments.9938 */9939 error = EINVAL;9940 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);9941 end_addr = start_addr + count;9942 for (cur_addr = start_addr; cur_addr < end_addr; cur_addr++) {9943 9944 ahd_outb(ahd, SEEADR, cur_addr);9945 ahd_outb(ahd, SEECTL, SEEOP_READ | SEESTART);9946 9947 error = ahd_wait_seeprom(ahd);9948 if (error)9949 break;9950 if (bytestream != 0) {9951 uint8_t *bytestream_ptr;9952 9953 bytestream_ptr = (uint8_t *)buf;9954 *bytestream_ptr++ = ahd_inb(ahd, SEEDAT);9955 *bytestream_ptr = ahd_inb(ahd, SEEDAT+1);9956 } else {9957 /*9958 * ahd_inw() already handles machine byte order.9959 */9960 *buf = ahd_inw(ahd, SEEDAT);9961 }9962 buf++;9963 }9964 return (error);9965}9966 9967/*9968 * Write count 16bit words from buf, into SEEPROM attache to the9969 * controller starting at 16bit word address start_addr, using the9970 * controller's SEEPROM writing state machine.9971 */9972int9973ahd_write_seeprom(struct ahd_softc *ahd, uint16_t *buf,9974 u_int start_addr, u_int count)9975{9976 u_int cur_addr;9977 u_int end_addr;9978 int error;9979 int retval;9980 9981 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);9982 error = ENOENT;9983 9984 /* Place the chip into write-enable mode */9985 ahd_outb(ahd, SEEADR, SEEOP_EWEN_ADDR);9986 ahd_outb(ahd, SEECTL, SEEOP_EWEN | SEESTART);9987 error = ahd_wait_seeprom(ahd);9988 if (error)9989 return (error);9990 9991 /*9992 * Write the data. If we don't get through the loop at9993 * least once, the arguments were invalid.9994 */9995 retval = EINVAL;9996 end_addr = start_addr + count;9997 for (cur_addr = start_addr; cur_addr < end_addr; cur_addr++) {9998 ahd_outw(ahd, SEEDAT, *buf++);9999 ahd_outb(ahd, SEEADR, cur_addr);10000 ahd_outb(ahd, SEECTL, SEEOP_WRITE | SEESTART);10001 10002 retval = ahd_wait_seeprom(ahd);10003 if (retval)10004 break;10005 }10006 10007 /*10008 * Disable writes.10009 */10010 ahd_outb(ahd, SEEADR, SEEOP_EWDS_ADDR);10011 ahd_outb(ahd, SEECTL, SEEOP_EWDS | SEESTART);10012 error = ahd_wait_seeprom(ahd);10013 if (error)10014 return (error);10015 return (retval);10016}10017 10018/*10019 * Wait ~100us for the serial eeprom to satisfy our request.10020 */10021static int10022ahd_wait_seeprom(struct ahd_softc *ahd)10023{10024 int cnt;10025 10026 cnt = 5000;10027 while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt)10028 ahd_delay(5);10029 10030 if (cnt == 0)10031 return (ETIMEDOUT);10032 return (0);10033}10034 10035/*10036 * Validate the two checksums in the per_channel10037 * vital product data struct.10038 */10039static int10040ahd_verify_vpd_cksum(struct vpd_config *vpd)10041{10042 int i;10043 int maxaddr;10044 uint32_t checksum;10045 uint8_t *vpdarray;10046 10047 vpdarray = (uint8_t *)vpd;10048 maxaddr = offsetof(struct vpd_config, vpd_checksum);10049 checksum = 0;10050 for (i = offsetof(struct vpd_config, resource_type); i < maxaddr; i++)10051 checksum = checksum + vpdarray[i];10052 if (checksum == 010053 || (-checksum & 0xFF) != vpd->vpd_checksum)10054 return (0);10055 10056 checksum = 0;10057 maxaddr = offsetof(struct vpd_config, checksum);10058 for (i = offsetof(struct vpd_config, default_target_flags);10059 i < maxaddr; i++)10060 checksum = checksum + vpdarray[i];10061 if (checksum == 010062 || (-checksum & 0xFF) != vpd->checksum)10063 return (0);10064 return (1);10065}10066 10067int10068ahd_verify_cksum(struct seeprom_config *sc)10069{10070 int i;10071 int maxaddr;10072 uint32_t checksum;10073 uint16_t *scarray;10074 10075 maxaddr = (sizeof(*sc)/2) - 1;10076 checksum = 0;10077 scarray = (uint16_t *)sc;10078 10079 for (i = 0; i < maxaddr; i++)10080 checksum = checksum + scarray[i];10081 if (checksum == 010082 || (checksum & 0xFFFF) != sc->checksum) {10083 return (0);10084 } else {10085 return (1);10086 }10087}10088 10089int10090ahd_acquire_seeprom(struct ahd_softc *ahd)10091{10092 /*10093 * We should be able to determine the SEEPROM type10094 * from the flexport logic, but unfortunately not10095 * all implementations have this logic and there is10096 * no programatic method for determining if the logic10097 * is present.10098 */10099 return (1);10100#if 010101 uint8_t seetype;10102 int error;10103 10104 error = ahd_read_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, &seetype);10105 if (error != 010106 || ((seetype & FLX_ROMSTAT_SEECFG) == FLX_ROMSTAT_SEE_NONE))10107 return (0);10108 return (1);10109#endif10110}10111 10112void10113ahd_release_seeprom(struct ahd_softc *ahd)10114{10115 /* Currently a no-op */10116}10117 10118/*10119 * Wait at most 2 seconds for flexport arbitration to succeed.10120 */10121static int10122ahd_wait_flexport(struct ahd_softc *ahd)10123{10124 int cnt;10125 10126 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);10127 cnt = 1000000 * 2 / 5;10128 while ((ahd_inb(ahd, BRDCTL) & FLXARBACK) == 0 && --cnt)10129 ahd_delay(5);10130 10131 if (cnt == 0)10132 return (ETIMEDOUT);10133 return (0);10134}10135 10136int10137ahd_write_flexport(struct ahd_softc *ahd, u_int addr, u_int value)10138{10139 int error;10140 10141 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);10142 if (addr > 7)10143 panic("ahd_write_flexport: address out of range");10144 ahd_outb(ahd, BRDCTL, BRDEN|(addr << 3));10145 error = ahd_wait_flexport(ahd);10146 if (error != 0)10147 return (error);10148 ahd_outb(ahd, BRDDAT, value);10149 ahd_flush_device_writes(ahd);10150 ahd_outb(ahd, BRDCTL, BRDSTB|BRDEN|(addr << 3));10151 ahd_flush_device_writes(ahd);10152 ahd_outb(ahd, BRDCTL, BRDEN|(addr << 3));10153 ahd_flush_device_writes(ahd);10154 ahd_outb(ahd, BRDCTL, 0);10155 ahd_flush_device_writes(ahd);10156 return (0);10157}10158 10159int10160ahd_read_flexport(struct ahd_softc *ahd, u_int addr, uint8_t *value)10161{10162 int error;10163 10164 AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);10165 if (addr > 7)10166 panic("ahd_read_flexport: address out of range");10167 ahd_outb(ahd, BRDCTL, BRDRW|BRDEN|(addr << 3));10168 error = ahd_wait_flexport(ahd);10169 if (error != 0)10170 return (error);10171 *value = ahd_inb(ahd, BRDDAT);10172 ahd_outb(ahd, BRDCTL, 0);10173 ahd_flush_device_writes(ahd);10174 return (0);10175}10176 10177/************************* Target Mode ****************************************/10178#ifdef AHD_TARGET_MODE10179cam_status10180ahd_find_tmode_devs(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb,10181 struct ahd_tmode_tstate **tstate,10182 struct ahd_tmode_lstate **lstate,10183 int notfound_failure)10184{10185 10186 if ((ahd->features & AHD_TARGETMODE) == 0)10187 return (CAM_REQ_INVALID);10188 10189 /*10190 * Handle the 'black hole' device that sucks up10191 * requests to unattached luns on enabled targets.10192 */10193 if (ccb->ccb_h.target_id == CAM_TARGET_WILDCARD10194 && ccb->ccb_h.target_lun == CAM_LUN_WILDCARD) {10195 *tstate = NULL;10196 *lstate = ahd->black_hole;10197 } else {10198 u_int max_id;10199 10200 max_id = (ahd->features & AHD_WIDE) ? 16 : 8;10201 if (ccb->ccb_h.target_id >= max_id)10202 return (CAM_TID_INVALID);10203 10204 if (ccb->ccb_h.target_lun >= AHD_NUM_LUNS)10205 return (CAM_LUN_INVALID);10206 10207 *tstate = ahd->enabled_targets[ccb->ccb_h.target_id];10208 *lstate = NULL;10209 if (*tstate != NULL)10210 *lstate =10211 (*tstate)->enabled_luns[ccb->ccb_h.target_lun];10212 }10213 10214 if (notfound_failure != 0 && *lstate == NULL)10215 return (CAM_PATH_INVALID);10216 10217 return (CAM_REQ_CMP);10218}10219 10220void10221ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)10222{10223#if NOT_YET10224 struct ahd_tmode_tstate *tstate;10225 struct ahd_tmode_lstate *lstate;10226 struct ccb_en_lun *cel;10227 cam_status status;10228 u_int target;10229 u_int lun;10230 u_int target_mask;10231 u_long s;10232 char channel;10233 10234 status = ahd_find_tmode_devs(ahd, sim, ccb, &tstate, &lstate,10235 /*notfound_failure*/FALSE);10236 10237 if (status != CAM_REQ_CMP) {10238 ccb->ccb_h.status = status;10239 return;10240 }10241 10242 if ((ahd->features & AHD_MULTIROLE) != 0) {10243 u_int our_id;10244 10245 our_id = ahd->our_id;10246 if (ccb->ccb_h.target_id != our_id) {10247 if ((ahd->features & AHD_MULTI_TID) != 010248 && (ahd->flags & AHD_INITIATORROLE) != 0) {10249 /*10250 * Only allow additional targets if10251 * the initiator role is disabled.10252 * The hardware cannot handle a re-select-in10253 * on the initiator id during a re-select-out10254 * on a different target id.10255 */10256 status = CAM_TID_INVALID;10257 } else if ((ahd->flags & AHD_INITIATORROLE) != 010258 || ahd->enabled_luns > 0) {10259 /*10260 * Only allow our target id to change10261 * if the initiator role is not configured10262 * and there are no enabled luns which10263 * are attached to the currently registered10264 * scsi id.10265 */10266 status = CAM_TID_INVALID;10267 }10268 }10269 }10270 10271 if (status != CAM_REQ_CMP) {10272 ccb->ccb_h.status = status;10273 return;10274 }10275 10276 /*10277 * We now have an id that is valid.10278 * If we aren't in target mode, switch modes.10279 */10280 if ((ahd->flags & AHD_TARGETROLE) == 010281 && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) {10282 u_long s;10283 10284 printk("Configuring Target Mode\n");10285 ahd_lock(ahd, &s);10286 if (LIST_FIRST(&ahd->pending_scbs) != NULL) {10287 ccb->ccb_h.status = CAM_BUSY;10288 ahd_unlock(ahd, &s);10289 return;10290 }10291 ahd->flags |= AHD_TARGETROLE;10292 if ((ahd->features & AHD_MULTIROLE) == 0)10293 ahd->flags &= ~AHD_INITIATORROLE;10294 ahd_pause(ahd);10295 ahd_loadseq(ahd);10296 ahd_restart(ahd);10297 ahd_unlock(ahd, &s);10298 }10299 cel = &ccb->cel;10300 target = ccb->ccb_h.target_id;10301 lun = ccb->ccb_h.target_lun;10302 channel = SIM_CHANNEL(ahd, sim);10303 target_mask = 0x01 << target;10304 if (channel == 'B')10305 target_mask <<= 8;10306 10307 if (cel->enable != 0) {10308 u_int scsiseq1;10309 10310 /* Are we already enabled?? */10311 if (lstate != NULL) {10312 xpt_print_path(ccb->ccb_h.path);10313 printk("Lun already enabled\n");10314 ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;10315 return;10316 }10317 10318 if (cel->grp6_len != 010319 || cel->grp7_len != 0) {10320 /*10321 * Don't (yet?) support vendor10322 * specific commands.10323 */10324 ccb->ccb_h.status = CAM_REQ_INVALID;10325 printk("Non-zero Group Codes\n");10326 return;10327 }10328 10329 /*10330 * Seems to be okay.10331 * Setup our data structures.10332 */10333 if (target != CAM_TARGET_WILDCARD && tstate == NULL) {10334 tstate = ahd_alloc_tstate(ahd, target, channel);10335 if (tstate == NULL) {10336 xpt_print_path(ccb->ccb_h.path);10337 printk("Couldn't allocate tstate\n");10338 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;10339 return;10340 }10341 }10342 lstate = kzalloc(sizeof(*lstate), GFP_ATOMIC);10343 if (lstate == NULL) {10344 xpt_print_path(ccb->ccb_h.path);10345 printk("Couldn't allocate lstate\n");10346 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;10347 return;10348 }10349 status = xpt_create_path(&lstate->path, /*periph*/NULL,10350 xpt_path_path_id(ccb->ccb_h.path),10351 xpt_path_target_id(ccb->ccb_h.path),10352 xpt_path_lun_id(ccb->ccb_h.path));10353 if (status != CAM_REQ_CMP) {10354 kfree(lstate);10355 xpt_print_path(ccb->ccb_h.path);10356 printk("Couldn't allocate path\n");10357 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;10358 return;10359 }10360 SLIST_INIT(&lstate->accept_tios);10361 SLIST_INIT(&lstate->immed_notifies);10362 ahd_lock(ahd, &s);10363 ahd_pause(ahd);10364 if (target != CAM_TARGET_WILDCARD) {10365 tstate->enabled_luns[lun] = lstate;10366 ahd->enabled_luns++;10367 10368 if ((ahd->features & AHD_MULTI_TID) != 0) {10369 u_int targid_mask;10370 10371 targid_mask = ahd_inw(ahd, TARGID);10372 targid_mask |= target_mask;10373 ahd_outw(ahd, TARGID, targid_mask);10374 ahd_update_scsiid(ahd, targid_mask);10375 } else {10376 u_int our_id;10377 char channel;10378 10379 channel = SIM_CHANNEL(ahd, sim);10380 our_id = SIM_SCSI_ID(ahd, sim);10381 10382 /*10383 * This can only happen if selections10384 * are not enabled10385 */10386 if (target != our_id) {10387 u_int sblkctl;10388 char cur_channel;10389 int swap;10390 10391 sblkctl = ahd_inb(ahd, SBLKCTL);10392 cur_channel = (sblkctl & SELBUSB)10393 ? 'B' : 'A';10394 if ((ahd->features & AHD_TWIN) == 0)10395 cur_channel = 'A';10396 swap = cur_channel != channel;10397 ahd->our_id = target;10398 10399 if (swap)10400 ahd_outb(ahd, SBLKCTL,10401 sblkctl ^ SELBUSB);10402 10403 ahd_outb(ahd, SCSIID, target);10404 10405 if (swap)10406 ahd_outb(ahd, SBLKCTL, sblkctl);10407 }10408 }10409 } else10410 ahd->black_hole = lstate;10411 /* Allow select-in operations */10412 if (ahd->black_hole != NULL && ahd->enabled_luns > 0) {10413 scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE);10414 scsiseq1 |= ENSELI;10415 ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq1);10416 scsiseq1 = ahd_inb(ahd, SCSISEQ1);10417 scsiseq1 |= ENSELI;10418 ahd_outb(ahd, SCSISEQ1, scsiseq1);10419 }10420 ahd_unpause(ahd);10421 ahd_unlock(ahd, &s);10422 ccb->ccb_h.status = CAM_REQ_CMP;10423 xpt_print_path(ccb->ccb_h.path);10424 printk("Lun now enabled for target mode\n");10425 } else {10426 struct scb *scb;10427 int i, empty;10428 10429 if (lstate == NULL) {10430 ccb->ccb_h.status = CAM_LUN_INVALID;10431 return;10432 }10433 10434 ahd_lock(ahd, &s);10435 10436 ccb->ccb_h.status = CAM_REQ_CMP;10437 LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) {10438 struct ccb_hdr *ccbh;10439 10440 ccbh = &scb->io_ctx->ccb_h;10441 if (ccbh->func_code == XPT_CONT_TARGET_IO10442 && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){10443 printk("CTIO pending\n");10444 ccb->ccb_h.status = CAM_REQ_INVALID;10445 ahd_unlock(ahd, &s);10446 return;10447 }10448 }10449 10450 if (SLIST_FIRST(&lstate->accept_tios) != NULL) {10451 printk("ATIOs pending\n");10452 ccb->ccb_h.status = CAM_REQ_INVALID;10453 }10454 10455 if (SLIST_FIRST(&lstate->immed_notifies) != NULL) {10456 printk("INOTs pending\n");10457 ccb->ccb_h.status = CAM_REQ_INVALID;10458 }10459 10460 if (ccb->ccb_h.status != CAM_REQ_CMP) {10461 ahd_unlock(ahd, &s);10462 return;10463 }10464 10465 xpt_print_path(ccb->ccb_h.path);10466 printk("Target mode disabled\n");10467 xpt_free_path(lstate->path);10468 kfree(lstate);10469 10470 ahd_pause(ahd);10471 /* Can we clean up the target too? */10472 if (target != CAM_TARGET_WILDCARD) {10473 tstate->enabled_luns[lun] = NULL;10474 ahd->enabled_luns--;10475 for (empty = 1, i = 0; i < 8; i++)10476 if (tstate->enabled_luns[i] != NULL) {10477 empty = 0;10478 break;10479 }10480 10481 if (empty) {10482 ahd_free_tstate(ahd, target, channel,10483 /*force*/FALSE);10484 if (ahd->features & AHD_MULTI_TID) {10485 u_int targid_mask;10486 10487 targid_mask = ahd_inw(ahd, TARGID);10488 targid_mask &= ~target_mask;10489 ahd_outw(ahd, TARGID, targid_mask);10490 ahd_update_scsiid(ahd, targid_mask);10491 }10492 }10493 } else {10494 10495 ahd->black_hole = NULL;10496 10497 /*10498 * We can't allow selections without10499 * our black hole device.10500 */10501 empty = TRUE;10502 }10503 if (ahd->enabled_luns == 0) {10504 /* Disallow select-in */10505 u_int scsiseq1;10506 10507 scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE);10508 scsiseq1 &= ~ENSELI;10509 ahd_outb(ahd, SCSISEQ_TEMPLATE, scsiseq1);10510 scsiseq1 = ahd_inb(ahd, SCSISEQ1);10511 scsiseq1 &= ~ENSELI;10512 ahd_outb(ahd, SCSISEQ1, scsiseq1);10513 10514 if ((ahd->features & AHD_MULTIROLE) == 0) {10515 printk("Configuring Initiator Mode\n");10516 ahd->flags &= ~AHD_TARGETROLE;10517 ahd->flags |= AHD_INITIATORROLE;10518 ahd_pause(ahd);10519 ahd_loadseq(ahd);10520 ahd_restart(ahd);10521 /*10522 * Unpaused. The extra unpause10523 * that follows is harmless.10524 */10525 }10526 }10527 ahd_unpause(ahd);10528 ahd_unlock(ahd, &s);10529 }10530#endif10531}10532 10533static void10534ahd_update_scsiid(struct ahd_softc *ahd, u_int targid_mask)10535{10536#if NOT_YET10537 u_int scsiid_mask;10538 u_int scsiid;10539 10540 if ((ahd->features & AHD_MULTI_TID) == 0)10541 panic("ahd_update_scsiid called on non-multitid unit\n");10542 10543 /*10544 * Since we will rely on the TARGID mask10545 * for selection enables, ensure that OID10546 * in SCSIID is not set to some other ID10547 * that we don't want to allow selections on.10548 */10549 if ((ahd->features & AHD_ULTRA2) != 0)10550 scsiid = ahd_inb(ahd, SCSIID_ULTRA2);10551 else10552 scsiid = ahd_inb(ahd, SCSIID);10553 scsiid_mask = 0x1 << (scsiid & OID);10554 if ((targid_mask & scsiid_mask) == 0) {10555 u_int our_id;10556 10557 /* ffs counts from 1 */10558 our_id = ffs(targid_mask);10559 if (our_id == 0)10560 our_id = ahd->our_id;10561 else10562 our_id--;10563 scsiid &= TID;10564 scsiid |= our_id;10565 }10566 if ((ahd->features & AHD_ULTRA2) != 0)10567 ahd_outb(ahd, SCSIID_ULTRA2, scsiid);10568 else10569 ahd_outb(ahd, SCSIID, scsiid);10570#endif10571}10572 10573static void10574ahd_run_tqinfifo(struct ahd_softc *ahd, int paused)10575{10576 struct target_cmd *cmd;10577 10578 ahd_sync_tqinfifo(ahd, BUS_DMASYNC_POSTREAD);10579 while ((cmd = &ahd->targetcmds[ahd->tqinfifonext])->cmd_valid != 0) {10580 10581 /*10582 * Only advance through the queue if we10583 * have the resources to process the command.10584 */10585 if (ahd_handle_target_cmd(ahd, cmd) != 0)10586 break;10587 10588 cmd->cmd_valid = 0;10589 ahd_dmamap_sync(ahd, ahd->shared_data_dmat,10590 ahd->shared_data_map.dmamap,10591 ahd_targetcmd_offset(ahd, ahd->tqinfifonext),10592 sizeof(struct target_cmd),10593 BUS_DMASYNC_PREREAD);10594 ahd->tqinfifonext++;10595 10596 /*10597 * Lazily update our position in the target mode incoming10598 * command queue as seen by the sequencer.10599 */10600 if ((ahd->tqinfifonext & (HOST_TQINPOS - 1)) == 1) {10601 u_int hs_mailbox;10602 10603 hs_mailbox = ahd_inb(ahd, HS_MAILBOX);10604 hs_mailbox &= ~HOST_TQINPOS;10605 hs_mailbox |= ahd->tqinfifonext & HOST_TQINPOS;10606 ahd_outb(ahd, HS_MAILBOX, hs_mailbox);10607 }10608 }10609}10610 10611static int10612ahd_handle_target_cmd(struct ahd_softc *ahd, struct target_cmd *cmd)10613{10614 struct ahd_tmode_tstate *tstate;10615 struct ahd_tmode_lstate *lstate;10616 struct ccb_accept_tio *atio;10617 uint8_t *byte;10618 int initiator;10619 int target;10620 int lun;10621 10622 initiator = SCSIID_TARGET(ahd, cmd->scsiid);10623 target = SCSIID_OUR_ID(cmd->scsiid);10624 lun = (cmd->identify & MSG_IDENTIFY_LUNMASK);10625 10626 byte = cmd->bytes;10627 tstate = ahd->enabled_targets[target];10628 lstate = NULL;10629 if (tstate != NULL)10630 lstate = tstate->enabled_luns[lun];10631 10632 /*10633 * Commands for disabled luns go to the black hole driver.10634 */10635 if (lstate == NULL)10636 lstate = ahd->black_hole;10637 10638 atio = (struct ccb_accept_tio*)SLIST_FIRST(&lstate->accept_tios);10639 if (atio == NULL) {10640 ahd->flags |= AHD_TQINFIFO_BLOCKED;10641 /*10642 * Wait for more ATIOs from the peripheral driver for this lun.10643 */10644 return (1);10645 } else10646 ahd->flags &= ~AHD_TQINFIFO_BLOCKED;10647#ifdef AHD_DEBUG10648 if ((ahd_debug & AHD_SHOW_TQIN) != 0)10649 printk("Incoming command from %d for %d:%d%s\n",10650 initiator, target, lun,10651 lstate == ahd->black_hole ? "(Black Holed)" : "");10652#endif10653 SLIST_REMOVE_HEAD(&lstate->accept_tios, sim_links.sle);10654 10655 if (lstate == ahd->black_hole) {10656 /* Fill in the wildcards */10657 atio->ccb_h.target_id = target;10658 atio->ccb_h.target_lun = lun;10659 }10660 10661 /*10662 * Package it up and send it off to10663 * whomever has this lun enabled.10664 */10665 atio->sense_len = 0;10666 atio->init_id = initiator;10667 if (byte[0] != 0xFF) {10668 /* Tag was included */10669 atio->tag_action = *byte++;10670 atio->tag_id = *byte++;10671 atio->ccb_h.flags = CAM_TAG_ACTION_VALID;10672 } else {10673 atio->ccb_h.flags = 0;10674 }10675 byte++;10676 10677 /* Okay. Now determine the cdb size based on the command code */10678 switch (*byte >> CMD_GROUP_CODE_SHIFT) {10679 case 0:10680 atio->cdb_len = 6;10681 break;10682 case 1:10683 case 2:10684 atio->cdb_len = 10;10685 break;10686 case 4:10687 atio->cdb_len = 16;10688 break;10689 case 5:10690 atio->cdb_len = 12;10691 break;10692 case 3:10693 default:10694 /* Only copy the opcode. */10695 atio->cdb_len = 1;10696 printk("Reserved or VU command code type encountered\n");10697 break;10698 }10699 10700 memcpy(atio->cdb_io.cdb_bytes, byte, atio->cdb_len);10701 10702 atio->ccb_h.status |= CAM_CDB_RECVD;10703 10704 if ((cmd->identify & MSG_IDENTIFY_DISCFLAG) == 0) {10705 /*10706 * We weren't allowed to disconnect.10707 * We're hanging on the bus until a10708 * continue target I/O comes in response10709 * to this accept tio.10710 */10711#ifdef AHD_DEBUG10712 if ((ahd_debug & AHD_SHOW_TQIN) != 0)10713 printk("Received Immediate Command %d:%d:%d - %p\n",10714 initiator, target, lun, ahd->pending_device);10715#endif10716 ahd->pending_device = lstate;10717 ahd_freeze_ccb((union ccb *)atio);10718 atio->ccb_h.flags |= CAM_DIS_DISCONNECT;10719 }10720 xpt_done((union ccb*)atio);10721 return (0);10722}10723 10724#endif10725