diff options
Diffstat (limited to 'drivers/scsi/aic7xxx/aic79xx_core.c')
| -rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_core.c | 3117 |
1 files changed, 2026 insertions, 1091 deletions
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 137fb1a37dd..0bcacf71aef 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -37,9 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#202 $ - * - * $FreeBSD$ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#250 $ */ #ifdef __linux__ @@ -52,28 +50,26 @@ #include <dev/aic7xxx/aicasm/aicasm_insformat.h> #endif -/******************************** Globals *************************************/ -struct ahd_softc_tailq ahd_tailq = TAILQ_HEAD_INITIALIZER(ahd_tailq); /***************************** Lookup Tables **********************************/ -char *ahd_chip_names[] = +static const char *const ahd_chip_names[] = { "NONE", "aic7901", "aic7902", "aic7901A" }; -static const u_int num_chip_names = NUM_ELEMENTS(ahd_chip_names); +static const u_int num_chip_names = ARRAY_SIZE(ahd_chip_names); /* * Hardware error codes. */ struct ahd_hard_error_entry { uint8_t errno; - char *errmesg; + const char *errmesg; }; -static struct ahd_hard_error_entry ahd_hard_errors[] = { +static const struct ahd_hard_error_entry ahd_hard_errors[] = { { DSCTMOUT, "Discard Timer has timed out" }, { ILLOPCODE, "Illegal Opcode in sequencer program" }, { SQPARERR, "Sequencer Parity Error" }, @@ -81,9 +77,9 @@ static struct ahd_hard_error_entry ahd_hard_errors[] = { { MPARERR, "Scratch or SCB Memory Parity Error" }, { CIOPARERR, "CIOBUS Parity Error" }, }; -static const u_int num_errors = NUM_ELEMENTS(ahd_hard_errors); +static const u_int num_errors = ARRAY_SIZE(ahd_hard_errors); -static struct ahd_phase_table_entry ahd_phase_table[] = +static const struct ahd_phase_table_entry ahd_phase_table[] = { { P_DATAOUT, MSG_NOOP, "in Data-out phase" }, { P_DATAIN, MSG_INITIATOR_DET_ERR, "in Data-in phase" }, @@ -101,7 +97,7 @@ static struct ahd_phase_table_entry ahd_phase_table[] = * In most cases we only wish to itterate over real phases, so * exclude the last element from the count. */ -static const u_int num_phases = NUM_ELEMENTS(ahd_phase_table) - 1; +static const u_int num_phases = ARRAY_SIZE(ahd_phase_table) - 1; /* Our Sequencer Program */ #include "aic79xx_seq.h" @@ -201,7 +197,8 @@ static int ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, int lun, u_int tag, role_t role, uint32_t status, ahd_search_action action, - u_int *list_head, u_int tid); + u_int *list_head, u_int *list_tail, + u_int tid); static void ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev, u_int tid_cur, u_int tid_next); @@ -210,14 +207,13 @@ static void ahd_add_scb_to_free_list(struct ahd_softc *ahd, static u_int ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid, u_int prev, u_int next, u_int tid); static void ahd_reset_current_bus(struct ahd_softc *ahd); -static ahd_callback_t ahd_reset_poll; static ahd_callback_t ahd_stat_timer; #ifdef AHD_DUMP_SEQ static void ahd_dumpseq(struct ahd_softc *ahd); #endif static void ahd_loadseq(struct ahd_softc *ahd); static int ahd_check_patch(struct ahd_softc *ahd, - struct patch **start_patch, + const struct patch **start_patch, u_int start_instr, u_int *skip_addr); static u_int ahd_resolve_seqaddr(struct ahd_softc *ahd, u_int address); @@ -241,12 +237,804 @@ static int ahd_handle_target_cmd(struct ahd_softc *ahd, struct target_cmd *cmd); #endif -/******************************** Private Inlines *****************************/ -static __inline void ahd_assert_atn(struct ahd_softc *ahd); -static __inline int ahd_currently_packetized(struct ahd_softc *ahd); -static __inline int ahd_set_active_fifo(struct ahd_softc *ahd); +static int ahd_abort_scbs(struct ahd_softc *ahd, int target, + char channel, int lun, u_int tag, + role_t role, uint32_t status); +static void ahd_alloc_scbs(struct ahd_softc *ahd); +static void ahd_busy_tcl(struct ahd_softc *ahd, u_int tcl, + u_int scbid); +static void ahd_calc_residual(struct ahd_softc *ahd, + struct scb *scb); +static void ahd_clear_critical_section(struct ahd_softc *ahd); +static void ahd_clear_intstat(struct ahd_softc *ahd); +static void ahd_enable_coalescing(struct ahd_softc *ahd, + int enable); +static u_int ahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl); +static void ahd_freeze_devq(struct ahd_softc *ahd, + struct scb *scb); +static void ahd_handle_scb_status(struct ahd_softc *ahd, + struct scb *scb); +static const struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase); +static void ahd_shutdown(void *arg); +static void ahd_update_coalescing_values(struct ahd_softc *ahd, + u_int timer, + u_int maxcmds, + u_int mincmds); +static int ahd_verify_vpd_cksum(struct vpd_config *vpd); +static int ahd_wait_seeprom(struct ahd_softc *ahd); +static int ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, + int target, char channel, int lun, + u_int tag, role_t role); + +static void ahd_reset_cmds_pending(struct ahd_softc *ahd); + +/*************************** Interrupt Services *******************************/ +static void ahd_run_qoutfifo(struct ahd_softc *ahd); +#ifdef AHD_TARGET_MODE +static void ahd_run_tqinfifo(struct ahd_softc *ahd, int paused); +#endif +static void ahd_handle_hwerrint(struct ahd_softc *ahd); +static void ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat); +static void ahd_handle_scsiint(struct ahd_softc *ahd, + u_int intstat); + +/************************ Sequencer Execution Control *************************/ +void +ahd_set_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst) +{ + if (ahd->src_mode == src && ahd->dst_mode == dst) + return; +#ifdef AHD_DEBUG + if (ahd->src_mode == AHD_MODE_UNKNOWN + || ahd->dst_mode == AHD_MODE_UNKNOWN) + panic("Setting mode prior to saving it.\n"); + if ((ahd_debug & AHD_SHOW_MODEPTR) != 0) + printk("%s: Setting mode 0x%x\n", ahd_name(ahd), + ahd_build_mode_state(ahd, src, dst)); +#endif + ahd_outb(ahd, MODE_PTR, ahd_build_mode_state(ahd, src, dst)); + ahd->src_mode = src; + ahd->dst_mode = dst; +} + +static void +ahd_update_modes(struct ahd_softc *ahd) +{ + ahd_mode_state mode_ptr; + ahd_mode src; + ahd_mode dst; + + mode_ptr = ahd_inb(ahd, MODE_PTR); +#ifdef AHD_DEBUG + if ((ahd_debug & AHD_SHOW_MODEPTR) != 0) + printk("Reading mode 0x%x\n", mode_ptr); +#endif + ahd_extract_mode_state(ahd, mode_ptr, &src, &dst); + ahd_known_modes(ahd, src, dst); +} + +static void +ahd_assert_modes(struct ahd_softc *ahd, ahd_mode srcmode, + ahd_mode dstmode, const char *file, int line) +{ +#ifdef AHD_DEBUG + if ((srcmode & AHD_MK_MSK(ahd->src_mode)) == 0 + || (dstmode & AHD_MK_MSK(ahd->dst_mode)) == 0) { + panic("%s:%s:%d: Mode assertion failed.\n", + ahd_name(ahd), file, line); + } +#endif +} + +#define AHD_ASSERT_MODES(ahd, source, dest) \ + ahd_assert_modes(ahd, source, dest, __FILE__, __LINE__); + +ahd_mode_state +ahd_save_modes(struct ahd_softc *ahd) +{ + if (ahd->src_mode == AHD_MODE_UNKNOWN + || ahd->dst_mode == AHD_MODE_UNKNOWN) + ahd_update_modes(ahd); + + return (ahd_build_mode_state(ahd, ahd->src_mode, ahd->dst_mode)); +} + +void +ahd_restore_modes(struct ahd_softc *ahd, ahd_mode_state state) +{ + ahd_mode src; + ahd_mode dst; + + ahd_extract_mode_state(ahd, state, &src, &dst); + ahd_set_modes(ahd, src, dst); +} + +/* + * Determine whether the sequencer has halted code execution. + * Returns non-zero status if the sequencer is stopped. + */ +int +ahd_is_paused(struct ahd_softc *ahd) +{ + return ((ahd_inb(ahd, HCNTRL) & PAUSE) != 0); +} + +/* + * Request that the sequencer stop and wait, indefinitely, for it + * to stop. The sequencer will only acknowledge that it is paused + * once it has reached an instruction boundary and PAUSEDIS is + * cleared in the SEQCTL register. The sequencer may use PAUSEDIS + * for critical sections. + */ +void +ahd_pause(struct ahd_softc *ahd) +{ + ahd_outb(ahd, HCNTRL, ahd->pause); + + /* + * Since the sequencer can disable pausing in a critical section, we + * must loop until it actually stops. + */ + while (ahd_is_paused(ahd) == 0) + ; +} + +/* + * Allow the sequencer to continue program execution. + * We check here to ensure that no additional interrupt + * sources that would cause the sequencer to halt have been + * asserted. If, for example, a SCSI bus reset is detected + * while we are fielding a different, pausing, interrupt type, + * we don't want to release the sequencer before going back + * into our interrupt handler and dealing with this new + * condition. + */ +void +ahd_unpause(struct ahd_softc *ahd) +{ + /* + * Automatically restore our modes to those saved + * prior to the first change of the mode. + */ + if (ahd->saved_src_mode != AHD_MODE_UNKNOWN + && ahd->saved_dst_mode != AHD_MODE_UNKNOWN) { + if ((ahd->flags & AHD_UPDATE_PEND_CMDS) != 0) + ahd_reset_cmds_pending(ahd); + ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode); + } + + if ((ahd_inb(ahd, INTSTAT) & ~CMDCMPLT) == 0) + ahd_outb(ahd, HCNTRL, ahd->unpause); + + ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN); +} + +/*********************** Scatter Gather List Handling *************************/ +void * +ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb, + void *sgptr, dma_addr_t addr, bus_size_t len, int last) +{ + scb->sg_count++; + if (sizeof(dma_addr_t) > 4 + && (ahd->flags & AHD_64BIT_ADDRESSING) != 0) { + struct ahd_dma64_seg *sg; + + sg = (struct ahd_dma64_seg *)sgptr; + sg->addr = ahd_htole64(addr); + sg->len = ahd_htole32(len | (last ? AHD_DMA_LAST_SEG : 0)); + return (sg + 1); + } else { + struct ahd_dma_seg *sg; + + sg = (struct ahd_dma_seg *)sgptr; + sg->addr = ahd_htole32(addr & 0xFFFFFFFF); + sg->len = ahd_htole32(len | ((addr >> 8) & 0x7F000000) + | (last ? AHD_DMA_LAST_SEG : 0)); + return (sg + 1); + } +} + +static void +ahd_setup_scb_common(struct ahd_softc *ahd, struct scb *scb) +{ + /* XXX Handle target mode SCBs. */ + scb->crc_retry_count = 0; + if ((scb->flags & SCB_PACKETIZED) != 0) { + /* XXX what about ACA?? It is type 4, but TAG_TYPE == 0x3. */ + scb->hscb->task_attribute = scb->hscb->control & SCB_TAG_TYPE; + } else { + if (ahd_get_transfer_length(scb) & 0x01) + scb->hscb->task_attribute = SCB_XFERLEN_ODD; + else + scb->hscb->task_attribute = 0; + } + + if (scb->hscb->cdb_len <= MAX_CDB_LEN_WITH_SENSE_ADDR + || (scb->hscb->cdb_len & SCB_CDB_LEN_PTR) != 0) + scb->hscb->shared_data.idata.cdb_plus_saddr.sense_addr = + ahd_htole32(scb->sense_busaddr); +} + +static void +ahd_setup_data_scb(struct ahd_softc *ahd, struct scb *scb) +{ + /* + * Copy the first SG into the "current" data ponter area. + */ + if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0) { + struct ahd_dma64_seg *sg; + + sg = (struct ahd_dma64_seg *)scb->sg_list; + scb->hscb->dataptr = sg->addr; + scb->hscb->datacnt = sg->len; + } else { + struct ahd_dma_seg *sg; + uint32_t *dataptr_words; + + sg = (struct ahd_dma_seg *)scb->sg_list; + dataptr_words = (uint32_t*)&scb->hscb->dataptr; + dataptr_words[0] = sg->addr; + dataptr_words[1] = 0; + if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) { + uint64_t high_addr; + + high_addr = ahd_le32toh(sg->len) & 0x7F000000; + scb->hscb->dataptr |= ahd_htole64(high_addr << 8); + } + scb->hscb->datacnt = sg->len; + } + /* + * Note where to find the SG entries in bus space. + * We also set the full residual flag which the + * sequencer will clear as soon as a data transfer + * occurs. + */ + scb->hscb->sgptr = ahd_htole32(scb->sg_list_busaddr|SG_FULL_RESID); +} + +static void +ahd_setup_noxfer_scb(struct ahd_softc *ahd, struct scb *scb) +{ + scb->hscb->sgptr = ahd_htole32(SG_LIST_NULL); + scb->hscb->dataptr = 0; + scb->hscb->datacnt = 0; +} + +/************************** Memory mapping routines ***************************/ +static void * +ahd_sg_bus_to_virt(struct ahd_softc *ahd, struct scb *scb, uint32_t sg_busaddr) +{ + dma_addr_t sg_offset; + + /* sg_list_phys points to entry 1, not 0 */ + sg_offset = sg_busaddr - (scb->sg_list_busaddr - ahd_sg_size(ahd)); + return ((uint8_t *)scb->sg_list + sg_offset); +} + +static uint32_t +ahd_sg_virt_to_bus(struct ahd_softc *ahd, struct scb *scb, void *sg) +{ + dma_addr_t sg_offset; + + /* sg_list_phys points to entry 1, not 0 */ + sg_offset = ((uint8_t *)sg - (uint8_t *)scb->sg_list) + - ahd_sg_size(ahd); + + return (scb->sg_list_busaddr + sg_offset); +} + +static void +ahd_sync_scb(struct ahd_softc *ahd, struct scb *scb, int op) +{ + ahd_dmamap_sync(ahd, ahd->scb_data.hscb_dmat, + scb->hscb_map->dmamap, + /*offset*/(uint8_t*)scb->hscb - scb->hscb_map->vaddr, + /*len*/sizeof(*scb->hscb), op); +} + +void +ahd_sync_sglist(struct ahd_softc *ahd, struct scb *scb, int op) +{ + if (scb->sg_count == 0) + return; + + ahd_dmamap_sync(ahd, ahd->scb_data.sg_dmat, + scb->sg_map->dmamap, + /*offset*/scb->sg_list_busaddr - ahd_sg_size(ahd), + /*len*/ahd_sg_size(ahd) * scb->sg_count, op); +} + +static void +ahd_sync_sense(struct ahd_softc *ahd, struct scb *scb, int op) +{ + ahd_dmamap_sync(ahd, ahd->scb_data.sense_dmat, + scb->sense_map->dmamap, + /*offset*/scb->sense_busaddr, + /*len*/AHD_SENSE_BUFSIZE, op); +} + +#ifdef AHD_TARGET_MODE +static uint32_t +ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index) +{ + return (((uint8_t *)&ahd->targetcmds[index]) + - (uint8_t *)ahd->qoutfifo); +} +#endif + +/*********************** Miscellaneous Support Functions ***********************/ +/* + * Return pointers to the transfer negotiation information + * for the specified our_id/remote_id pair. + */ +struct ahd_initiator_tinfo * +ahd_fetch_transinfo(struct ahd_softc *ahd, char channel, u_int our_id, + u_int remote_id, struct ahd_tmode_tstate **tstate) +{ + /* + * Transfer data structures are stored from the perspective + * of the target role. Since the parameters for a connection + * in the initiator role to a given target are the same as + * when the roles are reversed, we pretend we are the target. + */ + if (channel == 'B') + our_id += 8; + *tstate = ahd->enabled_targets[our_id]; + return (&(*tstate)->transinfo[remote_id]); +} + +uint16_t +ahd_inw(struct ahd_softc *ahd, u_int port) +{ + /* + * Read high byte first as some registers increment + * or have other side effects when the low byte is + * read. + */ + uint16_t r = ahd_inb(ahd, port+1) << 8; + return r | ahd_inb(ahd, port); +} + +void +ahd_outw(struct ahd_softc *ahd, u_int port, u_int value) +{ + /* + * Write low byte first to accommodate registers + * such as PRGMCNT where the order maters. + */ + ahd_outb(ahd, port, value & 0xFF); + ahd_outb(ahd, port+1, (value >> 8) & 0xFF); +} + +uint32_t +ahd_inl(struct ahd_softc *ahd, u_int port) +{ + return ((ahd_inb(ahd, port)) + | (ahd_inb(ahd, port+1) << 8) + | (ahd_inb(ahd, port+2) << 16) + | (ahd_inb(ahd, port+3) << 24)); +} + +void +ahd_outl(struct ahd_softc *ahd, u_int port, uint32_t value) +{ + ahd_outb(ahd, port, (value) & 0xFF); + ahd_outb(ahd, port+1, ((value) >> 8) & 0xFF); + ahd_outb(ahd, port+2, ((value) >> 16) & 0xFF); + ahd_outb(ahd, port+3, ((value) >> 24) & 0xFF); +} + +uint64_t +ahd_inq(struct ahd_softc *ahd, u_int port) +{ + return ((ahd_inb(ahd, port)) + | (ahd_inb(ahd, port+1) << 8) + | (ahd_inb(ahd, port+2) << 16) + | (ahd_inb(ahd, port+3) << 24) + | (((uint64_t)ahd_inb(ahd, port+4)) << 32) + | (((uint64_t)ahd_inb(ahd, port+5)) << 40) + | (((uint64_t)ahd_inb(ahd, port+6)) << 48) + | (((uint64_t)ahd_inb(ahd, port+7)) << 56)); +} + +void +ahd_outq(struct ahd_softc *ahd, u_int port, uint64_t value) +{ + ahd_outb(ahd, port, value & 0xFF); + ahd_outb(ahd, port+1, (value >> 8) & 0xFF); + ahd_outb(ahd, port+2, (value >> 16) & 0xFF); + ahd_outb(ahd, port+3, (value >> 24) & 0xFF); + ahd_outb(ahd, port+4, (value >> 32) & 0xFF); + ahd_outb(ahd, port+5, (value >> 40) & 0xFF); + ahd_outb(ahd, port+6, (value >> 48) & 0xFF); + ahd_outb(ahd, port+7, (value >> 56) & 0xFF); +} + +u_int +ahd_get_scbptr(struct ahd_softc *ahd) +{ + AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK), + ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK)); + return (ahd_inb(ahd, SCBPTR) | (ahd_inb(ahd, SCBPTR + 1) << 8)); +} + +void +ahd_set_scbptr(struct ahd_softc *ahd, u_int scbptr) +{ + AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK), + ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK)); + ahd_outb(ahd, SCBPTR, scbptr & 0xFF); + ahd_outb(ahd, SCBPTR+1, (scbptr >> 8) & 0xFF); +} + +#if 0 /* unused */ +static u_int +ahd_get_hnscb_qoff(struct ahd_softc *ahd) +{ + return (ahd_inw_atomic(ahd, HNSCB_QOFF)); +} +#endif + +static void +ahd_set_hnscb_qoff(struct ahd_softc *ahd, u_int value) +{ + ahd_outw_atomic(ahd, HNSCB_QOFF, value); +} + +#if 0 /* unused */ +static u_int +ahd_get_hescb_qoff(struct ahd_softc *ahd) +{ + return (ahd_inb(ahd, HESCB_QOFF)); +} +#endif + +static void +ahd_set_hescb_qoff(struct ahd_softc *ahd, u_int value) +{ + ahd_outb(ahd, HESCB_QOFF, value); +} + +static u_int +ahd_get_snscb_qoff(struct ahd_softc *ahd) +{ + u_int oldvalue; + + AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); + oldvalue = ahd_inw(ahd, SNSCB_QOFF); + ahd_outw(ahd, SNSCB_QOFF, oldvalue); + return (oldvalue); +} + +static void +ahd_set_snscb_qoff(struct ahd_softc *ahd, u_int value) +{ + AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); + ahd_outw(ahd, SNSCB_QOFF, value); +} + +#if 0 /* unused */ +static u_int +ahd_get_sescb_qoff(struct ahd_softc *ahd) +{ + AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); + return (ahd_inb(ahd, SESCB_QOFF)); +} +#endif + +static void +ahd_set_sescb_qoff(struct ahd_softc *ahd, u_int value) +{ + AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); + ahd_outb(ahd, SESCB_QOFF, value); +} + +#if 0 /* unused */ +static u_int +ahd_get_sdscb_qoff(struct ahd_softc *ahd) +{ + AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); + return (ahd_inb(ahd, SDSCB_QOFF) | (ahd_inb(ahd, SDSCB_QOFF + 1) << 8)); +} +#endif + +static void +ahd_set_sdscb_qoff(struct ahd_softc *ahd, u_int value) +{ + AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); + ahd_outb(ahd, SDSCB_QOFF, value & 0xFF); + ahd_outb(ahd, SDSCB_QOFF+1, (value >> 8) & 0xFF); +} + +u_int +ahd_inb_scbram(struct ahd_softc *ahd, u_int offset) +{ + u_int value; + + /* + * Workaround PCI-X Rev A. hardware bug. + * After a host read of SCB memory, the chip + * may become confused into thinking prefetch + * was required. This starts the discard timer + * running and can cause an unexpected discard + * timer interrupt. The work around is to read + * a normal register prior to the exhaustion of + * the discard timer. The mode pointer register + * has no side effects and so serves well for + * this purpose. + * + * Razor #528 + */ + value = ahd_inb(ahd, offset); + if ((ahd->bugs & AHD_PCIX_SCBRAM_RD_BUG) != 0) + ahd_inb(ahd, MODE_PTR); + return (value); +} + +u_int +ahd_inw_scbram(struct ahd_softc *ahd, u_int offset) +{ + return (ahd_inb_scbram(ahd, offset) + | (ahd_inb_scbram(ahd, offset+1) << 8)); +} + +static uint32_t +ahd_inl_scbram(struct ahd_softc *ahd, u_int offset) +{ + return (ahd_inw_scbram(ahd, offset) + | (ahd_inw_scbram(ahd, offset+2) << 16)); +} + +static uint64_t +ahd_inq_scbram(struct ahd_softc *ahd, u_int offset) +{ + return (ahd_inl_scbram(ahd, offset) + | ((uint64_t)ahd_inl_scbram(ahd, offset+4)) << 32); +} + +struct scb * +ahd_lookup_scb(struct ahd_softc *ahd, u_int tag) +{ + struct scb* scb; + + if (tag >= AHD_SCB_MAX) + return (NULL); + scb = ahd->scb_data.scbindex[tag]; + if (scb != NULL) + ahd_sync_scb(ahd, scb, + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + return (scb); +} + +static void +ahd_swap_with_next_hscb(struct ahd_softc *ahd, struct scb *scb) +{ + struct hardware_scb *q_hscb; + struct map_node *q_hscb_map; + uint32_t saved_hscb_busaddr; + + /* + * Our queuing method is a bit tricky. The card + * knows in advance which HSCB (by address) to download, + * and we can't disappoint it. To achieve this, the next + * HSCB to download is saved off in ahd->next_queued_hscb. + * When we are called to queue "an arbitrary scb", + * we copy the contents of the incoming HSCB to the one + * the sequencer knows about, swap HSCB pointers and + * finally assign the SCB to the tag indexed location + * in the scb_array. This makes sure that we can still + * locate the correct SCB by SCB_TAG. + */ + q_hscb = ahd->next_queued_hscb; + q_hscb_map = ahd->next_queued_hscb_map; + saved_hscb_busaddr = q_hscb->hscb_busaddr; + memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb)); + q_hscb->hscb_busaddr = saved_hscb_busaddr; + q_hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr; + + /* Now swap HSCB pointers. */ + ahd->next_queued_hscb = scb->hscb; + ahd->next_queued_hscb_map = scb->hscb_map; + scb->hscb = q_hscb; + scb->hscb_map = q_hscb_map; -static __inline void + /* Now define the mapping from tag to SCB in the scbindex */ + ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb; +} + +/* + * Tell the sequencer about a new transaction to execute. + */ +void +ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb) +{ + ahd_swap_with_next_hscb(ahd, scb); + + if (SCBID_IS_NULL(SCB_GET_TAG(scb))) + panic("Attempt to queue invalid SCB tag %x\n", + SCB_GET_TAG(scb)); + + /* + * Keep a history of SCBs we've downloaded in the qinfifo. + */ + ahd->qinfifo[AHD_QIN_WRAP(ahd->qinfifonext)] = SCB_GET_TAG(scb); + ahd->qinfifonext++; + + if (scb->sg_count != 0) + ahd_setup_data_scb(ahd, scb); + else + ahd_setup_noxfer_scb(ahd, scb); + ahd_setup_scb_common(ahd, scb); + + /* + * Make sure our data is consistent from the + * perspective of the adapter. + */ + ahd_sync_scb(ahd, scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + +#ifdef AHD_DEBUG + if ((ahd_debug & AHD_SHOW_QUEUE) != 0) { + uint64_t host_dataptr; + + host_dataptr = ahd_le64toh(scb->hscb->dataptr); + printk("%s: Queueing SCB %d:0x%x bus addr 0x%x - 0x%x%x/0x%x\n", + ahd_name(ahd), + SCB_GET_TAG(scb), scb->hscb->scsiid, + ahd_le32toh(scb->hscb->hscb_busaddr), + (u_int)((host_dataptr >> 32) & 0xFFFFFFFF), + (u_int)(host_dataptr & 0xFFFFFFFF), + ahd_le32toh(scb->hscb->datacnt)); + } +#endif + /* Tell the adapter about the newly queued SCB */ + ahd_set_hnscb_qoff(ahd, ahd->qinfifonext); +} + +/************************** Interrupt Processing ******************************/ +static void +ahd_sync_qoutfifo(struct ahd_softc *ahd, int op) +{ + ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, + /*offset*/0, + /*len*/AHD_SCB_MAX * sizeof(struct ahd_completion), op); +} + +static void +ahd_sync_tqinfifo(struct ahd_softc *ahd, int op) +{ +#ifdef AHD_TARGET_MODE + if ((ahd->flags & AHD_TARGETROLE) != 0) { + ahd_dmamap_sync(ahd, ahd->shared_data_dmat, + ahd->shared_data_map.dmamap, + ahd_targetcmd_offset(ahd, 0), + sizeof(struct target_cmd) * AHD_TMODE_CMDS, + op); + } +#endif +} + +/* + * See if the firmware has posted any completed commands + * into our in-core command complete fifos. + */ +#define AHD_RUN_QOUTFIFO 0x1 +#define AHD_RUN_TQINFIFO 0x2 +static u_int +ahd_check_cmdcmpltqueues(struct ahd_softc *ahd) +{ + u_int retval; + + retval = 0; + ahd_dmamap_sync(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, + /*offset*/ahd->qoutfifonext * sizeof(*ahd->qoutfifo), + /*len*/sizeof(*ahd->qoutfifo), BUS_DMASYNC_POSTREAD); + if (ahd->qoutfifo[ahd->qoutfifonext].valid_tag + == ahd->qoutfifonext_valid_tag) + retval |= AHD_RUN_QOUTFIFO; +#ifdef AHD_TARGET_MODE + if ((ahd->flags & AHD_TARGETROLE) != 0 + && (ahd->flags & AHD_TQINFIFO_BLOCKED) == 0) { + ahd_dmamap_sync(ahd, ahd->shared_data_dmat, + ahd->shared_data_map.dmamap, + ahd_targetcmd_offset(ahd, ahd->tqinfifofnext), + /*len*/sizeof(struct target_cmd), + BUS_DMASYNC_POSTREAD); + if (ahd->targetcmds[ahd->tqinfifonext].cmd_valid != 0) + retval |= AHD_RUN_TQINFIFO; + } +#endif + return (retval); +} + +/* + * Catch an interrupt from the adapter + */ +int +ahd_intr(struct ahd_softc *ahd) +{ + u_int intstat; + + if ((ahd->pause & INTEN) == 0) { + /* + * Our interrupt is not enabled on the chip + * and may be disabled for re-entrancy reasons, + * so just return. This is likely just a shared + * interrupt. + */ + return (0); + } + + /* + * Instead of directly reading the interrupt status register, + * infer the cause of the interrupt by checking our in-core + * completion queues. This avoids a costly PCI bus read in + * most cases. + */ + if ((ahd->flags & AHD_ALL_INTERRUPTS) == 0 + && (ahd_check_cmdcmpltqueues(ahd) != 0)) + intstat = CMDCMPLT; + else + intstat = ahd_inb(ahd, INTSTAT); + + if ((intstat & INT_PEND) == 0) + return (0); + + if (intstat & CMDCMPLT) { + ahd_outb(ahd, CLRINT, CLRCMDINT); + + /* + * Ensure that the chip sees that we've cleared + * this interrupt before we walk the output fifo. + * Otherwise, we may, due to posted bus writes, + * clear the interrupt after we finish the scan, + * and after the sequencer has added new entries + * and asserted the interrupt again. + */ + if ((ahd->bugs & AHD_INTCOLLISION_BUG) != 0) { + if (ahd_is_paused(ahd)) { + /* + * Potentially lost SEQINT. + * If SEQINTCODE is non-zero, + * simulate the SEQINT. + */ + if (ahd_inb(ahd, SEQINTCODE) != NO_SEQINT) + intstat |= SEQINT; + } + } else { + ahd_flush_device_writes(ahd); + } + ahd_run_qoutfifo(ahd); + ahd->cmdcmplt_counts[ahd->cmdcmplt_bucket]++; + ahd->cmdcmplt_total++; +#ifdef AHD_TARGET_MODE + if ((ahd->flags & AHD_TARGETROLE) != 0) + ahd_run_tqinfifo(ahd, /*paused*/FALSE); +#endif + } + + /* + * Handle statuses that may invalidate our cached + * copy of INTSTAT separately. + */ + if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) { + /* Hot eject. Do nothing */ + } else if (intstat & HWERRINT) { + ahd_handle_hwerrint(ahd); + } else if ((intstat & (PCIINT|SPLTINT)) != 0) { + ahd->bus_intr(ahd); + } else { + + if ((intstat & SEQINT) != 0) + ahd_handle_seqint(ahd, intstat); + + if ((intstat & SCSIINT) != 0) + ahd_handle_scsiint(ahd, intstat); + } + return (1); +} + +/******************************** Private Inlines *****************************/ +static inline void ahd_assert_atn(struct ahd_softc *ahd) { ahd_outb(ahd, SCSISIGO, ATNO); @@ -258,7 +1046,7 @@ ahd_assert_atn(struct ahd_softc *ahd) * are currently in a packetized transfer. We could * just as easily be sending or receiving a message. */ -static __inline int +static int ahd_currently_packetized(struct ahd_softc *ahd) { ahd_mode_state saved_modes; @@ -281,7 +1069,7 @@ ahd_currently_packetized(struct ahd_softc *ahd) return (packetized); } -static __inline int +static inline int ahd_set_active_fifo(struct ahd_softc *ahd) { u_int active_fifo; @@ -298,11 +1086,44 @@ ahd_set_active_fifo(struct ahd_softc *ahd) } } +static inline void +ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl) +{ + ahd_busy_tcl(ahd, tcl, SCB_LIST_NULL); +} + +/* + * Determine whether the sequencer reported a residual + * for this SCB/transaction. + */ +static inline void +ahd_update_residual(struct ahd_softc *ahd, struct scb *scb) +{ + uint32_t sgptr; + + sgptr = ahd_le32toh(scb->hscb->sgptr); + if ((sgptr & SG_STATUS_VALID) != 0) + ahd_calc_residual(ahd, scb); +} + +static inline void +ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb) +{ + uint32_t sgptr; + + sgptr = ahd_le32toh(scb->hscb->sgptr); + if ((sgptr & SG_STATUS_VALID) != 0) + ahd_handle_scb_status(ahd, scb); + else + ahd_done(ahd, scb); +} + + /************************* Sequencer Execution Control ************************/ /* * Restart the sequencer program from address zero */ -void +static void ahd_restart(struct ahd_softc *ahd) { @@ -334,18 +1155,26 @@ ahd_restart(struct ahd_softc *ahd) ahd_outb(ahd, SCSISEQ1, ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP)); ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); + + /* + * Clear any pending sequencer interrupt. It is no + * longer relevant since we're resetting the Program + * Counter. + */ + ahd_outb(ahd, CLRINT, CLRSEQINT); + ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET); ahd_unpause(ahd); } -void +static void ahd_clear_fifo(struct ahd_softc *ahd, u_int fifo) { ahd_mode_state saved_modes; #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_FIFOS) != 0) - printf("%s: Clearing FIFO %d\n", ahd_name(ahd), fifo); + printk("%s: Clearing FIFO %d\n", ahd_name(ahd), fifo); #endif saved_modes = ahd_save_modes(ahd); ahd_set_modes(ahd, fifo, fifo); @@ -362,7 +1191,7 @@ ahd_clear_fifo(struct ahd_softc *ahd, u_int fifo) * Flush and completed commands that are sitting in the command * complete queues down on the chip but have yet to be dma'ed back up. */ -void +static void ahd_flush_qoutfifo(struct ahd_softc *ahd) { struct scb *scb; @@ -375,13 +1204,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) saved_modes = ahd_save_modes(ahd); /* - * Complete any SCBs that just finished being - * DMA'ed into the qoutfifo. - */ - ahd_run_qoutfifo(ahd); - - /* - * Flush the good status FIFO for compelted packetized commands. + * Flush the good status FIFO for completed packetized commands. */ ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); saved_scbptr = ahd_get_scbptr(ahd); @@ -389,11 +1212,10 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) u_int fifo_mode; u_int i; - scbid = (ahd_inb(ahd, GSFIFO+1) << 8) - | ahd_inb(ahd, GSFIFO); + scbid = ahd_inw(ahd, GSFIFO); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: Warning - GSFIFO SCB %d invalid\n", + printk("%s: Warning - GSFIFO SCB %d invalid\n", ahd_name(ahd), scbid); continue; } @@ -403,22 +1225,33 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) * the host before completing the command. */ fifo_mode = 0; +rescan_fifos: for (i = 0; i < 2; i++) { /* Toggle to the other mode. */ fifo_mode ^= 1; ahd_set_modes(ahd, fifo_mode, fifo_mode); + if (ahd_scb_active_in_fifo(ahd, scb) == 0) continue; ahd_run_data_fifo(ahd, scb); /* - * Clearing this transaction in this FIFO may - * cause a CFG4DATA for this same transaction - * to assert in the other FIFO. Make sure we - * loop one more time and check the other FIFO. + * Running this FIFO may cause a CFG4DATA for + * this same transaction to assert in the other + * FIFO or a new snapshot SAVEPTRS interrupt + * in this FIFO. Even running a FIFO may not + * clear the transaction if we are still waiting + * for data to drain to the host. We must loop + * until the transaction is not active in either + * FIFO just to be sure. Reset our loop counter + * so we will visit both FIFOs again before + * declaring this transaction finished. We + * also delay a bit so that status has a chance + * to change before we look at this FIFO again. */ - i = 0; + ahd_delay(200); + goto rescan_fifos; } ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); ahd_set_scbptr(ahd, scbid); @@ -431,19 +1264,28 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) /* * The transfer completed with a residual. * Place this SCB on the complete DMA list - * so that we Update our in-core copy of the + * so that we update our in-core copy of the * SCB before completing the command. */ ahd_outb(ahd, SCB_SCSI_STATUS, 0); ahd_outb(ahd, SCB_SGPTR, ahd_inb_scbram(ahd, SCB_SGPTR) | SG_STATUS_VALID); - ahd_outw(ahd, SCB_TAG, SCB_GET_TAG(scb)); + ahd_outw(ahd, SCB_TAG, scbid); + ahd_outw(ahd, SCB_NEXT_COMPLETE, SCB_LIST_NULL); comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD); - ahd_outw(ahd, SCB_NEXT_COMPLETE, comp_head); - if (SCBID_IS_NULL(comp_head)) - ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, - SCB_GET_TAG(scb)); + if (SCBID_IS_NULL(comp_head)) { + ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, scbid); + ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid); + } else { + u_int tail; + + tail = ahd_inw(ahd, COMPLETE_DMA_SCB_TAIL); + ahd_set_scbptr(ahd, tail); + ahd_outw(ahd, SCB_NEXT_COMPLETE, scbid); + ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid); + ahd_set_scbptr(ahd, scbid); + } } else ahd_complete_scb(ahd, scb); } @@ -467,9 +1309,22 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) break; ahd_delay(200); } - if ((ccscbctl & CCSCBDIR) != 0) + /* + * We leave the sequencer to cleanup in the case of DMA's to + * update the qoutfifo. In all other cases (DMA's to the + * chip or a push of an SCB from the COMPLETE_DMA_SCB list), + * we disable the DMA engine so that the sequencer will not + * attempt to handle the DMA completion. + */ + if ((ccscbctl & CCSCBDIR) != 0 || (ccscbctl & ARRDONE) != 0) ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN)); + /* + * Complete any SCBs that just finished + * being DMA'ed into the qoutfifo. + */ + ahd_run_qoutfifo(ahd); + saved_scbptr = ahd_get_scbptr(ahd); /* * Manually update/complete any completed SCBs that are waiting to be @@ -484,7 +1339,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: Warning - DMA-up and complete " + printk("%s: Warning - DMA-up and complete " "SCB %d invalid\n", ahd_name(ahd), scbid); continue; } @@ -496,6 +1351,24 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) scbid = next_scbid; } ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL); + ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL); + + scbid = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD); + while (!SCBID_IS_NULL(scbid)) { + + ahd_set_scbptr(ahd, scbid); + next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); + scb = ahd_lookup_scb(ahd, scbid); + if (scb == NULL) { + printk("%s: Warning - Complete Qfrz SCB %d invalid\n", + ahd_name(ahd), scbid); + continue; + } + + ahd_complete_scb(ahd, scb); + scbid = next_scbid; + } + ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL); scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD); while (!SCBID_IS_NULL(scbid)) { @@ -504,7 +1377,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd) next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: Warning - Complete SCB %d invalid\n", + printk("%s: Warning - Complete SCB %d invalid\n", ahd_name(ahd), scbid); continue; } @@ -560,150 +1433,146 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb) { u_int seqintsrc; - while (1) { - seqintsrc = ahd_inb(ahd, SEQINTSRC); - if ((seqintsrc & CFG4DATA) != 0) { - uint32_t datacnt; - uint32_t sgptr; - - /* - * Clear full residual flag. - */ - sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID; - ahd_outb(ahd, SCB_SGPTR, sgptr); + seqintsrc = ahd_inb(ahd, SEQINTSRC); + if ((seqintsrc & CFG4DATA) != 0) { + uint32_t datacnt; + uint32_t sgptr; - /* - * Load datacnt and address. - */ - datacnt = ahd_inl_scbram(ahd, SCB_DATACNT); - if ((datacnt & AHD_DMA_LAST_SEG) != 0) { - sgptr |= LAST_SEG; - ahd_outb(ahd, SG_STATE, 0); - } else - ahd_outb(ahd, SG_STATE, LOADING_NEEDED); - ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR)); - ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK); - ahd_outb(ahd, SG_CACHE_PRE, sgptr); - ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN); + /* + * Clear full residual flag. + */ + sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID; + ahd_outb(ahd, SCB_SGPTR, sgptr); - /* - * Initialize Residual Fields. - */ - ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24); - ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK); + /* + * Load datacnt and address. + */ + datacnt = ahd_inl_scbram(ahd, SCB_DATACNT); + if ((datacnt & AHD_DMA_LAST_SEG) != 0) { + sgptr |= LAST_SEG; + ahd_outb(ahd, SG_STATE, 0); + } else + ahd_outb(ahd, SG_STATE, LOADING_NEEDED); + ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR)); + ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK); + ahd_outb(ahd, SG_CACHE_PRE, sgptr); + ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN); - /* - * Mark the SCB as having a FIFO in use. - */ - ahd_outb(ahd, SCB_FIFO_USE_COUNT, - ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1); + /* + * Initialize Residual Fields. + */ + ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24); + ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK); - /* - * Install a "fake" handler for this FIFO. - */ - ahd_outw(ahd, LONGJMP_ADDR, 0); + /* + * Mark the SCB as having a FIFO in use. + */ + ahd_outb(ahd, SCB_FIFO_USE_COUNT, + ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1); - /* - * Notify the hardware that we have satisfied - * this sequencer interrupt. - */ - ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA); - } else if ((seqintsrc & SAVEPTRS) != 0) { - uint32_t sgptr; - uint32_t resid; + /* + * Install a "fake" handler for this FIFO. + */ + ahd_outw(ahd, LONGJMP_ADDR, 0); - if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) { - /* - * Snapshot Save Pointers. Clear - * the snapshot and continue. - */ - ahd_outb(ahd, DFFSXFRCTL, CLRCHN); - continue; - } + /* + * Notify the hardware that we have satisfied + * this sequencer interrupt. + */ + ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA); + } else if ((seqintsrc & SAVEPTRS) != 0) { + uint32_t sgptr; + uint32_t resid; + if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) { /* - * Disable S/G fetch so the DMA engine - * is available to future users. + * Snapshot Save Pointers. All that + * is necessary to clear the snapshot + * is a CLRCHN. */ - if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) - ahd_outb(ahd, CCSGCTL, 0); - ahd_outb(ahd, SG_STATE, 0); + goto clrchn; + } - /* - * Flush the data FIFO. Strickly only - * necessary for Rev A parts. - */ - ahd_outb(ahd, DFCNTRL, - ahd_inb(ahd, DFCNTRL) | FIFOFLUSH); + /* + * Disable S/G fetch so the DMA engine + * is available to future users. + */ + if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) + ahd_outb(ahd, CCSGCTL, 0); + ahd_outb(ahd, SG_STATE, 0); - /* - * Calculate residual. - */ - sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); - resid = ahd_inl(ahd, SHCNT); - resid |= - ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24; - ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid); - if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) { - /* - * Must back up to the correct S/G element. - * Typically this just means resetting our - * low byte to the offset in the SG_CACHE, - * but if we wrapped, we have to correct - * the other bytes of the sgptr too. - */ - if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0 - && (sgptr & 0x80) == 0) - sgptr -= 0x100; - sgptr &= ~0xFF; - sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW) - & SG_ADDR_MASK; - ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr); - ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0); - } else if ((resid & AHD_SG_LEN_MASK) == 0) { - ahd_outb(ahd, SCB_RESIDUAL_SGPTR, - sgptr | SG_LIST_NULL); - } - /* - * Save Pointers. - */ - ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR)); - ahd_outl(ahd, SCB_DATACNT, resid); - ahd_outl(ahd, SCB_SGPTR, sgptr); - ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS); - ahd_outb(ahd, SEQIMODE, - ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS); - /* - * If the data is to the SCSI bus, we are - * done, otherwise wait for FIFOEMP. - */ - if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0) - break; - } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) { - uint32_t sgptr; - uint64_t data_addr; - uint32_t data_len; - u_int dfcntrl; + /* + * Flush the data FIFO. Strickly only + * necessary for Rev A parts. + */ + ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH); + /* + * Calculate residual. + */ + sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); + resid = ahd_inl(ahd, SHCNT); + resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24; + ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid); + if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) { /* - * Disable S/G fetch so the DMA engine - * is available to future users. + * Must back up to the correct S/G element. + * Typically this just means resetting our + * low byte to the offset in the SG_CACHE, + * but if we wrapped, we have to correct + * the other bytes of the sgptr too. */ - if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) { - ahd_outb(ahd, CCSGCTL, 0); - ahd_outb(ahd, SG_STATE, LOADING_NEEDED); - } + if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0 + && (sgptr & 0x80) == 0) + sgptr -= 0x100; + sgptr &= ~0xFF; + sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW) + & SG_ADDR_MASK; + ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr); + ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0); + } else if ((resid & AHD_SG_LEN_MASK) == 0) { + ahd_outb(ahd, SCB_RESIDUAL_SGPTR, + sgptr | SG_LIST_NULL); + } + /* + * Save Pointers. + */ + ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR)); + ahd_outl(ahd, SCB_DATACNT, resid); + ahd_outl(ahd, SCB_SGPTR, sgptr); + ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS); + ahd_outb(ahd, SEQIMODE, + ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS); + /* + * If the data is to the SCSI bus, we are + * done, otherwise wait for FIFOEMP. + */ + if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0) + goto clrchn; + } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) { + uint32_t sgptr; + uint64_t data_addr; + uint32_t data_len; + u_int dfcntrl; - /* - * Wait for the DMA engine to notice that the - * host transfer is enabled and that there is - * space in the S/G FIFO for new segments before - * loading more segments. - */ - if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) == 0) - continue; - if ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) == 0) - continue; + /* + * Disable S/G fetch so the DMA engine + * is available to future users. We won't + * be using the DMA engine to load segments. + */ + if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) { + ahd_outb(ahd, CCSGCTL, 0); + ahd_outb(ahd, SG_STATE, LOADING_NEEDED); + } + + /* + * Wait for the DMA engine to notice that the + * host transfer is enabled and that there is + * space in the S/G FIFO for new segments before + * loading more segments. + */ + if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) != 0 + && (ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) { /* * Determine the offset of the next S/G @@ -750,7 +1619,7 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb) * Advertise the segment to the hardware. */ dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN; - if ((ahd->features & AHD_NEW_DFCNTRL_OPTS)!=0) { + if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) { /* * Use SCSIENWRDIS so that SCSIEN * is never modified by this @@ -759,35 +1628,44 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb) dfcntrl |= SCSIENWRDIS; } ahd_outb(ahd, DFCNTRL, dfcntrl); - } else if ((ahd_inb(ahd, SG_CACHE_SHADOW) - & LAST_SEG_DONE) != 0) { - - /* - * Transfer completed to the end of SG list - * and has flushed to the host. - */ - ahd_outb(ahd, SCB_SGPTR, - ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL); - break; - } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) { - break; } - ahd_delay(200); + } else if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG_DONE) != 0) { + + /* + * Transfer completed to the end of SG list + * and has flushed to the host. + */ + ahd_outb(ahd, SCB_SGPTR, + ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL); + goto clrchn; + } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) { +clrchn: + /* + * Clear any handler for this FIFO, decrement + * the FIFO use count for the SCB, and release + * the FIFO. + */ + ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR); + ahd_outb(ahd, SCB_FIFO_USE_COUNT, + ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1); + ahd_outb(ahd, DFFSXFRCTL, CLRCHN); } - /* - * Clear any handler for this FIFO, decrement - * the FIFO use count for the SCB, and release - * the FIFO. - */ - ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR); - ahd_outb(ahd, SCB_FIFO_USE_COUNT, - ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1); - ahd_outb(ahd, DFFSXFRCTL, CLRCHN); } -void +/* + * Look for entries in the QoutFIFO that have completed. + * The valid_tag completion field indicates the validity + * of the entry - the valid value toggles each time through + * the queue. We use the sg_status field in the completion + * entry to avoid referencing the hscb if the completion + * occurred with no errors and no residual. sg_status is + * a copy of the first byte (little endian) of the sgptr + * hscb field. + */ +static void ahd_run_qoutfifo(struct ahd_softc *ahd) { + struct ahd_completion *completion; struct scb *scb; u_int scb_index; @@ -795,30 +1673,35 @@ ahd_run_qoutfifo(struct ahd_softc *ahd) panic("ahd_run_qoutfifo recursion"); ahd->flags |= AHD_RUNNING_QOUTFIFO; ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD); - while ((ahd->qoutfifo[ahd->qoutfifonext] - & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) { + for (;;) { + completion = &ahd->qoutfifo[ahd->qoutfifonext]; - scb_index = ahd_le16toh(ahd->qoutfifo[ahd->qoutfifonext] - & ~QOUTFIFO_ENTRY_VALID_LE); + if (completion->valid_tag != ahd->qoutfifonext_valid_tag) + break; + + scb_index = ahd_le16toh(completion->tag); scb = ahd_lookup_scb(ahd, scb_index); if (scb == NULL) { - printf("%s: WARNING no command for scb %d " + printk("%s: WARNING no command for scb %d " "(cmdcmplt)\nQOUTPOS = %d\n", ahd_name(ahd), scb_index, ahd->qoutfifonext); ahd_dump_card_state(ahd); - } else - ahd_complete_scb(ahd, scb); + } else if ((completion->sg_status & SG_STATUS_VALID) != 0) { + ahd_handle_scb_status(ahd, scb); + } else { + ahd_done(ahd, scb); + } ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1); if (ahd->qoutfifonext == 0) - ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID_LE; + ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID; } ahd->flags &= ~AHD_RUNNING_QOUTFIFO; } /************************* Interrupt Handling *********************************/ -void +static void ahd_handle_hwerrint(struct ahd_softc *ahd) { /* @@ -831,7 +1714,7 @@ ahd_handle_hwerrint(struct ahd_softc *ahd) error = ahd_inb(ahd, ERROR); for (i = 0; i < num_errors; i++) { if ((error & ahd_hard_errors[i].errno) != 0) - printf("%s: hwerrint, %s\n", + printk("%s: hwerrint, %s\n", ahd_name(ahd), ahd_hard_errors[i].errmesg); } @@ -847,7 +1730,52 @@ ahd_handle_hwerrint(struct ahd_softc *ahd) ahd_free(ahd); } -void +#ifdef AHD_DEBUG +static void +ahd_dump_sglist(struct scb *scb) +{ + int i; + + if (scb->sg_count > 0) { + if ((scb->ahd_softc->flags & AHD_64BIT_ADDRESSING) != 0) { + struct ahd_dma64_seg *sg_list; + + sg_list = (struct ahd_dma64_seg*)scb->sg_list; + for (i = 0; i < scb->sg_count; i++) { + uint64_t addr; + uint32_t len; + + addr = ahd_le64toh(sg_list[i].addr); + len = ahd_le32toh(sg_list[i].len); + printk("sg[%d] - Addr 0x%x%x : Length %d%s\n", + i, + (uint32_t)((addr >> 32) & 0xFFFFFFFF), + (uint32_t)(addr & 0xFFFFFFFF), + sg_list[i].len & AHD_SG_LEN_MASK, + (sg_list[i].len & AHD_DMA_LAST_SEG) + ? " Last" : ""); + } + } else { + struct ahd_dma_seg *sg_list; + + sg_list = (struct ahd_dma_seg*)scb->sg_list; + for (i = 0; i < scb->sg_count; i++) { + uint32_t len; + + len = ahd_le32toh(sg_list[i].len); + printk("sg[%d] - Addr 0x%x%x : Length %d%s\n", + i, + (len & AHD_SG_HIGH_ADDR_MASK) >> 24, + ahd_le32toh(sg_list[i].addr), + len & AHD_SG_LEN_MASK, + len & AHD_DMA_LAST_SEG ? " Last" : ""); + } + } + } +} +#endif /* AHD_DEBUG */ + +static void ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) { u_int seqintcode; @@ -874,30 +1802,10 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) ahd_update_modes(ahd); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("%s: Handle Seqint Called for code %d\n", + printk("%s: Handle Seqint Called for code %d\n", ahd_name(ahd), seqintcode); #endif switch (seqintcode) { - case BAD_SCB_STATUS: - { - struct scb *scb; - u_int scbid; - int cmds_pending; - - scbid = ahd_get_scbptr(ahd); - scb = ahd_lookup_scb(ahd, scbid); - if (scb != NULL) { - ahd_complete_scb(ahd, scb); - } else { - printf("%s: WARNING no command for scb %d " - "(bad status)\n", ahd_name(ahd), scbid); - ahd_dump_card_state(ahd); - } - cmds_pending = ahd_inw(ahd, CMDS_PENDING); - if (cmds_pending > 0) - ahd_outw(ahd, CMDS_PENDING, cmds_pending - 1); - break; - } case ENTERING_NONPACK: { struct scb *scb; @@ -928,20 +1836,24 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) */ #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) - printf("%s: Assuming LQIPHASE_NLQ with " + printk("%s: Assuming LQIPHASE_NLQ with " "P0 assertion\n", ahd_name(ahd)); #endif } #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) - printf("%s: Entering NONPACK\n", ahd_name(ahd)); + printk("%s: Entering NONPACK\n", ahd_name(ahd)); #endif break; } case INVALID_SEQINT: - printf("%s: Invalid Sequencer interrupt occurred.\n", + printk("%s: Invalid Sequencer interrupt occurred, " + "resetting channel.\n", ahd_name(ahd)); - ahd_dump_card_state(ahd); +#ifdef AHD_DEBUG + if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) + ahd_dump_card_state(ahd); +#endif ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); break; case STATUS_OVERRUN: @@ -954,8 +1866,8 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) if (scb != NULL) ahd_print_path(ahd, scb); else - printf("%s: ", ahd_name(ahd)); - printf("SCB %d Packetized Status Overrun", scbid); + printk("%s: ", ahd_name(ahd)); + printk("SCB %d Packetized Status Overrun", scbid); ahd_dump_card_state(ahd); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); break; @@ -969,7 +1881,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { ahd_dump_card_state(ahd); - printf("CFG4ISTAT: Free SCB %d referenced", scbid); + printk("CFG4ISTAT: Free SCB %d referenced", scbid); panic("For safety"); } ahd_outq(ahd, HADDR, scb->sense_busaddr); @@ -984,7 +1896,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) u_int bus_phase; bus_phase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK; - printf("%s: ILLEGAL_PHASE 0x%x\n", + printk("%s: ILLEGAL_PHASE 0x%x\n", ahd_name(ahd), bus_phase); switch (bus_phase) { @@ -996,7 +1908,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) case P_STATUS: case P_MESGIN: ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); - printf("%s: Issued Bus Reset.\n", ahd_name(ahd)); + printk("%s: Issued Bus Reset.\n", ahd_name(ahd)); break; case P_COMMAND: { @@ -1021,7 +1933,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) scbid = ahd_get_scbptr(ahd); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("Invalid phase with no valid SCB. " + printk("Invalid phase with no valid SCB. " "Resetting bus.\n"); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); @@ -1043,6 +1955,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0, /*ppr_options*/0, AHD_TRANS_ACTIVE, /*paused*/TRUE); + /* Hand-craft TUR command */ ahd_outb(ahd, SCB_CDB_STORE, 0); ahd_outb(ahd, SCB_CDB_STORE+1, 0); ahd_outb(ahd, SCB_CDB_STORE+2, 0); @@ -1062,12 +1975,16 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) ahd_outb(ahd, SAVED_LUN, 0); ahd_outb(ahd, SEQ_FLAGS, 0); ahd_assert_atn(ahd); - scb->flags &= ~(SCB_PACKETIZED); - scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT; + scb->flags &= ~SCB_PACKETIZED; + scb->flags |= SCB_ABORT|SCB_EXTERNAL_RESET; ahd_freeze_devq(ahd, scb); ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); ahd_freeze_scb(scb); + /* Notify XPT */ + ahd_send_async(ahd, devinfo.channel, devinfo.target, + CAM_LUN_WILDCARD, AC_SENT_BDR); + /* * Allow the sequencer to continue with * non-pack processing. @@ -1080,7 +1997,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { ahd_print_path(ahd, scb); - printf("Unexpected command phase from " + printk("Unexpected command phase from " "packetized target\n"); } #endif @@ -1096,7 +2013,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { - printf("%s: CFG4OVERRUN mode = %x\n", ahd_name(ahd), + printk("%s: CFG4OVERRUN mode = %x\n", ahd_name(ahd), ahd_inb(ahd, MODE_PTR)); } #endif @@ -1132,7 +2049,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) { #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { - printf("%s: PDATA_REINIT - DFCNTRL = 0x%x " + printk("%s: PDATA_REINIT - DFCNTRL = 0x%x " "SG_CACHE_SHADOW = 0x%x\n", ahd_name(ahd), ahd_inb(ahd, DFCNTRL), ahd_inb(ahd, SG_CACHE_SHADOW)); @@ -1150,7 +2067,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) * that requires host assistance for completion. * While handling the message phase(s), we will be * notified by the sequencer after each byte is - * transfered so we can track bus phase changes. + * transferred so we can track bus phase changes. * * If this is the first time we've seen a HOST_MSG_LOOP * interrupt, initialize the state of the host message @@ -1165,7 +2082,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) bus_phase = ahd_inb(ahd, SCSISIGI) & PHASE_MASK; if (bus_phase != P_MESGIN && bus_phase != P_MESGOUT) { - printf("ahd_intr: HOST_MSG_LOOP bad " + printk("ahd_intr: HOST_MSG_LOOP bad " "phase 0x%x\n", bus_phase); /* * Probably transitioned to bus free before @@ -1214,29 +2131,29 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO); - printf("%s:%c:%d: no active SCB for reconnecting " + printk("%s:%c:%d: no active SCB for reconnecting " "target - issuing BUS DEVICE RESET\n", ahd_name(ahd), 'A', ahd_inb(ahd, SELID) >> 4); - printf("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, " + printk("SAVED_SCSIID == 0x%x, SAVED_LUN == 0x%x, " "REG0 == 0x%x ACCUM = 0x%x\n", ahd_inb(ahd, SAVED_SCSIID), ahd_inb(ahd, SAVED_LUN), ahd_inw(ahd, REG0), ahd_inb(ahd, ACCUM)); - printf("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, " + printk("SEQ_FLAGS == 0x%x, SCBPTR == 0x%x, BTT == 0x%x, " "SINDEX == 0x%x\n", ahd_inb(ahd, SEQ_FLAGS), ahd_get_scbptr(ahd), ahd_find_busy_tcl(ahd, BUILD_TCL(ahd_inb(ahd, SAVED_SCSIID), ahd_inb(ahd, SAVED_LUN))), ahd_inw(ahd, SINDEX)); - printf("SELID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, " + printk("SELID == 0x%x, SCB_SCSIID == 0x%x, SCB_LUN == 0x%x, " "SCB_CONTROL == 0x%x\n", ahd_inb(ahd, SELID), ahd_inb_scbram(ahd, SCB_SCSIID), ahd_inb_scbram(ahd, SCB_LUN), ahd_inb_scbram(ahd, SCB_CONTROL)); - printf("SCSIBUS[0] == 0x%x, SCSISIGI == 0x%x\n", + printk("SCSIBUS[0] == 0x%x, SCSISIGI == 0x%x\n", ahd_inb(ahd, SCSIBUS), ahd_inb(ahd, SCSISIGI)); - printf("SXFRCTL0 == 0x%x\n", ahd_inb(ahd, SXFRCTL0)); - printf("SEQCTL0 == 0x%x\n", ahd_inb(ahd, SEQCTL0)); + printk("SXFRCTL0 == 0x%x\n", ahd_inb(ahd, SXFRCTL0)); + printk("SEQCTL0 == 0x%x\n", ahd_inb(ahd, SEQCTL0)); ahd_dump_card_state(ahd); ahd->msgout_buf[0] = MSG_BUS_DEV_RESET; ahd->msgout_len = 1; @@ -1264,7 +2181,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) u_int lastphase; lastphase = ahd_inb(ahd, LASTPHASE); - printf("%s:%c:%d: unknown scsi bus phase %x, " + printk("%s:%c:%d: unknown scsi bus phase %x, " "lastphase = 0x%x. Attempting to continue\n", ahd_name(ahd), 'A', SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)), @@ -1276,7 +2193,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) u_int lastphase; lastphase = ahd_inb(ahd, LASTPHASE); - printf("%s:%c:%d: Missed busfree. " + printk("%s:%c:%d: Missed busfree. " "Lastphase = 0x%x, Curphase = 0x%x\n", ahd_name(ahd), 'A', SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)), @@ -1306,11 +2223,11 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) lastphase = ahd_inb(ahd, LASTPHASE); if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { ahd_print_path(ahd, scb); - printf("data overrun detected %s. Tag == 0x%x.\n", + printk("data overrun detected %s. Tag == 0x%x.\n", ahd_lookup_phase_entry(lastphase)->phasemsg, SCB_GET_TAG(scb)); ahd_print_path(ahd, scb); - printf("%s seen Data Phase. Length = %ld. " + printk("%s seen Data Phase. Length = %ld. " "NumSGs = %d.\n", ahd_inb(ahd, SEQ_FLAGS) & DPHASE ? "Have" : "Haven't", @@ -1335,7 +2252,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) u_int scbid; ahd_fetch_devinfo(ahd, &devinfo); - printf("%s:%c:%d:%d: Attempt to issue message failed\n", + printk("%s:%c:%d:%d: Attempt to issue message failed\n", ahd_name(ahd), devinfo.channel, devinfo.target, devinfo.lun); scbid = ahd_get_scbptr(ahd); @@ -1368,7 +2285,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) cam_status error; ahd_print_path(ahd, scb); - printf("Task Management Func 0x%x Complete\n", + printk("Task Management Func 0x%x Complete\n", scb->hscb->task_management); lun = CAM_LUN_WILDCARD; tag = SCB_LIST_NULL; @@ -1424,7 +2341,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) * the QINFIFO if it is still there. */ ahd_print_path(ahd, scb); - printf("SCB completes before TMF\n"); + printk("SCB completes before TMF\n"); /* * Handle losing the race. Wait until any * current selection completes. We will then @@ -1449,7 +2366,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) case TRACEPOINT1: case TRACEPOINT2: case TRACEPOINT3: - printf("%s: Tracepoint %d\n", ahd_name(ahd), + printk("%s: Tracepoint %d\n", ahd_name(ahd), seqintcode - TRACEPOINT0); break; case NO_SEQINT: @@ -1458,7 +2375,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) ahd_handle_hwerrint(ahd); break; default: - printf("%s: Unexpected SEQINTCODE %d\n", ahd_name(ahd), + printk("%s: Unexpected SEQINTCODE %d\n", ahd_name(ahd), seqintcode); break; } @@ -1470,7 +2387,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) ahd_unpause(ahd); } -void +static void ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) { struct scb *scb; @@ -1491,6 +2408,20 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) lqistat1 = ahd_inb(ahd, LQISTAT1); lqostat0 = ahd_inb(ahd, LQOSTAT0); busfreetime = ahd_inb(ahd, SSTAT2) & BUSFREETIME; + + /* + * Ignore external resets after a bus reset. + */ + if (((status & SCSIRSTI) != 0) && (ahd->flags & AHD_BUS_RESET_ACTIVE)) { + ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI); + return; + } + + /* + * Clear bus reset flag + */ + ahd->flags &= ~AHD_BUS_RESET_ACTIVE; + if ((status0 & (SELDI|SELDO)) != 0) { u_int simode0; @@ -1505,14 +2436,11 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0) scb = NULL; - /* Make sure the sequencer is in a safe location. */ - ahd_clear_critical_section(ahd); - if ((status0 & IOERR) != 0) { u_int now_lvd; now_lvd = ahd_inb(ahd, SBLKCTL) & ENAB40; - printf("%s: Transceiver State Has Changed to %s mode\n", + printk("%s: Transceiver State Has Changed to %s mode\n", ahd_name(ahd), now_lvd ? "LVD" : "SE"); ahd_outb(ahd, CLRSINT0, CLRIOERR); /* @@ -1523,26 +2451,33 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) ahd_setup_iocell_workaround(ahd); ahd_unpause(ahd); } else if ((status0 & OVERRUN) != 0) { - printf("%s: SCSI offset overrun detected. Resetting bus.\n", + + printk("%s: SCSI offset overrun detected. Resetting bus.\n", ahd_name(ahd)); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); } else if ((status & SCSIRSTI) != 0) { - printf("%s: Someone reset channel A\n", ahd_name(ahd)); + + printk("%s: Someone reset channel A\n", ahd_name(ahd)); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE); } else if ((status & SCSIPERR) != 0) { + + /* Make sure the sequencer is in a safe location. */ + ahd_clear_critical_section(ahd); + ahd_handle_transmission_error(ahd); } else if (lqostat0 != 0) { - printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0); + + printk("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0); ahd_outb(ahd, CLRLQOINT0, lqostat0); - if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) { + if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) ahd_outb(ahd, CLRLQOINT1, 0); - } } else if ((status & SELTO) != 0) { - u_int scbid; - /* Stop the selection */ ahd_outb(ahd, SCSISEQ0, 0); + /* Make sure the sequencer is in a safe location. */ + ahd_clear_critical_section(ahd); + /* No more pending messages */ ahd_clear_msg_state(ahd); @@ -1552,7 +2487,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) /* * Although the driver does not care about the * 'Selection in Progress' status bit, the busy - * LED does. SELINGO is only cleared by a sucessfull + * LED does. SELINGO is only cleared by a successful * selection, so we must manually clear it to insure * the LED turns off just incase no future successful * selections occur (e.g. no devices on the bus). @@ -1562,7 +2497,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) scbid = ahd_inw(ahd, WAITING_TID_HEAD); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: ahd_intr - referenced scb not " + printk("%s: ahd_intr - referenced scb not " "valid during SELTO scb(0x%x)\n", ahd_name(ahd), scbid); ahd_dump_card_state(ahd); @@ -1571,35 +2506,42 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_SELTO) != 0) { ahd_print_path(ahd, scb); - printf("Saw Selection Timeout for SCB 0x%x\n", + printk("Saw Selection Timeout for SCB 0x%x\n", scbid); } #endif - /* - * Force a renegotiation with this target just in - * case the cable was pulled and will later be - * re-attached. The target may forget its negotiation - * settings with us should it attempt to reselect - * during the interruption. The target will not issue - * a unit attention in this case, so we must always - * renegotiate. - */ ahd_scb_devinfo(ahd, &devinfo, scb); - ahd_force_renegotiation(ahd, &devinfo); ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT); ahd_freeze_devq(ahd, scb); + + /* + * Cancel any pending transactions on the device + * now that it seems to be missing. This will + * also revert us to async/narrow transfers until + * we can renegotiate with the device. + */ + ahd_handle_devreset(ahd, &devinfo, + CAM_LUN_WILDCARD, + CAM_SEL_TIMEOUT, + "Selection Timeout", + /*verbose_level*/1); } ahd_outb(ahd, CLRINT, CLRSCSIINT); ahd_iocell_first_selection(ahd); ahd_unpause(ahd); } else if ((status0 & (SELDI|SELDO)) != 0) { + ahd_iocell_first_selection(ahd); ahd_unpause(ahd); } else if (status3 != 0) { - printf("%s: SCSI Cell parity error SSTAT3 == 0x%x\n", + printk("%s: SCSI Cell parity error SSTAT3 == 0x%x\n", ahd_name(ahd), status3); ahd_outb(ahd, CLRSINT3, status3); } else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) { + + /* Make sure the sequencer is in a safe location. */ + ahd_clear_critical_section(ahd); + ahd_handle_lqiphase_error(ahd, lqistat1); } else if ((lqistat1 & LQICRCI_NLQ) != 0) { /* @@ -1609,7 +2551,8 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) * so just clear the error. */ ahd_outb(ahd, CLRLQIINT1, CLRLQICRCI_NLQ); - } else if ((status & BUSFREE) != 0) { + } else if ((status & BUSFREE) != 0 + || (lqistat1 & LQOBUSFREE) != 0) { u_int lqostat1; int restart; int clear_fifo; @@ -1624,6 +2567,9 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) */ ahd_outb(ahd, SCSISEQ0, 0); + /* Make sure the sequencer is in a safe location. */ + ahd_clear_critical_section(ahd); + /* * Determine what we were up to at the time of * the busfree. @@ -1635,16 +2581,13 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) case BUSFREE_DFF0: case BUSFREE_DFF1: { - u_int scbid; - struct scb *scb; - mode = busfreetime == BUSFREE_DFF0 ? AHD_MODE_DFF0 : AHD_MODE_DFF1; ahd_set_modes(ahd, mode, mode); scbid = ahd_get_scbptr(ahd); scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: Invalid SCB %d in DFF%d " + printk("%s: Invalid SCB %d in DFF%d " "during unexpected busfree\n", ahd_name(ahd), scbid, mode); packetized = 0; @@ -1661,14 +2604,23 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) clear_fifo = 0; packetized = (lqostat1 & LQOBUSFREE) != 0; if (!packetized - && ahd_inb(ahd, LASTPHASE) == P_BUSFREE) + && ahd_inb(ahd, LASTPHASE) == P_BUSFREE + && (ahd_inb(ahd, SSTAT0) & SELDI) == 0 + && ((ahd_inb(ahd, SSTAT0) & SELDO) == 0 + || (ahd_inb(ahd, SCSISEQ0) & ENSELO) == 0)) + /* + * Assume packetized if we are not + * on the bus in a non-packetized + * capacity and any pending selection + * was a packetized selection. + */ packetized = 1; break; } #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("Saw Busfree. Busfreetime = 0x%x.\n", + printk("Saw Busfree. Busfreetime = 0x%x.\n", busfreetime); #endif /* @@ -1709,7 +2661,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) ahd_unpause(ahd); } } else { - printf("%s: Missing case in ahd_handle_scsiint. status = %x\n", + printk("%s: Missing case in ahd_handle_scsiint. status = %x\n", ahd_name(ahd), status); ahd_dump_card_state(ahd); ahd_clear_intstat(ahd); @@ -1745,7 +2697,7 @@ ahd_handle_transmission_error(struct ahd_softc *ahd) || (lqistate == 0x29)) { #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) { - printf("%s: NLQCRC found via LQISTATE\n", + printk("%s: NLQCRC found via LQISTATE\n", ahd_name(ahd)); } #endif @@ -1777,18 +2729,18 @@ ahd_handle_transmission_error(struct ahd_softc *ahd) cur_col = 0; if (silent == FALSE) { - printf("%s: Transmission error detected\n", ahd_name(ahd)); + printk("%s: Transmission error detected\n", ahd_name(ahd)); ahd_lqistat1_print(lqistat1, &cur_col, 50); ahd_lastphase_print(lastphase, &cur_col, 50); ahd_scsisigi_print(curphase, &cur_col, 50); ahd_perrdiag_print(perrdiag, &cur_col, 50); - printf("\n"); + printk("\n"); ahd_dump_card_state(ahd); } if ((lqistat1 & (LQIOVERI_LQ|LQIOVERI_NLQ)) != 0) { if (silent == FALSE) { - printf("%s: Gross protocol error during incoming " + printk("%s: Gross protocol error during incoming " "packet. lqistat1 == 0x%x. Resetting bus.\n", ahd_name(ahd), lqistat1); } @@ -1817,7 +2769,7 @@ ahd_handle_transmission_error(struct ahd_softc *ahd) * (SPI4R09 10.7.3.3.3) */ ahd_outb(ahd, LQCTL2, LQIRETRY); - printf("LQIRetry for LQICRCI_LQ to release ACK\n"); + printk("LQIRetry for LQICRCI_LQ to release ACK\n"); } else if ((lqistat1 & LQICRCI_NLQ) != 0) { /* * We detected a CRC error in a NON-LQ packet. @@ -1865,22 +2817,22 @@ ahd_handle_transmission_error(struct ahd_softc *ahd) * Busfree detection is enabled. */ if (silent == FALSE) - printf("LQICRC_NLQ\n"); + printk("LQICRC_NLQ\n"); if (scb == NULL) { - printf("%s: No SCB valid for LQICRC_NLQ. " + printk("%s: No SCB valid for LQICRC_NLQ. " "Resetting bus\n", ahd_name(ahd)); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); return; } } else if ((lqistat1 & LQIBADLQI) != 0) { - printf("Need to handle BADLQI!\n"); + printk("Need to handle BADLQI!\n"); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); return; } else if ((perrdiag & (PARITYERR|PREVPHASE)) == PARITYERR) { if ((curphase & ~P_DATAIN_DT) != 0) { /* Ack the byte. So we can continue. */ if (silent == FALSE) - printf("Acking %s to clear perror\n", + printk("Acking %s to clear perror\n", ahd_lookup_phase_entry(curphase)->phasemsg); ahd_inb(ahd, SCSIDAT); } @@ -1925,10 +2877,10 @@ ahd_handle_lqiphase_error(struct ahd_softc *ahd, u_int lqistat1) if ((ahd_inb(ahd, SCSISIGO) & ATNO) != 0 && (ahd_inb(ahd, MDFFSTAT) & DLZERO) != 0) { if ((lqistat1 & LQIPHASE_LQ) != 0) { - printf("LQIRETRY for LQIPHASE_LQ\n"); + printk("LQIRETRY for LQIPHASE_LQ\n"); ahd_outb(ahd, LQCTL2, LQIRETRY); } else if ((lqistat1 & LQIPHASE_NLQ) != 0) { - printf("LQIRETRY for LQIPHASE_NLQ\n"); + printk("LQIRETRY for LQIPHASE_NLQ\n"); ahd_outb(ahd, LQCTL2, LQIRETRY); } else panic("ahd_handle_lqiphase_error: No phase errors\n"); @@ -1936,7 +2888,7 @@ ahd_handle_lqiphase_error(struct ahd_softc *ahd, u_int lqistat1) ahd_outb(ahd, CLRINT, CLRSCSIINT); ahd_unpause(ahd); } else { - printf("Reseting Channel for LQI Phase error\n"); + printk("Resetting Channel for LQI Phase error\n"); ahd_dump_card_state(ahd); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); } @@ -1962,10 +2914,6 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime) u_int waiting_t; u_int next; - if ((busfreetime & BUSFREE_LQO) == 0) - printf("%s: Warning, BUSFREE time is 0x%x. " - "Expected BUSFREE_LQO.\n", - ahd_name(ahd), busfreetime); /* * The LQO manager detected an unexpected busfree * either: @@ -2028,7 +2976,7 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime) if (scb->crc_retry_count < AHD_MAX_LQ_CRC_ERRORS) { if (SCB_IS_SILENT(scb) == FALSE) { ahd_print_path(ahd, scb); - printf("Probable outgoing LQ CRC error. " + printk("Probable outgoing LQ CRC error. " "Retrying command\n"); } scb->crc_retry_count++; @@ -2050,7 +2998,7 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime) ahd_outb(ahd, CLRSINT1, CLRSCSIPERR|CLRBUSFREE); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MASKED_ERRORS) != 0) - printf("%s: Parity on last REQ detected " + printk("%s: Parity on last REQ detected " "during busfree phase.\n", ahd_name(ahd)); #endif @@ -2064,7 +3012,7 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime) scbid = ahd_get_scbptr(ahd); scb = ahd_lookup_scb(ahd, scbid); ahd_print_path(ahd, scb); - printf("Unexpected PKT busfree condition\n"); + printk("Unexpected PKT busfree condition\n"); ahd_dump_card_state(ahd); ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb), 'A', SCB_GET_LUN(scb), SCB_GET_TAG(scb), @@ -2073,7 +3021,7 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime) /* Return restarting the sequencer. */ return (1); } - printf("%s: Unexpected PKT busfree condition\n", ahd_name(ahd)); + printk("%s: Unexpected PKT busfree condition\n", ahd_name(ahd)); ahd_dump_card_state(ahd); /* Restart the sequencer. */ return (1); @@ -2128,21 +3076,21 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) if (scb == NULL) { ahd_print_devinfo(ahd, &devinfo); - printf("Abort for unidentified " + printk("Abort for unidentified " "connection completed.\n"); /* restart the sequencer. */ return (1); } sent_msg = ahd->msgout_buf[ahd->msgout_index - 1]; ahd_print_path(ahd, scb); - printf("SCB %d - Abort%s Completed.\n", + printk("SCB %d - Abort%s Completed.\n", SCB_GET_TAG(scb), sent_msg == MSG_ABORT_TAG ? "" : " Tag"); if (sent_msg == MSG_ABORT_TAG) tag = SCB_GET_TAG(scb); - if ((scb->flags & SCB_CMDPHASE_ABORT) != 0) { + if ((scb->flags & SCB_EXTERNAL_RESET) != 0) { /* * This abort is in response to an * unexpected switch to command phase @@ -2161,7 +3109,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) found = ahd_abort_scbs(ahd, target, 'A', saved_lun, tag, ROLE_INITIATOR, CAM_REQ_ABORTED); - printf("found == 0x%x\n", found); + printk("found == 0x%x\n", found); printerror = 0; } else if (ahd_sent_msg(ahd, AHDMSG_1B, MSG_BUS_DEV_RESET, TRUE)) { @@ -2188,21 +3136,53 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) struct ahd_tmode_tstate *tstate; /* - * PPR Rejected. Try non-ppr negotiation - * and retry command. + * PPR Rejected. + * + * If the previous negotiation was packetized, + * this could be because the device has been + * reset without our knowledge. Force our + * current negotiation to async and retry the + * negotiation. Otherwise retry the command + * with non-ppr negotiation. */ #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("PPR negotiation rejected busfree.\n"); + printk("PPR negotiation rejected busfree.\n"); #endif tinfo = ahd_fetch_transinfo(ahd, devinfo.channel, devinfo.our_scsiid, devinfo.target, &tstate); - tinfo->curr.transport_version = 2; - tinfo->goal.transport_version = 2; - tinfo->goal.ppr_options = 0; - ahd_qinfifo_requeue_tail(ahd, scb); - printerror = 0; + if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ)!=0) { + ahd_set_width(ahd, &devinfo, + MSG_EXT_WDTR_BUS_8_BIT, + AHD_TRANS_CUR, + /*paused*/TRUE); + ahd_set_syncrate(ahd, &devinfo, + /*period*/0, /*offset*/0, + /*ppr_options*/0, + AHD_TRANS_CUR, + /*paused*/TRUE); + /* + * The expect PPR busfree handler below + * will effect the retry and necessary + * abort. + */ + } else { + tinfo->curr.transport_version = 2; + tinfo->goal.transport_version = 2; + tinfo->goal.ppr_options = 0; + if (scb != NULL) { + /* + * Remove any SCBs in the waiting + * for selection queue that may + * also be for this target so that + * command ordering is preserved. + */ + ahd_freeze_devq(ahd, scb); + ahd_qinfifo_requeue_tail(ahd, scb); + } + printerror = 0; + } } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, FALSE) && ppr_busfree == 0) { /* @@ -2211,13 +3191,22 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) */ #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("WDTR negotiation rejected busfree.\n"); + printk("WDTR negotiation rejected busfree.\n"); #endif ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, AHD_TRANS_CUR|AHD_TRANS_GOAL, /*paused*/TRUE); - ahd_qinfifo_requeue_tail(ahd, scb); + if (scb != NULL) { + /* + * Remove any SCBs in the waiting for + * selection queue that may also be for + * this target so that command ordering + * is preserved. + */ + ahd_freeze_devq(ahd, scb); + ahd_qinfifo_requeue_tail(ahd, scb); + } printerror = 0; } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_SDTR, FALSE) && ppr_busfree == 0) { @@ -2227,14 +3216,23 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) */ #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("SDTR negotiation rejected busfree.\n"); + printk("SDTR negotiation rejected busfree.\n"); #endif ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0, /*ppr_options*/0, AHD_TRANS_CUR|AHD_TRANS_GOAL, /*paused*/TRUE); - ahd_qinfifo_requeue_tail(ahd, scb); + if (scb != NULL) { + /* + * Remove any SCBs in the waiting for + * selection queue that may also be for + * this target so that command ordering + * is preserved. + */ + ahd_freeze_devq(ahd, scb); + ahd_qinfifo_requeue_tail(ahd, scb); + } printerror = 0; } else if ((ahd->msg_flags & MSG_FLAG_EXPECT_IDE_BUSFREE) != 0 && ahd_sent_msg(ahd, AHDMSG_1B, @@ -2242,7 +3240,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("Expected IDE Busfree\n"); + printk("Expected IDE Busfree\n"); #endif printerror = 0; } else if ((ahd->msg_flags & MSG_FLAG_EXPECT_QASREJ_BUSFREE) @@ -2251,7 +3249,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("Expected QAS Reject Busfree\n"); + printk("Expected QAS Reject Busfree\n"); #endif printerror = 0; } @@ -2262,7 +3260,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) * the message phases. We check it last in case we * had to send some other message that caused a busfree. */ - if (printerror != 0 + if (scb != NULL && printerror != 0 && (lastphase == P_MESGIN || lastphase == P_MESGOUT) && ((ahd->msg_flags & MSG_FLAG_EXPECT_PPR_BUSFREE) != 0)) { @@ -2277,7 +3275,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) } else { #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("PPR Negotiation Busfree.\n"); + printk("PPR Negotiation Busfree.\n"); #endif ahd_done(ahd, scb); } @@ -2304,17 +3302,16 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) * We had not fully identified this connection, * so we cannot abort anything. */ - printf("%s: ", ahd_name(ahd)); + printk("%s: ", ahd_name(ahd)); } - if (lastphase != P_BUSFREE) - ahd_force_renegotiation(ahd, &devinfo); - printf("Unexpected busfree %s, %d SCBs aborted, " + printk("Unexpected busfree %s, %d SCBs aborted, " "PRGMCNT == 0x%x\n", ahd_lookup_phase_entry(lastphase)->phasemsg, aborted, - ahd_inb(ahd, PRGMCNT) - | (ahd_inb(ahd, PRGMCNT+1) << 8)); + ahd_inw(ahd, PRGMCNT)); ahd_dump_card_state(ahd); + if (lastphase != P_BUSFREE) + ahd_force_renegotiation(ahd, &devinfo); } /* Always restart the sequencer. */ return (1); @@ -2345,7 +3342,7 @@ ahd_handle_proto_violation(struct ahd_softc *ahd) * to match. */ ahd_print_devinfo(ahd, &devinfo); - printf("Target did not send an IDENTIFY message. " + printk("Target did not send an IDENTIFY message. " "LASTPHASE = 0x%x.\n", lastphase); scb = NULL; } else if (scb == NULL) { @@ -2354,13 +3351,13 @@ ahd_handle_proto_violation(struct ahd_softc *ahd) * transaction. Print an error and reset the bus. */ ahd_print_devinfo(ahd, &devinfo); - printf("No SCB found during protocol violation\n"); + printk("No SCB found during protocol violation\n"); goto proto_violation_reset; } else { ahd_set_transaction_status(scb, CAM_SEQUENCE_FAIL); if ((seq_flags & NO_CDB_SENT) != 0) { ahd_print_path(ahd, scb); - printf("No or incomplete CDB sent to device.\n"); + printk("No or incomplete CDB sent to device.\n"); } else if ((ahd_inb_scbram(ahd, SCB_CONTROL) & STATUS_RCVD) == 0) { /* @@ -2371,10 +3368,10 @@ ahd_handle_proto_violation(struct ahd_softc *ahd) * message. */ ahd_print_path(ahd, scb); - printf("Completed command without status.\n"); + printk("Completed command without status.\n"); } else { ahd_print_path(ahd, scb); - printf("Unknown protocol violation.\n"); + printk("Unknown protocol violation.\n"); ahd_dump_card_state(ahd); } } @@ -2388,7 +3385,7 @@ proto_violation_reset: * it away with a bus reset. */ found = ahd_reset_channel(ahd, 'A', TRUE); - printf("%s: Issued Channel %c Bus Reset. " + printk("%s: Issued Channel %c Bus Reset. " "%d SCBs aborted\n", ahd_name(ahd), 'A', found); } else { /* @@ -2410,7 +3407,7 @@ proto_violation_reset: ahd_print_path(ahd, scb); scb->flags |= SCB_ABORT; } - printf("Protocol violation %s. Attempting to abort.\n", + printk("Protocol violation %s. Attempting to abort.\n", ahd_lookup_phase_entry(curphase)->phasemsg); } } @@ -2428,7 +3425,7 @@ ahd_force_renegotiation(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { ahd_print_devinfo(ahd, devinfo); - printf("Forcing renegotiation\n"); + printk("Forcing renegotiation\n"); } #endif targ_info = ahd_fetch_transinfo(ahd, @@ -2441,7 +3438,7 @@ ahd_force_renegotiation(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) } #define AHD_MAX_STEPS 2000 -void +static void ahd_clear_critical_section(struct ahd_softc *ahd) { ahd_mode_state saved_modes; @@ -2476,8 +3473,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd) u_int i; ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - seqaddr = ahd_inb(ahd, CURADDR) - | (ahd_inb(ahd, CURADDR+1) << 8); + seqaddr = ahd_inw(ahd, CURADDR); cs = ahd->critical_sections; for (i = 0; i < ahd->num_critical_sections; i++, cs++) { @@ -2490,7 +3486,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd) break; if (steps > AHD_MAX_STEPS) { - printf("%s: Infinite loop in critical section\n" + printk("%s: Infinite loop in critical section\n" "%s: First Instruction 0x%x now 0x%x\n", ahd_name(ahd), ahd_name(ahd), first_instr, seqaddr); @@ -2501,7 +3497,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd) steps++; #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("%s: Single stepping at 0x%x\n", ahd_name(ahd), + printk("%s: Single stepping at 0x%x\n", ahd_name(ahd), seqaddr); #endif if (stepping == FALSE) { @@ -2552,7 +3548,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd) ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) & ~STEP); ahd_outb(ahd, SIMODE1, simode1); /* - * SCSIINT seems to glitch occassionally when + * SCSIINT seems to glitch occasionally when * the interrupt masks are restored. Clear SCSIINT * one more time so that only persistent errors * are seen as a real interrupt. @@ -2565,7 +3561,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd) /* * Clear any pending interrupt status. */ -void +static void ahd_clear_intstat(struct ahd_softc *ahd) { AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK), @@ -2596,6 +3592,8 @@ ahd_clear_intstat(struct ahd_softc *ahd) #ifdef AHD_DEBUG uint32_t ahd_debug = AHD_DEBUG_OPTS; #endif + +#if 0 void ahd_print_scb(struct scb *scb) { @@ -2603,16 +3601,16 @@ ahd_print_scb(struct scb *scb) int i; hscb = scb->hscb; - printf("scb:%p control:0x%x scsiid:0x%x lun:%d cdb_len:%d\n", + printk("scb:%p control:0x%x scsiid:0x%x lun:%d cdb_len:%d\n", (void *)scb, hscb->control, hscb->scsiid, hscb->lun, hscb->cdb_len); - printf("Shared Data: "); + printk("Shared Data: "); for (i = 0; i < sizeof(hscb->shared_data.idata.cdb); i++) - printf("%#02x", hscb->shared_data.idata.cdb[i]); - printf(" dataptr:%#x%x datacnt:%#x sgptr:%#x tag:%#x\n", + printk("%#02x", hscb->shared_data.idata.cdb[i]); + printk(" dataptr:%#x%x datacnt:%#x sgptr:%#x tag:%#x\n", (uint32_t)((ahd_le64toh(hscb->dataptr) >> 32) & 0xFFFFFFFF), (uint32_t)(ahd_le64toh(hscb->dataptr) & 0xFFFFFFFF), ahd_le32toh(hscb->datacnt), @@ -2620,49 +3618,7 @@ ahd_print_scb(struct scb *scb) SCB_GET_TAG(scb)); ahd_dump_sglist(scb); } - -void -ahd_dump_sglist(struct scb *scb) -{ - int i; - - if (scb->sg_count > 0) { - if ((scb->ahd_softc->flags & AHD_64BIT_ADDRESSING) != 0) { - struct ahd_dma64_seg *sg_list; - - sg_list = (struct ahd_dma64_seg*)scb->sg_list; - for (i = 0; i < scb->sg_count; i++) { - uint64_t addr; - uint32_t len; - - addr = ahd_le64toh(sg_list[i].addr); - len = ahd_le32toh(sg_list[i].len); - printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", - i, - (uint32_t)((addr >> 32) & 0xFFFFFFFF), - (uint32_t)(addr & 0xFFFFFFFF), - sg_list[i].len & AHD_SG_LEN_MASK, - (sg_list[i].len & AHD_DMA_LAST_SEG) - ? " Last" : ""); - } - } else { - struct ahd_dma_seg *sg_list; - - sg_list = (struct ahd_dma_seg*)scb->sg_list; - for (i = 0; i < scb->sg_count; i++) { - uint32_t len; - - len = ahd_le32toh(sg_list[i].len); - printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", - i, - (len & AHD_SG_HIGH_ADDR_MASK) >> 24, - ahd_le32toh(sg_list[i].addr), - len & AHD_SG_LEN_MASK, - len & AHD_DMA_LAST_SEG ? " Last" : ""); - } - } - } -} +#endif /* 0 */ /************************* Transfer Negotiation *******************************/ /* @@ -2681,7 +3637,7 @@ ahd_alloc_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel) && ahd->enabled_targets[scsi_id] != master_tstate) panic("%s: ahd_alloc_tstate - Target already allocated", ahd_name(ahd)); - tstate = malloc(sizeof(*tstate), M_DEVBUF, M_NOWAIT); + tstate = kmalloc(sizeof(*tstate), GFP_ATOMIC); if (tstate == NULL) return (NULL); @@ -2726,7 +3682,7 @@ ahd_free_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel, int force) tstate = ahd->enabled_targets[scsi_id]; if (tstate != NULL) - free(tstate, M_DEVBUF); + kfree(tstate); ahd->enabled_targets[scsi_id] = NULL; } #endif @@ -2737,7 +3693,7 @@ ahd_free_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel, int force) * by the capabilities of the bus connectivity of and sync settings for * the target. */ -void +static void ahd_devlimited_syncrate(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo, u_int *period, u_int *ppr_options, role_t role) @@ -2769,14 +3725,14 @@ ahd_devlimited_syncrate(struct ahd_softc *ahd, transinfo = &tinfo->goal; *ppr_options &= (transinfo->ppr_options|MSG_EXT_PPR_PCOMP_EN); if (transinfo->width == MSG_EXT_WDTR_BUS_8_BIT) { - maxsync = MAX(maxsync, AHD_SYNCRATE_ULTRA2); + maxsync = max(maxsync, (u_int)AHD_SYNCRATE_ULTRA2); *ppr_options &= ~MSG_EXT_PPR_DT_REQ; } if (transinfo->period == 0) { *period = 0; *ppr_options = 0; } else { - *period = MAX(*period, transinfo->period); + *period = max(*period, (u_int)transinfo->period); ahd_find_syncrate(ahd, period, ppr_options, maxsync); } } @@ -2825,7 +3781,7 @@ ahd_find_syncrate(struct ahd_softc *ahd, u_int *period, * Truncate the given synchronous offset to a value the * current adapter type and syncrate are capable of. */ -void +static void ahd_validate_offset(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo, u_int period, u_int *offset, int wide, @@ -2843,12 +3799,12 @@ ahd_validate_offset(struct ahd_softc *ahd, maxoffset = MAX_OFFSET_PACED; } else maxoffset = MAX_OFFSET_NON_PACED; - *offset = MIN(*offset, maxoffset); + *offset = min(*offset, maxoffset); if (tinfo != NULL) { if (role == ROLE_TARGET) - *offset = MIN(*offset, tinfo->user.offset); + *offset = min(*offset, (u_int)tinfo->user.offset); else - *offset = MIN(*offset, tinfo->goal.offset); + *offset = min(*offset, (u_int)tinfo->goal.offset); } } @@ -2856,7 +3812,7 @@ ahd_validate_offset(struct ahd_softc *ahd, * Truncate the given transfer width parameter to a value the * current adapter type is capable of. */ -void +static void ahd_validate_width(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo, u_int *bus_width, role_t role) { @@ -2874,15 +3830,15 @@ ahd_validate_width(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo, } if (tinfo != NULL) { if (role == ROLE_TARGET) - *bus_width = MIN(tinfo->user.width, *bus_width); + *bus_width = min((u_int)tinfo->user.width, *bus_width); else - *bus_width = MIN(tinfo->goal.width, *bus_width); + *bus_width = min((u_int)tinfo->goal.width, *bus_width); } } /* * Update the bitmask of targets for which the controller should - * negotiate with at the next convenient oportunity. This currently + * negotiate with at the next convenient opportunity. This currently * means the next time we send the initial identify messages for * a new transaction. */ @@ -2981,42 +3937,42 @@ ahd_set_syncrate(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, tinfo->curr.ppr_options = ppr_options; ahd_send_async(ahd, devinfo->channel, devinfo->target, - CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL); + CAM_LUN_WILDCARD, AC_TRANSFER_NEG); if (bootverbose) { if (offset != 0) { int options; - printf("%s: target %d synchronous with " + printk("%s: target %d synchronous with " "period = 0x%x, offset = 0x%x", ahd_name(ahd), devinfo->target, period, offset); options = 0; if ((ppr_options & MSG_EXT_PPR_RD_STRM) != 0) { - printf("(RDSTRM"); + printk("(RDSTRM"); options++; } if ((ppr_options & MSG_EXT_PPR_DT_REQ) != 0) { - printf("%s", options ? "|DT" : "(DT"); + printk("%s", options ? "|DT" : "(DT"); options++; } if ((ppr_options & MSG_EXT_PPR_IU_REQ) != 0) { - printf("%s", options ? "|IU" : "(IU"); + printk("%s", options ? "|IU" : "(IU"); options++; } if ((ppr_options & MSG_EXT_PPR_RTI) != 0) { - printf("%s", options ? "|RTI" : "(RTI"); + printk("%s", options ? "|RTI" : "(RTI"); options++; } if ((ppr_options & MSG_EXT_PPR_QAS_REQ) != 0) { - printf("%s", options ? "|QAS" : "(QAS"); + printk("%s", options ? "|QAS" : "(QAS"); options++; } if (options != 0) - printf(")\n"); + printk(")\n"); else - printf("\n"); + printk("\n"); } else { - printf("%s: target %d using " + printk("%s: target %d using " "asynchronous transfers%s\n", ahd_name(ahd), devinfo->target, (ppr_options & MSG_EXT_PPR_QAS_REQ) != 0 @@ -3044,7 +4000,7 @@ ahd_set_syncrate(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { ahd_print_devinfo(ahd, devinfo); - printf("Expecting IU Change busfree\n"); + printk("Expecting IU Change busfree\n"); } #endif ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE @@ -3053,7 +4009,7 @@ ahd_set_syncrate(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, if ((old_ppr & MSG_EXT_PPR_IU_REQ) != 0) { #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("PPR with IU_REQ outstanding\n"); + printk("PPR with IU_REQ outstanding\n"); #endif ahd->msg_flags |= MSG_FLAG_EXPECT_PPR_BUSFREE; } @@ -3103,9 +4059,9 @@ ahd_set_width(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, tinfo->curr.width = width; ahd_send_async(ahd, devinfo->channel, devinfo->target, - CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL); + CAM_LUN_WILDCARD, AC_TRANSFER_NEG); if (bootverbose) { - printf("%s: target %d using %dbit transfers\n", + printk("%s: target %d using %dbit transfers\n", ahd_name(ahd), devinfo->target, 8 * (0x01 << width)); } @@ -3129,13 +4085,15 @@ ahd_set_width(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, /* * Update the current state of tagged queuing for a given target. */ -void -ahd_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, - ahd_queue_alg alg) +static void +ahd_set_tags(struct ahd_softc *ahd, struct scsi_cmnd *cmd, + struct ahd_devinfo *devinfo, ahd_queue_alg alg) { - ahd_platform_set_tags(ahd, devinfo, alg); + struct scsi_device *sdev = cmd->device; + + ahd_platform_set_tags(ahd, sdev, devinfo, alg); ahd_send_async(ahd, devinfo->channel, devinfo->target, - devinfo->lun, AC_TRANSFER_NEG, &alg); + devinfo->lun, AC_TRANSFER_NEG); } static void @@ -3182,7 +4140,7 @@ ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, /* * Harpoon2A assumed that there would be a - * fallback rate between 160MHz and 80Mhz, + * fallback rate between 160MHz and 80MHz, * so 7 is used as the period factor rather * than 8 for 160MHz. */ @@ -3198,14 +4156,25 @@ ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK; if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0 - && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0) { + && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0 + && (ppr_opts & MSG_EXT_PPR_IU_REQ) == 0) { /* * Slow down our CRC interval to be - * compatible with devices that can't - * handle a CRC at full speed. + * compatible with non-packetized + * U160 devices that can't handle a + * CRC at full speed. */ con_opts |= ENSLOWCRC; } + + if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) { + /* + * On H2A4, revert to a slower slewrate + * on non-paced transfers. + */ + iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= + ~AHD_SLEWRATE_MASK; + } } ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW); @@ -3221,8 +4190,17 @@ ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, con_opts |= WIDEXFER; /* + * Slow down our CRC interval to be + * compatible with packetized U320 devices + * that can't handle a CRC at full speed + */ + if (ahd->features & AHD_AIC79XXB_SLOWCRC) { + con_opts |= ENSLOWCRC; + } + + /* * During packetized transfers, the target will - * give us the oportunity to send command packets + * give us the opportunity to send command packets * without us asserting attention. */ if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ) == 0) @@ -3243,7 +4221,6 @@ ahd_update_pending_scbs(struct ahd_softc *ahd) { struct scb *pending_scb; int pending_scb_count; - u_int scb_tag; int paused; u_int saved_scbptr; ahd_mode_state saved_modes; @@ -3261,7 +4238,6 @@ ahd_update_pending_scbs(struct ahd_softc *ahd) pending_scb_count = 0; LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) { struct ahd_devinfo devinfo; - struct hardware_scb *pending_hscb; struct ahd_initiator_tinfo *tinfo; struct ahd_tmode_tstate *tstate; @@ -3269,11 +4245,10 @@ ahd_update_pending_scbs(struct ahd_softc *ahd) tinfo = ahd_fetch_transinfo(ahd, devinfo.channel, devinfo.our_scsiid, devinfo.target, &tstate); - pending_hscb = pending_scb->hscb; if ((tstate->auto_negotiate & devinfo.target_mask) == 0 && (pending_scb->flags & SCB_AUTO_NEGOTIATE) != 0) { pending_scb->flags &= ~SCB_AUTO_NEGOTIATE; - pending_hscb->control &= ~MK_MESSAGE; + pending_scb->hscb->control &= ~MK_MESSAGE; } ahd_sync_scb(ahd, pending_scb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); @@ -3294,25 +4269,26 @@ ahd_update_pending_scbs(struct ahd_softc *ahd) * Force the sequencer to reinitialize the selection for * the command at the head of the execution queue if it * has already been setup. The negotiation changes may - * effect whether we select-out with ATN. + * effect whether we select-out with ATN. It is only + * safe to clear ENSELO when the bus is not free and no + * selection is in progres or completed. */ saved_modes = ahd_save_modes(ahd); ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO); + if ((ahd_inb(ahd, SCSISIGI) & BSYI) != 0 + && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0) + ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO); saved_scbptr = ahd_get_scbptr(ahd); /* Ensure that the hscbs down on the card match the new information */ - for (scb_tag = 0; scb_tag < ahd->scb_data.maxhscbs; scb_tag++) { - struct hardware_scb *pending_hscb; + LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) { + u_int scb_tag; u_int control; - pending_scb = ahd_lookup_scb(ahd, scb_tag); - if (pending_scb == NULL) - continue; + scb_tag = SCB_GET_TAG(pending_scb); ahd_set_scbptr(ahd, scb_tag); - pending_hscb = pending_scb->hscb; control = ahd_inb_scbram(ahd, SCB_CONTROL); control &= ~MK_MESSAGE; - control |= pending_hscb->control & MK_MESSAGE; + control |= pending_scb->hscb->control & MK_MESSAGE; ahd_outb(ahd, SCB_CONTROL, control); } ahd_set_scbptr(ahd, saved_scbptr); @@ -3361,15 +4337,15 @@ ahd_fetch_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) void ahd_print_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) { - printf("%s:%c:%d:%d: ", ahd_name(ahd), 'A', + printk("%s:%c:%d:%d: ", ahd_name(ahd), 'A', devinfo->target, devinfo->lun); } -struct ahd_phase_table_entry* +static const struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase) { - struct ahd_phase_table_entry *entry; - struct ahd_phase_table_entry *last_entry; + const struct ahd_phase_table_entry *entry; + const struct ahd_phase_table_entry *last_entry; /* * num_phases doesn't include the default entry which @@ -3443,11 +4419,11 @@ ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT; #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("Setting up for Parity Error delivery\n"); + printk("Setting up for Parity Error delivery\n"); #endif return; } else if (scb == NULL) { - printf("%s: WARNING. No pending message for " + printk("%s: WARNING. No pending message for " "I_T msgin. Issuing NO-OP\n", ahd_name(ahd)); ahd->msgout_buf[ahd->msgout_index++] = MSG_NOOP; ahd->msgout_len++; @@ -3478,7 +4454,7 @@ ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ahd->msgout_buf[ahd->msgout_index++] = MSG_BUS_DEV_RESET; ahd->msgout_len++; ahd_print_path(ahd, scb); - printf("Bus Device Reset Message Sent\n"); + printk("Bus Device Reset Message Sent\n"); /* * Clear our selection hardware in advance of * the busfree. We may have an entry in the waiting @@ -3496,7 +4472,7 @@ ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, } ahd->msgout_len++; ahd_print_path(ahd, scb); - printf("Abort%s Message Sent\n", + printk("Abort%s Message Sent\n", (scb->hscb->control & TAG_ENB) != 0 ? " Tag" : ""); /* * Clear our selection hardware in advance of @@ -3517,9 +4493,9 @@ ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, */ ahd_outb(ahd, SCSISEQ0, 0); } else { - printf("ahd_intr: AWAITING_MSG for an SCB that " + printk("ahd_intr: AWAITING_MSG for an SCB that " "does not have a waiting message\n"); - printf("SCSIID = %x, target_mask = %x\n", scb->hscb->scsiid, + printk("SCSIID = %x, target_mask = %x\n", scb->hscb->scsiid, devinfo->target_mask); panic("SCB = %d, SCB Control = %x:%x, MSG_OUT = %x " "SCB flags = %x", SCB_GET_TAG(scb), scb->hscb->control, @@ -3601,7 +4577,7 @@ ahd_build_transfer_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) if (bootverbose) { ahd_print_devinfo(ahd, devinfo); - printf("Ensuring async\n"); + printk("Ensuring async\n"); } } /* Target initiated PPR is not allowed in the SCSI spec */ @@ -3644,14 +4620,11 @@ ahd_construct_sdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, { if (offset == 0) period = AHD_ASYNC_XFER_PERIOD; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR_LEN; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_SDTR; - ahd->msgout_buf[ahd->msgout_index++] = period; - ahd->msgout_buf[ahd->msgout_index++] = offset; + ahd->msgout_index += spi_populate_sync_msg( + ahd->msgout_buf + ahd->msgout_index, period, offset); ahd->msgout_len += 5; if (bootverbose) { - printf("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n", + printk("(%s:%c:%d:%d): Sending SDTR period %x, offset %x\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun, period, offset); } @@ -3665,13 +4638,11 @@ static void ahd_construct_wdtr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, u_int bus_width) { - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR_LEN; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_WDTR; - ahd->msgout_buf[ahd->msgout_index++] = bus_width; + ahd->msgout_index += spi_populate_width_msg( + ahd->msgout_buf + ahd->msgout_index, bus_width); ahd->msgout_len += 4; if (bootverbose) { - printf("(%s:%c:%d:%d): Sending WDTR %x\n", + printk("(%s:%c:%d:%d): Sending WDTR %x\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun, bus_width); } @@ -3695,17 +4666,12 @@ ahd_construct_ppr(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ppr_options |= MSG_EXT_PPR_PCOMP_EN; if (offset == 0) period = AHD_ASYNC_XFER_PERIOD; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXTENDED; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR_LEN; - ahd->msgout_buf[ahd->msgout_index++] = MSG_EXT_PPR; - ahd->msgout_buf[ahd->msgout_index++] = period; - ahd->msgout_buf[ahd->msgout_index++] = 0; - ahd->msgout_buf[ahd->msgout_index++] = offset; - ahd->msgout_buf[ahd->msgout_index++] = bus_width; - ahd->msgout_buf[ahd->msgout_index++] = ppr_options; + ahd->msgout_index += spi_populate_ppr_msg( + ahd->msgout_buf + ahd->msgout_index, period, offset, + bus_width, ppr_options); ahd->msgout_len += 8; if (bootverbose) { - printf("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, " + printk("(%s:%c:%d:%d): Sending PPR bus_width %x, period %x, " "offset %x, ppr_options %x\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun, bus_width, period, offset, ppr_options); @@ -3745,7 +4711,7 @@ ahd_clear_msg_state(struct ahd_softc *ahd) */ static void ahd_handle_message_phase(struct ahd_softc *ahd) -{ +{ struct ahd_devinfo devinfo; u_int bus_phase; int end_session; @@ -3755,7 +4721,7 @@ ahd_handle_message_phase(struct ahd_softc *ahd) bus_phase = ahd_inb(ahd, LASTPHASE); if ((ahd_inb(ahd, LQISTAT2) & LQIPHASE_OUTPKT) != 0) { - printf("LQIRETRY for LQIPHASE_OUTPKT\n"); + printk("LQIRETRY for LQIPHASE_OUTPKT\n"); ahd_outb(ahd, LQCTL2, LQIRETRY); } reswitch: @@ -3772,14 +4738,14 @@ reswitch: #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { ahd_print_devinfo(ahd, &devinfo); - printf("INITIATOR_MSG_OUT"); + printk("INITIATOR_MSG_OUT"); } #endif phasemis = bus_phase != P_MESGOUT; if (phasemis) { #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { - printf(" PHASEMIS %s\n", + printk(" PHASEMIS %s\n", ahd_lookup_phase_entry(bus_phase) ->phasemsg); } @@ -3806,7 +4772,7 @@ reswitch: ahd_outb(ahd, CLRSINT1, CLRREQINIT); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf(" byte 0x%x\n", ahd->send_msg_perror); + printk(" byte 0x%x\n", ahd->send_msg_perror); #endif /* * If we are notifying the target of a CRC error @@ -3847,7 +4813,7 @@ reswitch: ahd_outb(ahd, CLRSINT1, CLRREQINIT); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf(" byte 0x%x\n", + printk(" byte 0x%x\n", ahd->msgout_buf[ahd->msgout_index]); #endif ahd_outb(ahd, RETURN_2, ahd->msgout_buf[ahd->msgout_index++]); @@ -3862,14 +4828,14 @@ reswitch: #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { ahd_print_devinfo(ahd, &devinfo); - printf("INITIATOR_MSG_IN"); + printk("INITIATOR_MSG_IN"); } #endif phasemis = bus_phase != P_MESGIN; if (phasemis) { #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { - printf(" PHASEMIS %s\n", + printk(" PHASEMIS %s\n", ahd_lookup_phase_entry(bus_phase) ->phasemsg); } @@ -3890,7 +4856,7 @@ reswitch: ahd->msgin_buf[ahd->msgin_index] = ahd_inb(ahd, SCSIBUS); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf(" byte 0x%x\n", + printk(" byte 0x%x\n", ahd->msgin_buf[ahd->msgin_index]); #endif @@ -3912,7 +4878,7 @@ reswitch: #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) { ahd_print_devinfo(ahd, &devinfo); - printf("Asserting ATN for response\n"); + printk("Asserting ATN for response\n"); } #endif ahd_assert_atn(ahd); @@ -4060,7 +5026,7 @@ reswitch: if (end_session) { if ((ahd->msg_flags & MSG_FLAG_PACKETIZED) != 0) { - printf("%s: Returning to Idle Loop\n", + printk("%s: Returning to Idle Loop\n", ahd_name(ahd)); ahd_clear_msg_state(ahd); @@ -4212,7 +5178,7 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) ahd_validate_offset(ahd, tinfo, period, &offset, tinfo->curr.width, devinfo->role); if (bootverbose) { - printf("(%s:%c:%d:%d): Received " + printk("(%s:%c:%d:%d): Received " "SDTR period %x, offset %x\n\t" "Filtered to period %x, offset %x\n", ahd_name(ahd), devinfo->channel, @@ -4242,7 +5208,7 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) */ if (bootverbose && devinfo->role == ROLE_INITIATOR) { - printf("(%s:%c:%d:%d): Target " + printk("(%s:%c:%d:%d): Target " "Initiated SDTR\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun); @@ -4284,7 +5250,7 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) ahd_validate_width(ahd, tinfo, &bus_width, devinfo->role); if (bootverbose) { - printf("(%s:%c:%d:%d): Received WDTR " + printk("(%s:%c:%d:%d): Received WDTR " "%x filtered to %x\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun, @@ -4300,7 +5266,7 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) */ if (saved_width > bus_width) { reject = TRUE; - printf("(%s:%c:%d:%d): requested %dBit " + printk("(%s:%c:%d:%d): requested %dBit " "transfers. Rejecting...\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun, @@ -4313,7 +5279,7 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) */ if (bootverbose && devinfo->role == ROLE_INITIATOR) { - printf("(%s:%c:%d:%d): Target " + printk("(%s:%c:%d:%d): Target " "Initiated WDTR\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun); @@ -4425,12 +5391,12 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) } } else { if (devinfo->role != ROLE_TARGET) - printf("(%s:%c:%d:%d): Target " + printk("(%s:%c:%d:%d): Target " "Initiated PPR\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun); else - printf("(%s:%c:%d:%d): Initiator " + printk("(%s:%c:%d:%d): Initiator " "Initiated PPR\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun); @@ -4442,7 +5408,7 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) response = TRUE; } if (bootverbose) { - printf("(%s:%c:%d:%d): Received PPR width %x, " + printk("(%s:%c:%d:%d): Received PPR width %x, " "period %x, offset %x,options %x\n" "\tFiltered to width %x, period %x, " "offset %x, options %x\n", @@ -4518,7 +5484,7 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) case MSG_QAS_REQUEST: #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MESSAGES) != 0) - printf("%s: QAS request. SCSISIGI == 0x%x\n", + printk("%s: QAS request. SCSISIGI == 0x%x\n", ahd_name(ahd), ahd_inb(ahd, SCSISIGI)); #endif ahd->msg_flags |= MSG_FLAG_EXPECT_QASREJ_BUSFREE; @@ -4583,7 +5549,7 @@ ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) * off these options. */ if (bootverbose) { - printf("(%s:%c:%d:%d): PPR Rejected. " + printk("(%s:%c:%d:%d): PPR Rejected. " "Trying simple U160 PPR\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun); @@ -4598,7 +5564,7 @@ ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) * Attempt to negotiate SPI-2 style. */ if (bootverbose) { - printf("(%s:%c:%d:%d): PPR Rejected. " + printk("(%s:%c:%d:%d): PPR Rejected. " "Trying WDTR/SDTR\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun); @@ -4615,7 +5581,7 @@ ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) } else if (ahd_sent_msg(ahd, AHDMSG_EXT, MSG_EXT_WDTR, /*full*/FALSE)) { /* note 8bit xfers */ - printf("(%s:%c:%d:%d): refuses WIDE negotiation. Using " + printk("(%s:%c:%d:%d): refuses WIDE negotiation. Using " "8bit transfers\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun); ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT, @@ -4643,7 +5609,7 @@ ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) /*offset*/0, /*ppr_options*/0, AHD_TRANS_ACTIVE|AHD_TRANS_GOAL, /*paused*/TRUE); - printf("(%s:%c:%d:%d): refuses synchronous negotiation. " + printk("(%s:%c:%d:%d): refuses synchronous negotiation. " "Using asynchronous transfers\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun); @@ -4654,18 +5620,18 @@ ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) tag_type = (scb->hscb->control & MSG_SIMPLE_TASK); if (tag_type == MSG_SIMPLE_TASK) { - printf("(%s:%c:%d:%d): refuses tagged commands. " + printk("(%s:%c:%d:%d): refuses tagged commands. " "Performing non-tagged I/O\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun); - ahd_set_tags(ahd, devinfo, AHD_QUEUE_NONE); + ahd_set_tags(ahd, scb->io_ctx, devinfo, AHD_QUEUE_NONE); mask = ~0x23; } else { - printf("(%s:%c:%d:%d): refuses %s tagged commands. " + printk("(%s:%c:%d:%d): refuses %s tagged commands. " "Performing simple queue tagged I/O only\n", ahd_name(ahd), devinfo->channel, devinfo->target, devinfo->lun, tag_type == MSG_ORDERED_TASK ? "ordered" : "head of queue"); - ahd_set_tags(ahd, devinfo, AHD_QUEUE_BASIC); + ahd_set_tags(ahd, scb->io_ctx, devinfo, AHD_QUEUE_BASIC); mask = ~0x03; } @@ -4685,7 +5651,7 @@ ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) /* * Requeue all tagged commands for this target - * currently in our posession so they can be + * currently in our possession so they can be * converted to untagged commands. */ ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb), @@ -4711,7 +5677,7 @@ ahd_handle_msg_reject(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) /* * Otherwise, we ignore it. */ - printf("%s:%c:%d: Message reject for %x -- ignored\n", + printk("%s:%c:%d: Message reject for %x -- ignored\n", ahd_name(ahd), devinfo->channel, devinfo->target, last_msg); } @@ -4898,7 +5864,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd) ahd_delay(100); if (wait == 0) { ahd_print_path(ahd, scb); - printf("ahd_reinitialize_dataptrs: Forcing FIFO free.\n"); + printk("ahd_reinitialize_dataptrs: Forcing FIFO free.\n"); ahd_outb(ahd, DFFSXFRCTL, RSTCHN|CLRSHCNT); } saved_modes = ahd_save_modes(ahd); @@ -4911,10 +5877,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd) * Determine initial values for data_addr and data_cnt * for resuming the data phase. */ - sgptr = (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 3) << 24) - | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 2) << 16) - | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 1) << 8) - | ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR); + sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR); sgptr &= SG_PTR_MASK; resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16) @@ -4932,10 +5895,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd) dataptr = ahd_le64toh(sg->addr) + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK) - resid; - ahd_outb(ahd, HADDR + 7, dataptr >> 56); - ahd_outb(ahd, HADDR + 6, dataptr >> 48); - ahd_outb(ahd, HADDR + 5, dataptr >> 40); - ahd_outb(ahd, HADDR + 4, dataptr >> 32); + ahd_outl(ahd, HADDR + 4, dataptr >> 32); } else { struct ahd_dma_seg *sg; @@ -4950,10 +5910,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd) ahd_outb(ahd, HADDR + 4, (ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24); } - ahd_outb(ahd, HADDR + 3, dataptr >> 24); - ahd_outb(ahd, HADDR + 2, dataptr >> 16); - ahd_outb(ahd, HADDR + 1, dataptr >> 8); - ahd_outb(ahd, HADDR, dataptr); + ahd_outl(ahd, HADDR, dataptr); ahd_outb(ahd, HCNT + 2, resid >> 16); ahd_outb(ahd, HCNT + 1, resid >> 8); ahd_outb(ahd, HCNT, resid); @@ -4993,7 +5950,7 @@ ahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, cur_lun = lun; max_lun = lun; } - for (cur_lun <= max_lun; cur_lun++) { + for (;cur_lun <= max_lun; cur_lun++) { struct ahd_tmode_lstate* lstate; lstate = tstate->enabled_luns[cur_lun]; @@ -5013,14 +5970,15 @@ ahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT, AHD_TRANS_CUR, /*paused*/TRUE); ahd_set_syncrate(ahd, devinfo, /*period*/0, /*offset*/0, - /*ppr_options*/0, AHD_TRANS_CUR, /*paused*/TRUE); + /*ppr_options*/0, AHD_TRANS_CUR, + /*paused*/TRUE); - ahd_send_async(ahd, devinfo->channel, devinfo->target, - lun, AC_SENT_BDR, NULL); + if (status != CAM_SEL_TIMEOUT) + ahd_send_async(ahd, devinfo->channel, devinfo->target, + CAM_LUN_WILDCARD, AC_SENT_BDR); - if (message != NULL - && (verbose_level <= bootverbose)) - printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd), + if (message != NULL && bootverbose) + printk("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd), message, devinfo->channel, devinfo->target, found); } @@ -5116,23 +6074,22 @@ ahd_alloc(void *platform_arg, char *name) struct ahd_softc *ahd; #ifndef __FreeBSD__ - ahd = malloc(sizeof(*ahd), M_DEVBUF, M_NOWAIT); + ahd = kmalloc(sizeof(*ahd), GFP_ATOMIC); if (!ahd) { - printf("aic7xxx: cannot malloc softc!\n"); - free(name, M_DEVBUF); + printk("aic7xxx: cannot malloc softc!\n"); + kfree(name); return NULL; } #else ahd = device_get_softc((device_t)platform_arg); #endif memset(ahd, 0, sizeof(*ahd)); - ahd->seep_config = malloc(sizeof(*ahd->seep_config), - M_DEVBUF, M_NOWAIT); + ahd->seep_config = kmalloc(sizeof(*ahd->seep_config), GFP_ATOMIC); if (ahd->seep_config == NULL) { #ifndef __FreeBSD__ - free(ahd, M_DEVBUF); + kfree(ahd); #endif - free(name, M_DEVBUF); + kfree(name); return (NULL); } LIST_INIT(&ahd->pending_scbs); @@ -5162,7 +6119,7 @@ ahd_alloc(void *platform_arg, char *name) } #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MEMORY) != 0) { - printf("%s: scb size = 0x%x, hscb size = 0x%x\n", + printk("%s: scb size = 0x%x, hscb size = 0x%x\n", ahd_name(ahd), (u_int)sizeof(struct scb), (u_int)sizeof(struct hardware_scb)); } @@ -5180,74 +6137,6 @@ ahd_softc_init(struct ahd_softc *ahd) } void -ahd_softc_insert(struct ahd_softc *ahd) -{ - struct ahd_softc *list_ahd; - -#if AHD_PCI_CONFIG > 0 - /* - * Second Function PCI devices need to inherit some - * settings from function 0. - */ - if ((ahd->features & AHD_MULTI_FUNC) != 0) { - TAILQ_FOREACH(list_ahd, &ahd_tailq, links) { - ahd_dev_softc_t list_pci; - ahd_dev_softc_t pci; - - list_pci = list_ahd->dev_softc; - pci = ahd->dev_softc; - if (ahd_get_pci_slot(list_pci) == ahd_get_pci_slot(pci) - && ahd_get_pci_bus(list_pci) == ahd_get_pci_bus(pci)) { - struct ahd_softc *master; - struct ahd_softc *slave; - - if (ahd_get_pci_function(list_pci) == 0) { - master = list_ahd; - slave = ahd; - } else { - master = ahd; - slave = list_ahd; - } - slave->flags &= ~AHD_BIOS_ENABLED; - slave->flags |= - master->flags & AHD_BIOS_ENABLED; - break; - } - } - } -#endif - - /* - * Insertion sort into our list of softcs. - */ - list_ahd = TAILQ_FIRST(&ahd_tailq); - while (list_ahd != NULL - && ahd_softc_comp(ahd, list_ahd) <= 0) - list_ahd = TAILQ_NEXT(list_ahd, links); - if (list_ahd != NULL) - TAILQ_INSERT_BEFORE(list_ahd, ahd, links); - else - TAILQ_INSERT_TAIL(&ahd_tailq, ahd, links); - ahd->init_level++; -} - -/* - * Verify that the passed in softc pointer is for a - * controller that is still configured. - */ -struct ahd_softc * -ahd_find_softc(struct ahd_softc *ahd) -{ - struct ahd_softc *list_ahd; - - TAILQ_FOREACH(list_ahd, &ahd_tailq, links) { - if (list_ahd == ahd) - return (ahd); - } - return (NULL); -} - -void ahd_set_unit(struct ahd_softc *ahd, int unit) { ahd->unit = unit; @@ -5257,7 +6146,7 @@ void ahd_set_name(struct ahd_softc *ahd, char *name) { if (ahd->name != NULL) - free(ahd->name, M_DEVBUF); + kfree(ahd->name); ahd->name = name; } @@ -5273,13 +6162,13 @@ ahd_free(struct ahd_softc *ahd) /* FALLTHROUGH */ case 4: ahd_dmamap_unload(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap); + ahd->shared_data_map.dmamap); /* FALLTHROUGH */ case 3: ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo, - ahd->shared_data_dmamap); + ahd->shared_data_map.dmamap); ahd_dmamap_destroy(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap); + ahd->shared_data_map.dmamap); /* FALLTHROUGH */ case 2: ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat); @@ -5311,32 +6200,32 @@ ahd_free(struct ahd_softc *ahd) lstate = tstate->enabled_luns[j]; if (lstate != NULL) { xpt_free_path(lstate->path); - free(lstate, M_DEVBUF); + kfree(lstate); } } #endif - free(tstate, M_DEVBUF); + kfree(tstate); } } #ifdef AHD_TARGET_MODE if (ahd->black_hole != NULL) { xpt_free_path(ahd->black_hole->path); - free(ahd->black_hole, M_DEVBUF); + kfree(ahd->black_hole); } #endif if (ahd->name != NULL) - free(ahd->name, M_DEVBUF); + kfree(ahd->name); if (ahd->seep_config != NULL) - free(ahd->seep_config, M_DEVBUF); + kfree(ahd->seep_config); if (ahd->saved_stack != NULL) - free(ahd->saved_stack, M_DEVBUF); + kfree(ahd->saved_stack); #ifndef __FreeBSD__ - free(ahd, M_DEVBUF); + kfree(ahd); #endif return; } -void +static void ahd_shutdown(void *arg) { struct ahd_softc *ahd; @@ -5356,7 +6245,7 @@ ahd_shutdown(void *arg) /* * Reset the controller and record some information about it * that is only available just after a reset. If "reinit" is - * non-zero, this reset occured after initial configuration + * non-zero, this reset occurred after initial configuration * and the caller requests that the chip be fully reinitialized * to a runable state. Chip interrupts are *not* enabled after * a reinitialization. The caller must enable interrupts via @@ -5410,7 +6299,7 @@ ahd_reset(struct ahd_softc *ahd, int reinit) } while (--wait && !(ahd_inb(ahd, HCNTRL) & CHIPRSTACK)); if (wait == 0) { - printf("%s: WARNING - Failed chip reset! " + printk("%s: WARNING - Failed chip reset! " "Trying to initialize anyway.\n", ahd_name(ahd)); } ahd_outb(ahd, HCNTRL, ahd->pause); @@ -5465,7 +6354,7 @@ ahd_reset(struct ahd_softc *ahd, int reinit) /* * Determine the number of SCBs available on the controller */ -int +static int ahd_probe_scbs(struct ahd_softc *ahd) { int i; @@ -5532,7 +6421,7 @@ ahd_init_scbdata(struct ahd_softc *ahd) /* Determine the number of hardware SCBs and initialize them */ scb_data->maxhscbs = ahd_probe_scbs(ahd); if (scb_data->maxhscbs == 0) { - printf("%s: No SCB space found\n", ahd_name(ahd)); + printk("%s: No SCB space found\n", ahd_name(ahd)); return (ENXIO); } @@ -5575,7 +6464,7 @@ ahd_init_scbdata(struct ahd_softc *ahd) } #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MEMORY) != 0) - printf("%s: ahd_sglist_allocsize = 0x%x\n", ahd_name(ahd), + printk("%s: ahd_sglist_allocsize = 0x%x\n", ahd_name(ahd), ahd_sglist_allocsize(ahd)); #endif @@ -5599,14 +6488,14 @@ ahd_init_scbdata(struct ahd_softc *ahd) ahd_alloc_scbs(ahd); if (scb_data->numscbs == 0) { - printf("%s: ahd_init_scbdata - " + printk("%s: ahd_init_scbdata - " "Unable to allocate initial scbs\n", ahd_name(ahd)); goto error_exit; } /* - * Note that we were successfull + * Note that we were successful */ return (0); @@ -5674,7 +6563,7 @@ ahd_fini_scbdata(struct ahd_softc *ahd) sns_map->dmamap); ahd_dmamem_free(ahd, scb_data->sense_dmat, sns_map->vaddr, sns_map->dmamap); - free(sns_map, M_DEVBUF); + kfree(sns_map); } ahd_dma_tag_destroy(ahd, scb_data->sense_dmat); /* FALLTHROUGH */ @@ -5689,7 +6578,7 @@ ahd_fini_scbdata(struct ahd_softc *ahd) sg_map->dmamap); ahd_dmamem_free(ahd, scb_data->sg_dmat, sg_map->vaddr, sg_map->dmamap); - free(sg_map, M_DEVBUF); + kfree(sg_map); } ahd_dma_tag_destroy(ahd, scb_data->sg_dmat); /* FALLTHROUGH */ @@ -5704,7 +6593,7 @@ ahd_fini_scbdata(struct ahd_softc *ahd) hscb_map->dmamap); ahd_dmamem_free(ahd, scb_data->hscb_dmat, hscb_map->vaddr, hscb_map->dmamap); - free(hscb_map, M_DEVBUF); + kfree(hscb_map); } ahd_dma_tag_destroy(ahd, scb_data->hscb_dmat); /* FALLTHROUGH */ @@ -5734,7 +6623,7 @@ ahd_setup_iocell_workaround(struct ahd_softc *ahd) ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) | (ENSELDO|ENSELDI)); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("%s: Setting up iocell workaround\n", ahd_name(ahd)); + printk("%s: Setting up iocell workaround\n", ahd_name(ahd)); #endif ahd_restore_modes(ahd, saved_modes); ahd->flags &= ~AHD_HAD_FIRST_SEL; @@ -5754,14 +6643,14 @@ ahd_iocell_first_selection(struct ahd_softc *ahd) ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("%s: iocell first selection\n", ahd_name(ahd)); + printk("%s: iocell first selection\n", ahd_name(ahd)); #endif if ((sblkctl & ENAB40) != 0) { ahd_outb(ahd, DSPDATACTL, ahd_inb(ahd, DSPDATACTL) & ~BYPASSENAB); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("%s: BYPASS now disabled\n", ahd_name(ahd)); + printk("%s: BYPASS now disabled\n", ahd_name(ahd)); #endif } ahd_outb(ahd, SIMODE0, ahd_inb(ahd, SIMODE0) & ~(ENSELDO|ENSELDI)); @@ -5863,8 +6752,7 @@ found: */ void ahd_free_scb(struct ahd_softc *ahd, struct scb *scb) -{ - +{ /* Clean up for the next user */ scb->flags = SCB_FLAG_NONE; scb->hscb->control = 0; @@ -5914,7 +6802,7 @@ ahd_free_scb(struct ahd_softc *ahd, struct scb *scb) ahd_platform_scb_free(ahd, scb); } -void +static void ahd_alloc_scbs(struct ahd_softc *ahd) { struct scb_data *scb_data; @@ -5944,7 +6832,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) hscb = &((struct hardware_scb *)hscb_map->vaddr)[offset]; hscb_busaddr = hscb_map->physaddr + (offset * sizeof(*hscb)); } else { - hscb_map = malloc(sizeof(*hscb_map), M_DEVBUF, M_NOWAIT); + hscb_map = kmalloc(sizeof(*hscb_map), GFP_ATOMIC); if (hscb_map == NULL) return; @@ -5953,7 +6841,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) if (ahd_dmamem_alloc(ahd, scb_data->hscb_dmat, (void **)&hscb_map->vaddr, BUS_DMA_NOWAIT, &hscb_map->dmamap) != 0) { - free(hscb_map, M_DEVBUF); + kfree(hscb_map); return; } @@ -5977,7 +6865,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) segs = sg_map->vaddr + offset; sg_busaddr = sg_map->physaddr + offset; } else { - sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT); + sg_map = kmalloc(sizeof(*sg_map), GFP_ATOMIC); if (sg_map == NULL) return; @@ -5986,7 +6874,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) if (ahd_dmamem_alloc(ahd, scb_data->sg_dmat, (void **)&sg_map->vaddr, BUS_DMA_NOWAIT, &sg_map->dmamap) != 0) { - free(sg_map, M_DEVBUF); + kfree(sg_map); return; } @@ -6002,7 +6890,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd); #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_MEMORY) - printf("Mapped SG data\n"); + printk("Mapped SG data\n"); #endif } @@ -6014,7 +6902,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) sense_data = sense_map->vaddr + offset; sense_busaddr = sense_map->physaddr + offset; } else { - sense_map = malloc(sizeof(*sense_map), M_DEVBUF, M_NOWAIT); + sense_map = kmalloc(sizeof(*sense_map), GFP_ATOMIC); if (sense_map == NULL) return; @@ -6023,7 +6911,7 @@ ahd_alloc_scbs(struct ahd_softc *ahd) if (ahd_dmamem_alloc(ahd, scb_data->sense_dmat, (void **)&sense_map->vaddr, BUS_DMA_NOWAIT, &sense_map->dmamap) != 0) { - free(sense_map, M_DEVBUF); + kfree(sense_map); return; } @@ -6038,32 +6926,27 @@ ahd_alloc_scbs(struct ahd_softc *ahd) scb_data->sense_left = PAGE_SIZE / AHD_SENSE_BUFSIZE; #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_MEMORY) - printf("Mapped sense data\n"); + printk("Mapped sense data\n"); #endif } - newcount = MIN(scb_data->sense_left, scb_data->scbs_left); - newcount = MIN(newcount, scb_data->sgs_left); - newcount = MIN(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs)); - scb_data->sense_left -= newcount; - scb_data->scbs_left -= newcount; - scb_data->sgs_left -= newcount; + newcount = min(scb_data->sense_left, scb_data->scbs_left); + newcount = min(newcount, scb_data->sgs_left); + newcount = min(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs)); for (i = 0; i < newcount; i++) { - u_int col_tag; - struct scb_platform_data *pdata; + u_int col_tag; #ifndef __linux__ int error; #endif - next_scb = (struct scb *)malloc(sizeof(*next_scb), - M_DEVBUF, M_NOWAIT); + + next_scb = kmalloc(sizeof(*next_scb), GFP_ATOMIC); if (next_scb == NULL) break; - pdata = (struct scb_platform_data *)malloc(sizeof(*pdata), - M_DEVBUF, M_NOWAIT); + pdata = kmalloc(sizeof(*pdata), GFP_ATOMIC); if (pdata == NULL) { - free(next_scb, M_DEVBUF); + kfree(next_scb); break; } next_scb->platform_data = pdata; @@ -6093,8 +6976,8 @@ ahd_alloc_scbs(struct ahd_softc *ahd) error = ahd_dmamap_create(ahd, ahd->buffer_dmat, /*flags*/0, &next_scb->dmamap); if (error != 0) { - free(next_scb, M_DEVBUF); - free(pdata, M_DEVBUF); + kfree(next_scb); + kfree(pdata); break; } #endif @@ -6111,6 +6994,9 @@ ahd_alloc_scbs(struct ahd_softc *ahd) sense_data += AHD_SENSE_BUFSIZE; sense_busaddr += AHD_SENSE_BUFSIZE; scb_data->numscbs++; + scb_data->sense_left--; + scb_data->scbs_left--; + scb_data->sgs_left--; } } @@ -6152,13 +7038,30 @@ static const char *termstat_strings[] = { "Not Configured" }; +/***************************** Timer Facilities *******************************/ +#define ahd_timer_init init_timer +#define ahd_timer_stop del_timer_sync +typedef void ahd_linux_callback_t (u_long); + +static void +ahd_timer_reset(ahd_timer_t *timer, int usec, ahd_callback_t *func, void *arg) +{ + struct ahd_softc *ahd; + + ahd = (struct ahd_softc *)arg; + del_timer(timer); + timer->data = (u_long)arg; + timer->expires = jiffies + (usec * HZ)/1000000; + timer->function = (ahd_linux_callback_t*)func; + add_timer(timer); +} + /* * Start the board, ready for normal operation */ int ahd_init(struct ahd_softc *ahd) { - uint8_t *base_vaddr; uint8_t *next_vaddr; dma_addr_t next_baddr; size_t driver_data_size; @@ -6171,13 +7074,12 @@ ahd_init(struct ahd_softc *ahd) AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); ahd->stack_size = ahd_probe_stack_size(ahd); - ahd->saved_stack = malloc(ahd->stack_size * sizeof(uint16_t), - M_DEVBUF, M_NOWAIT); + ahd->saved_stack = kmalloc(ahd->stack_size * sizeof(uint16_t), GFP_ATOMIC); if (ahd->saved_stack == NULL) return (ENOMEM); /* - * Verify that the compiler hasn't over-agressively + * Verify that the compiler hasn't over-aggressively * padded important structures. */ if (sizeof(struct hardware_scb) != 64) @@ -6226,7 +7128,7 @@ ahd_init(struct ahd_softc *ahd) * for the target mode role, we must additionally provide space for * the incoming target command fifo. */ - driver_data_size = AHD_SCB_MAX * sizeof(uint16_t) + driver_data_size = AHD_SCB_MAX * sizeof(*ahd->qoutfifo) + sizeof(struct hardware_scb); if ((ahd->features & AHD_TARGETMODE) != 0) driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd); @@ -6248,20 +7150,23 @@ ahd_init(struct ahd_softc *ahd) /* Allocation of driver data */ if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat, - (void **)&base_vaddr, - BUS_DMA_NOWAIT, &ahd->shared_data_dmamap) != 0) { + (void **)&ahd->shared_data_map.vaddr, + BUS_DMA_NOWAIT, + &ahd->shared_data_map.dmamap) != 0) { return (ENOMEM); } ahd->init_level++; /* And permanently map it in */ - ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap, - base_vaddr, driver_data_size, ahd_dmamap_cb, - &ahd->shared_data_busaddr, /*flags*/0); - ahd->qoutfifo = (uint16_t *)base_vaddr; + ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap, + ahd->shared_data_map.vaddr, driver_data_size, + ahd_dmamap_cb, &ahd->shared_data_map.physaddr, + /*flags*/0); + ahd->qoutfifo = (struct ahd_completion *)ahd->shared_data_map.vaddr; next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE]; - next_baddr = ahd->shared_data_busaddr + AHD_QOUT_SIZE*sizeof(uint16_t); + next_baddr = ahd->shared_data_map.physaddr + + AHD_QOUT_SIZE*sizeof(struct ahd_completion); if ((ahd->features & AHD_TARGETMODE) != 0) { ahd->targetcmds = (struct target_cmd *)next_vaddr; next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd); @@ -6282,6 +7187,7 @@ ahd_init(struct ahd_softc *ahd) * specially from the DMA safe memory chunk used for the QOUTFIFO. */ ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr; + ahd->next_queued_hscb_map = &ahd->shared_data_map; ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr); ahd->init_level++; @@ -6314,20 +7220,20 @@ ahd_init(struct ahd_softc *ahd) error = ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, CURSENSE_ENB); if (error != 0) { - printf("%s: current sensing timeout 1\n", ahd_name(ahd)); + printk("%s: current sensing timeout 1\n", ahd_name(ahd)); goto init_done; } for (i = 20, fstat = FLX_FSTAT_BUSY; (fstat & FLX_FSTAT_BUSY) != 0 && i; i--) { error = ahd_read_flexport(ahd, FLXADDR_FLEXSTAT, &fstat); if (error != 0) { - printf("%s: current sensing timeout 2\n", + printk("%s: current sensing timeout 2\n", ahd_name(ahd)); goto init_done; } } if (i == 0) { - printf("%s: Timedout during current-sensing test\n", + printk("%s: Timedout during current-sensing test\n", ahd_name(ahd)); goto init_done; } @@ -6335,7 +7241,7 @@ ahd_init(struct ahd_softc *ahd) /* Latch Current Sensing status. */ error = ahd_read_flexport(ahd, FLXADDR_CURRENT_STAT, ¤t_sensing); if (error != 0) { - printf("%s: current sensing timeout 3\n", ahd_name(ahd)); + printk("%s: current sensing timeout 3\n", ahd_name(ahd)); goto init_done; } @@ -6344,7 +7250,7 @@ ahd_init(struct ahd_softc *ahd) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_TERMCTL) != 0) { - printf("%s: current_sensing == 0x%x\n", + printk("%s: current_sensing == 0x%x\n", ahd_name(ahd), current_sensing); } #endif @@ -6361,13 +7267,13 @@ ahd_init(struct ahd_softc *ahd) case FLX_CSTAT_OKAY: if (warn_user == 0 && bootverbose == 0) break; - printf("%s: %s Channel %s\n", ahd_name(ahd), + printk("%s: %s Channel %s\n", ahd_name(ahd), channel_strings[i], termstat_strings[term_stat]); break; } } if (warn_user) { - printf("%s: WARNING. Termination is not configured correctly.\n" + printk("%s: WARNING. Termination is not configured correctly.\n" "%s: WARNING. SCSI bus operations may FAIL.\n", ahd_name(ahd), ahd_name(ahd)); } @@ -6483,7 +7389,7 @@ ahd_chip_init(struct ahd_softc *ahd) } #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("%s: WRTBIASCTL now 0x%x\n", ahd_name(ahd), + printk("%s: WRTBIASCTL now 0x%x\n", ahd_name(ahd), WRTBIASCTL_HP_DEFAULT); #endif } @@ -6497,13 +7403,14 @@ ahd_chip_init(struct ahd_softc *ahd) | ENLQIOVERI_LQ|ENLQIOVERI_NLQ); ahd_outb(ahd, LQOMODE0, ENLQOATNLQ|ENLQOATNPKT|ENLQOTCRC); /* - * An interrupt from LQOBUSFREE is made redundant by the - * BUSFREE interrupt. We choose to have the sequencer catch - * LQOPHCHGINPKT errors manually for the command phase at the - * start of a packetized selection case. - ahd_outb(ahd, LQOMODE1, ENLQOBUSFREE|ENLQOPHACHGINPKT); + * We choose to have the sequencer catch LQOPHCHGINPKT errors + * manually for the command phase at the start of a packetized + * selection case. ENLQOBUSFREE should be made redundant by + * the BUSFREE interrupt, but it seems that some LQOBUSFREE + * events fail to assert the BUSFREE interrupt so we must + * also enable LQOBUSFREE interrupts. */ - ahd_outb(ahd, LQOMODE1, 0); + ahd_outb(ahd, LQOMODE1, ENLQOBUSFREE); /* * Setup sequencer interrupt handlers. @@ -6587,10 +7494,10 @@ ahd_chip_init(struct ahd_softc *ahd) /* All of our queues are empty */ ahd->qoutfifonext = 0; - ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID_LE; - ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID >> 8); + ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID; + ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID); for (i = 0; i < AHD_QOUT_SIZE; i++) - ahd->qoutfifo[i] = 0; + ahd->qoutfifo[i].valid_tag = 0; ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD); ahd->qinfifonext = 0; @@ -6614,6 +7521,8 @@ ahd_chip_init(struct ahd_softc *ahd) /* We don't have any waiting selections */ ahd_outw(ahd, WAITING_TID_HEAD, SCB_LIST_NULL); ahd_outw(ahd, WAITING_TID_TAIL, SCB_LIST_NULL); + ahd_outw(ahd, MK_MESSAGE_SCB, SCB_LIST_NULL); + ahd_outw(ahd, MK_MESSAGE_SCSIID, 0xFF); for (i = 0; i < AHD_NUM_TARGETS; i++) ahd_outw(ahd, WAITING_SCB_TAILS + (2 * i), SCB_LIST_NULL); @@ -6623,24 +7532,22 @@ ahd_chip_init(struct ahd_softc *ahd) ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL); ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL); ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL); + ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL); + ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL); /* * The Freeze Count is 0. */ + ahd->qfreeze_cnt = 0; ahd_outw(ahd, QFREEZE_COUNT, 0); + ahd_outw(ahd, KERNEL_QFREEZE_COUNT, 0); /* * Tell the sequencer where it can find our arrays in memory. */ - busaddr = ahd->shared_data_busaddr; - ahd_outb(ahd, SHARED_DATA_ADDR, busaddr & 0xFF); - ahd_outb(ahd, SHARED_DATA_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, SHARED_DATA_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, SHARED_DATA_ADDR + 3, (busaddr >> 24) & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR, busaddr & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 3, (busaddr >> 24) & 0xFF); + busaddr = ahd->shared_data_map.physaddr; + ahd_outl(ahd, SHARED_DATA_ADDR, busaddr); + ahd_outl(ahd, QOUTFIFO_NEXT_ADDR, busaddr); /* * Setup the allowed SCSI Sequences based on operational mode. @@ -6689,10 +7596,7 @@ ahd_chip_init(struct ahd_softc *ahd) * Tell the sequencer which SCB will be the next one it receives. */ busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); + ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr); /* * Default to coalescing disabled. @@ -6706,6 +7610,18 @@ ahd_chip_init(struct ahd_softc *ahd) ahd_loadseq(ahd); ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); + + if (ahd->features & AHD_AIC79XXB_SLOWCRC) { + u_int negodat3 = ahd_inb(ahd, NEGCONOPTS); + + negodat3 |= ENSLOWCRC; + ahd_outb(ahd, NEGCONOPTS, negodat3); + negodat3 = ahd_inb(ahd, NEGCONOPTS); + if (!(negodat3 & ENSLOWCRC)) + printk("aic79xx: failed to set the SLOWCRC bit\n"); + else + printk("aic79xx: SLOWCRC bit set\n"); + } } /* @@ -6726,7 +7642,7 @@ ahd_default_config(struct ahd_softc *ahd) * data for any target mode initiator. */ if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL) { - printf("%s: unable to allocate ahd_tmode_tstate. " + printk("%s: unable to allocate ahd_tmode_tstate. " "Failing attach\n", ahd_name(ahd)); return (ENOMEM); } @@ -6805,7 +7721,7 @@ ahd_parse_cfgdata(struct ahd_softc *ahd, struct seeprom_config *sc) * data for any target mode initiator. */ if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL) { - printf("%s: unable to allocate ahd_tmode_tstate. " + printk("%s: unable to allocate ahd_tmode_tstate. " "Failing attach\n", ahd_name(ahd)); return (ENOMEM); } @@ -6875,7 +7791,7 @@ ahd_parse_cfgdata(struct ahd_softc *ahd, struct seeprom_config *sc) user_tinfo->width = MSG_EXT_WDTR_BUS_8_BIT; #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) - printf("(%d): %x:%x:%x:%x\n", targ, user_tinfo->width, + printk("(%d): %x:%x:%x:%x\n", targ, user_tinfo->width, user_tinfo->period, user_tinfo->offset, user_tinfo->ppr_options); #endif @@ -6954,7 +7870,7 @@ ahd_intr_enable(struct ahd_softc *ahd, int enable) ahd_outb(ahd, HCNTRL, hcntrl); } -void +static void ahd_update_coalescing_values(struct ahd_softc *ahd, u_int timer, u_int maxcmds, u_int mincmds) { @@ -6972,7 +7888,7 @@ ahd_update_coalescing_values(struct ahd_softc *ahd, u_int timer, u_int maxcmds, ahd_outb(ahd, INT_COALESCING_MINCMDS, -mincmds); } -void +static void ahd_enable_coalescing(struct ahd_softc *ahd, int enable) { @@ -6996,43 +7912,34 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd) { u_int intstat; u_int maxloops; - u_int qfreeze_cnt; maxloops = 1000; ahd->flags |= AHD_ALL_INTERRUPTS; ahd_pause(ahd); /* - * Increment the QFreeze Count so that the sequencer - * will not start new selections. We do this only + * Freeze the outgoing selections. We do this only * until we are safely paused without further selections * pending. */ - ahd_outw(ahd, QFREEZE_COUNT, ahd_inw(ahd, QFREEZE_COUNT) + 1); + ahd->qfreeze_cnt--; + ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt); ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN); do { - struct scb *waiting_scb; ahd_unpause(ahd); + /* + * Give the sequencer some time to service + * any active selections. + */ + ahd_delay(500); + ahd_intr(ahd); ahd_pause(ahd); - ahd_clear_critical_section(ahd); intstat = ahd_inb(ahd, INTSTAT); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - if ((ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0) - ahd_outb(ahd, SCSISEQ0, - ahd_inb(ahd, SCSISEQ0) & ~ENSELO); - /* - * In the non-packetized case, the sequencer (for Rev A), - * relies on ENSELO remaining set after SELDO. The hardware - * auto-clears ENSELO in the packetized case. - */ - waiting_scb = ahd_lookup_scb(ahd, - ahd_inw(ahd, WAITING_TID_HEAD)); - if (waiting_scb != NULL - && (waiting_scb->flags & SCB_PACKETIZED) == 0 - && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0) - ahd_outb(ahd, SCSISEQ0, - ahd_inb(ahd, SCSISEQ0) | ENSELO); + if ((intstat & INT_PEND) == 0) { + ahd_clear_critical_section(ahd); + intstat = ahd_inb(ahd, INTSTAT); + } } while (--maxloops && (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0) && ((intstat & INT_PEND) != 0 @@ -7040,27 +7947,18 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd) || (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0)); if (maxloops == 0) { - printf("Infinite interrupt loop, INTSTAT = %x", + printk("Infinite interrupt loop, INTSTAT = %x", ahd_inb(ahd, INTSTAT)); } - qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT); - if (qfreeze_cnt == 0) { - printf("%s: ahd_pause_and_flushwork with 0 qfreeze count!\n", - ahd_name(ahd)); - } else { - qfreeze_cnt--; - } - ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt); - if (qfreeze_cnt == 0) - ahd_outb(ahd, SEQ_FLAGS2, - ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN); + ahd->qfreeze_cnt++; + ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt); ahd_flush_qoutfifo(ahd); - ahd_platform_flushwork(ahd); ahd->flags &= ~AHD_ALL_INTERRUPTS; } +#ifdef CONFIG_PM int ahd_suspend(struct ahd_softc *ahd) { @@ -7075,15 +7973,15 @@ ahd_suspend(struct ahd_softc *ahd) return (0); } -int +void ahd_resume(struct ahd_softc *ahd) { ahd_reset(ahd, /*reinit*/TRUE); ahd_intr_enable(ahd, TRUE); ahd_restart(ahd); - return (0); } +#endif /************************** Busy Target Table *********************************/ /* @@ -7094,7 +7992,7 @@ ahd_resume(struct ahd_softc *ahd) * scbid that should be restored once manipualtion * of the TCL entry is complete. */ -static __inline u_int +static inline u_int ahd_index_busy_tcl(struct ahd_softc *ahd, u_int *saved_scbid, u_int tcl) { /* @@ -7116,7 +8014,7 @@ ahd_index_busy_tcl(struct ahd_softc *ahd, u_int *saved_scbid, u_int tcl) /* * Return the untagged transaction id for a given target/channel lun. */ -u_int +static u_int ahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl) { u_int scbid; @@ -7129,7 +8027,7 @@ ahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl) return (scbid); } -void +static void ahd_busy_tcl(struct ahd_softc *ahd, u_int tcl, u_int scbid) { u_int scb_offset; @@ -7141,7 +8039,7 @@ ahd_busy_tcl(struct ahd_softc *ahd, u_int tcl, u_int scbid) } /************************** SCB and SCB queue management **********************/ -int +static int ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, int target, char channel, int lun, u_int tag, role_t role) { @@ -7177,7 +8075,7 @@ ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, int target, return match; } -void +static void ahd_freeze_devq(struct ahd_softc *ahd, struct scb *scb) { int target; @@ -7225,10 +8123,7 @@ ahd_qinfifo_requeue(struct ahd_softc *ahd, struct scb *prev_scb, uint32_t busaddr; busaddr = ahd_le32toh(scb->hscb->hscb_busaddr); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); + ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr); } else { prev_scb->hscb->next_hscb_busaddr = scb->hscb->hscb_busaddr; ahd_sync_scb(ahd, prev_scb, @@ -7255,10 +8150,10 @@ ahd_qinfifo_count(struct ahd_softc *ahd) return (wrap_qinfifonext - wrap_qinpos); else return (wrap_qinfifonext - + NUM_ELEMENTS(ahd->qinfifo) - wrap_qinpos); + + ARRAY_SIZE(ahd->qinfifo) - wrap_qinpos); } -void +static void ahd_reset_cmds_pending(struct ahd_softc *ahd) { struct scb *scb; @@ -7283,12 +8178,28 @@ ahd_reset_cmds_pending(struct ahd_softc *ahd) ahd->flags &= ~AHD_UPDATE_PEND_CMDS; } +static void +ahd_done_with_status(struct ahd_softc *ahd, struct scb *scb, uint32_t status) +{ + cam_status ostat; + cam_status cstat; + + ostat = ahd_get_transaction_status(scb); + if (ostat == CAM_REQ_INPROG) + ahd_set_transaction_status(scb, status); + cstat = ahd_get_transaction_status(scb); + if (cstat != CAM_REQ_CMP) + ahd_freeze_scb(scb); + ahd_done(ahd, scb); +} + int ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, int lun, u_int tag, role_t role, uint32_t status, ahd_search_action action) { struct scb *scb; + struct scb *mk_msg_scb; struct scb *prev_scb; ahd_mode_state saved_modes; u_int qinstart; @@ -7297,6 +8208,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, u_int tid_next; u_int tid_prev; u_int scbid; + u_int seq_flags2; u_int savedscbptr; uint32_t busaddr; int found; @@ -7325,7 +8237,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, prev_scb = NULL; if (action == SEARCH_PRINT) { - printf("qinstart = %d qinfifonext = %d\nQINFIFO:", + printk("qinstart = %d qinfifonext = %d\nQINFIFO:", qinstart, ahd->qinfifonext); } @@ -7335,15 +8247,12 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, */ ahd->qinfifonext = qinstart; busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF); - ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF); + ahd_outl(ahd, NEXT_QUEUED_SCB_ADDR, busaddr); while (qinpos != qintail) { scb = ahd_lookup_scb(ahd, ahd->qinfifo[qinpos]); if (scb == NULL) { - printf("qinpos = %d, SCB index = %d\n", + printk("qinpos = %d, SCB index = %d\n", qinpos, ahd->qinfifo[qinpos]); panic("Loop 1\n"); } @@ -7355,27 +8264,14 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, found++; switch (action) { case SEARCH_COMPLETE: - { - cam_status ostat; - cam_status cstat; - - ostat = ahd_get_transaction_status(scb); - if (ostat == CAM_REQ_INPROG) - ahd_set_transaction_status(scb, - status); - cstat = ahd_get_transaction_status(scb); - if (cstat != CAM_REQ_CMP) - ahd_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB in qinfifo\n"); - ahd_done(ahd, scb); - + printk("Inactive SCB in qinfifo\n"); + ahd_done_with_status(ahd, scb, status); /* FALLTHROUGH */ - } case SEARCH_REMOVE: break; case SEARCH_PRINT: - printf(" 0x%x", ahd->qinfifo[qinpos]); + printk(" 0x%x", ahd->qinfifo[qinpos]); /* FALLTHROUGH */ case SEARCH_COUNT: ahd_qinfifo_requeue(ahd, prev_scb, scb); @@ -7392,7 +8288,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, ahd_set_hnscb_qoff(ahd, ahd->qinfifonext); if (action == SEARCH_PRINT) - printf("\nWAITING_TID_QUEUES:\n"); + printk("\nWAITING_TID_QUEUES:\n"); /* * Search waiting for selection lists. We traverse the @@ -7400,23 +8296,27 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, * appropriate, traverse the SCBs of each "their id" * looking for matches. */ + ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); + seq_flags2 = ahd_inb(ahd, SEQ_FLAGS2); + if ((seq_flags2 & PENDING_MK_MESSAGE) != 0) { + scbid = ahd_inw(ahd, MK_MESSAGE_SCB); + mk_msg_scb = ahd_lookup_scb(ahd, scbid); + } else + mk_msg_scb = NULL; savedscbptr = ahd_get_scbptr(ahd); tid_next = ahd_inw(ahd, WAITING_TID_HEAD); tid_prev = SCB_LIST_NULL; targets = 0; for (scbid = tid_next; !SCBID_IS_NULL(scbid); scbid = tid_next) { u_int tid_head; + u_int tid_tail; - /* - * We limit based on the number of SCBs since - * MK_MESSAGE SCBs are not in the per-tid lists. - */ targets++; - if (targets > AHD_SCB_MAX) { + if (targets > AHD_NUM_TARGETS) panic("TID LIST LOOP"); - } + if (scbid >= ahd->scb_data.numscbs) { - printf("%s: Waiting TID List inconsistency. " + printk("%s: Waiting TID List inconsistency. " "SCB index == 0x%x, yet numscbs == 0x%x.", ahd_name(ahd), scbid, ahd->scb_data.numscbs); ahd_dump_card_state(ahd); @@ -7424,7 +8324,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, } scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: SCB = 0x%x Not Active!\n", + printk("%s: SCB = 0x%x Not Active!\n", ahd_name(ahd), scbid); panic("Waiting TID List traversal\n"); } @@ -7440,19 +8340,84 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, * We found a list of scbs that needs to be searched. */ if (action == SEARCH_PRINT) - printf(" %d ( ", SCB_GET_TARGET(ahd, scb)); + printk(" %d ( ", SCB_GET_TARGET(ahd, scb)); tid_head = scbid; found += ahd_search_scb_list(ahd, target, channel, lun, tag, role, status, - action, &tid_head, + action, &tid_head, &tid_tail, SCB_GET_TARGET(ahd, scb)); + /* + * Check any MK_MESSAGE SCB that is still waiting to + * enter this target's waiting for selection queue. + */ + if (mk_msg_scb != NULL + && ahd_match_scb(ahd, mk_msg_scb, target, channel, + lun, tag, role)) { + + /* + * We found an scb that needs to be acted on. + */ + found++; + switch (action) { + case SEARCH_COMPLETE: + if ((mk_msg_scb->flags & SCB_ACTIVE) == 0) + printk("Inactive SCB pending MK_MSG\n"); + ahd_done_with_status(ahd, mk_msg_scb, status); + /* FALLTHROUGH */ + case SEARCH_REMOVE: + { + u_int tail_offset; + + printk("Removing MK_MSG scb\n"); + + /* + * Reset our tail to the tail of the + * main per-target list. + */ + tail_offset = WAITING_SCB_TAILS + + (2 * SCB_GET_TARGET(ahd, mk_msg_scb)); + ahd_outw(ahd, tail_offset, tid_tail); + + seq_flags2 &= ~PENDING_MK_MESSAGE; + ahd_outb(ahd, SEQ_FLAGS2, seq_flags2); + ahd_outw(ahd, CMDS_PENDING, + ahd_inw(ahd, CMDS_PENDING)-1); + mk_msg_scb = NULL; + break; + } + case SEARCH_PRINT: + printk(" 0x%x", SCB_GET_TAG(scb)); + /* FALLTHROUGH */ + case SEARCH_COUNT: + break; + } + } + + if (mk_msg_scb != NULL + && SCBID_IS_NULL(tid_head) + && ahd_match_scb(ahd, scb, target, channel, CAM_LUN_WILDCARD, + SCB_LIST_NULL, ROLE_UNKNOWN)) { + + /* + * When removing the last SCB for a target + * queue with a pending MK_MESSAGE scb, we + * must queue the MK_MESSAGE scb. + */ + printk("Queueing mk_msg_scb\n"); + tid_head = ahd_inw(ahd, MK_MESSAGE_SCB); + seq_flags2 &= ~PENDING_MK_MESSAGE; + ahd_outb(ahd, SEQ_FLAGS2, seq_flags2); + mk_msg_scb = NULL; + } if (tid_head != scbid) ahd_stitch_tid_list(ahd, tid_prev, tid_head, tid_next); if (!SCBID_IS_NULL(tid_head)) tid_prev = tid_head; if (action == SEARCH_PRINT) - printf(")\n"); + printk(")\n"); } + + /* Restore saved state. */ ahd_set_scbptr(ahd, savedscbptr); ahd_restore_modes(ahd, saved_modes); return (found); @@ -7461,7 +8426,8 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, static int ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, int lun, u_int tag, role_t role, uint32_t status, - ahd_search_action action, u_int *list_head, u_int tid) + ahd_search_action action, u_int *list_head, + u_int *list_tail, u_int tid) { struct scb *scb; u_int scbid; @@ -7469,13 +8435,14 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, u_int prev; int found; - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); + AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); found = 0; prev = SCB_LIST_NULL; next = *list_head; + *list_tail = SCB_LIST_NULL; for (scbid = next; !SCBID_IS_NULL(scbid); scbid = next) { if (scbid >= ahd->scb_data.numscbs) { - printf("%s:SCB List inconsistency. " + printk("%s:SCB List inconsistency. " "SCB == 0x%x, yet numscbs == 0x%x.", ahd_name(ahd), scbid, ahd->scb_data.numscbs); ahd_dump_card_state(ahd); @@ -7483,11 +8450,12 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, } scb = ahd_lookup_scb(ahd, scbid); if (scb == NULL) { - printf("%s: SCB = %d Not Active!\n", + printk("%s: SCB = %d Not Active!\n", ahd_name(ahd), scbid); panic("Waiting List traversal\n"); } ahd_set_scbptr(ahd, scbid); + *list_tail = scbid; next = ahd_inw_scbram(ahd, SCB_NEXT); if (ahd_match_scb(ahd, scb, target, channel, lun, SCB_LIST_NULL, role) == 0) { @@ -7497,28 +8465,18 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, found++; switch (action) { case SEARCH_COMPLETE: - { - cam_status ostat; - cam_status cstat; - - ostat = ahd_get_transaction_status(scb); - if (ostat == CAM_REQ_INPROG) - ahd_set_transaction_status(scb, status); - cstat = ahd_get_transaction_status(scb); - if (cstat != CAM_REQ_CMP) - ahd_freeze_scb(scb); if ((scb->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB in Waiting List\n"); - ahd_done(ahd, scb); + printk("Inactive SCB in Waiting List\n"); + ahd_done_with_status(ahd, scb, status); /* FALLTHROUGH */ - } case SEARCH_REMOVE: ahd_rem_wscb(ahd, scbid, prev, next, tid); - if (prev == SCB_LIST_NULL) + *list_tail = prev; + if (SCBID_IS_NULL(prev)) *list_head = next; break; case SEARCH_PRINT: - printf("0x%x ", scbid); + printk("0x%x ", scbid); case SEARCH_COUNT: prev = scbid; break; @@ -7536,7 +8494,7 @@ static void ahd_stitch_tid_list(struct ahd_softc *ahd, u_int tid_prev, u_int tid_cur, u_int tid_next) { - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); + AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); if (SCBID_IS_NULL(tid_cur)) { @@ -7576,21 +8534,24 @@ ahd_rem_wscb(struct ahd_softc *ahd, u_int scbid, { u_int tail_offset; - AHD_ASSERT_MODES(ahd, AHD_MODE_CCHAN_MSK, AHD_MODE_CCHAN_MSK); + AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); if (!SCBID_IS_NULL(prev)) { ahd_set_scbptr(ahd, prev); ahd_outw(ahd, SCB_NEXT, next); } /* - * SCBs that had MK_MESSAGE set in them will not - * be queued to the per-target lists, so don't - * blindly clear the tail pointer. + * SCBs that have MK_MESSAGE set in them may + * cause the tail pointer to be updated without + * setting the next pointer of the previous tail. + * Only clear the tail if the removed SCB was + * the tail. */ tail_offset = WAITING_SCB_TAILS + (2 * tid); if (SCBID_IS_NULL(next) && ahd_inw(ahd, tail_offset) == scbid) ahd_outw(ahd, tail_offset, prev); + ahd_add_scb_to_free_list(ahd, scbid); return (next); } @@ -7618,7 +8579,7 @@ ahd_add_scb_to_free_list(struct ahd_softc *ahd, u_int scbid) * been modified from CAM_REQ_INPROG. This routine assumes that the sequencer * is paused before it is called. */ -int +static int ahd_abort_scbs(struct ahd_softc *ahd, int target, char channel, int lun, u_int tag, role_t role, uint32_t status) { @@ -7703,7 +8664,7 @@ ahd_abort_scbs(struct ahd_softc *ahd, int target, char channel, if (ahd_get_transaction_status(scbp) != CAM_REQ_CMP) ahd_freeze_scb(scbp); if ((scbp->flags & SCB_ACTIVE) == 0) - printf("Inactive SCB on pending list\n"); + printk("Inactive SCB on pending list\n"); ahd_done(ahd, scbp); found++; } @@ -7747,17 +8708,28 @@ ahd_reset_current_bus(struct ahd_softc *ahd) int ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) { - struct ahd_devinfo devinfo; + struct ahd_devinfo caminfo; u_int initiator; u_int target; u_int max_scsiid; int found; u_int fifo; u_int next_fifo; + uint8_t scsiseq; + + /* + * Check if the last bus reset is cleared + */ + if (ahd->flags & AHD_BUS_RESET_ACTIVE) { + printk("%s: bus reset still active\n", + ahd_name(ahd)); + return 0; + } + ahd->flags |= AHD_BUS_RESET_ACTIVE; ahd->pending_device = NULL; - ahd_compile_devinfo(&devinfo, + ahd_compile_devinfo(&caminfo, CAM_TARGET_WILDCARD, CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD, @@ -7767,6 +8739,12 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) /* Make sure the sequencer is in a safe location. */ ahd_clear_critical_section(ahd); + /* + * Run our command complete fifos to ensure that we perform + * completion processing on any commands that 'completed' + * before the reset occurred. + */ + ahd_run_qoutfifo(ahd); #ifdef AHD_TARGET_MODE if ((ahd->flags & AHD_TARGETROLE) != 0) { ahd_run_tqinfifo(ahd, /*paused*/TRUE); @@ -7809,7 +8787,7 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) */ ahd_clear_msg_state(ahd); ahd_outb(ahd, SIMODE1, - ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST|ENBUSFREE)); + ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST)); if (initiate_reset) ahd_reset_current_bus(ahd); @@ -7831,30 +8809,19 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) ahd_clear_fifo(ahd, 1); /* - * Revert to async/narrow transfers until we renegotiate. + * Clear SCSI interrupt status */ - max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7; - for (target = 0; target <= max_scsiid; target++) { - - if (ahd->enabled_targets[target] == NULL) - continue; - for (initiator = 0; initiator <= max_scsiid; initiator++) { - struct ahd_devinfo devinfo; + ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI); - ahd_compile_devinfo(&devinfo, target, initiator, - CAM_LUN_WILDCARD, - 'A', ROLE_UNKNOWN); - ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, - AHD_TRANS_CUR, /*paused*/TRUE); - ahd_set_syncrate(ahd, &devinfo, /*period*/0, - /*offset*/0, /*ppr_options*/0, - AHD_TRANS_CUR, /*paused*/TRUE); - } - } + /* + * Reenable selections + */ + ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST); + scsiseq = ahd_inb(ahd, SCSISEQ_TEMPLATE); + ahd_outb(ahd, SCSISEQ1, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP)); -#ifdef AHD_TARGET_MODE max_scsiid = (ahd->features & AHD_WIDE) ? 15 : 7; - +#ifdef AHD_TARGET_MODE /* * Send an immediate notify ccb to all target more peripheral * drivers affected by this action. @@ -7879,82 +8846,44 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) } } #endif - /* Notify the XPT that a bus reset occurred */ - ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD, - CAM_LUN_WILDCARD, AC_BUS_RESET, NULL); - ahd_restart(ahd); /* - * Freeze the SIMQ until our poller can determine that - * the bus reset has really gone away. We set the initial - * timer to 0 to have the check performed as soon as possible - * from the timer context. + * Revert to async/narrow transfers until we renegotiate. */ - if ((ahd->flags & AHD_RESET_POLL_ACTIVE) == 0) { - ahd->flags |= AHD_RESET_POLL_ACTIVE; - ahd_freeze_simq(ahd); - ahd_timer_reset(&ahd->reset_timer, 0, ahd_reset_poll, ahd); - } - return (found); -} + for (target = 0; target <= max_scsiid; target++) { + if (ahd->enabled_targets[target] == NULL) + continue; + for (initiator = 0; initiator <= max_scsiid; initiator++) { + struct ahd_devinfo devinfo; -#define AHD_RESET_POLL_US 1000 -static void -ahd_reset_poll(void *arg) -{ - struct ahd_softc *ahd; - u_int scsiseq1; - u_long l; - u_long s; - - ahd_list_lock(&l); - ahd = ahd_find_softc((struct ahd_softc *)arg); - if (ahd == NULL) { - printf("ahd_reset_poll: Instance %p no longer exists\n", arg); - ahd_list_unlock(&l); - return; - } - ahd_lock(ahd, &s); - ahd_pause(ahd); - ahd_update_modes(ahd); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI); - if ((ahd_inb(ahd, SSTAT1) & SCSIRSTI) != 0) { - ahd_timer_reset(&ahd->reset_timer, AHD_RESET_POLL_US, - ahd_reset_poll, ahd); - ahd_unpause(ahd); - ahd_unlock(ahd, &s); - ahd_list_unlock(&l); - return; + ahd_compile_devinfo(&devinfo, target, initiator, + CAM_LUN_WILDCARD, + 'A', ROLE_UNKNOWN); + ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT, + AHD_TRANS_CUR, /*paused*/TRUE); + ahd_set_syncrate(ahd, &devinfo, /*period*/0, + /*offset*/0, /*ppr_options*/0, + AHD_TRANS_CUR, /*paused*/TRUE); + } } - /* Reset is now low. Complete chip reinitialization. */ - ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) | ENSCSIRST); - scsiseq1 = ahd_inb(ahd, SCSISEQ_TEMPLATE); - ahd_outb(ahd, SCSISEQ1, scsiseq1 & (ENSELI|ENRSELI|ENAUTOATNP)); - ahd_unpause(ahd); - ahd->flags &= ~AHD_RESET_POLL_ACTIVE; - ahd_unlock(ahd, &s); - ahd_release_simq(ahd); - ahd_list_unlock(&l); + /* Notify the XPT that a bus reset occurred */ + ahd_send_async(ahd, caminfo.channel, CAM_TARGET_WILDCARD, + CAM_LUN_WILDCARD, AC_BUS_RESET); + + ahd_restart(ahd); + + return (found); } /**************************** Statistics Processing ***************************/ static void ahd_stat_timer(void *arg) { - struct ahd_softc *ahd; - u_long l; + struct ahd_softc *ahd = arg; u_long s; int enint_coal; - ahd_list_lock(&l); - ahd = ahd_find_softc((struct ahd_softc *)arg); - if (ahd == NULL) { - printf("ahd_stat_timer: Instance %p no longer exists\n", arg); - ahd_list_unlock(&l); - return; - } ahd_lock(ahd, &s); enint_coal = ahd->hs_mailbox & ENINT_COALESCE; @@ -7967,7 +8896,7 @@ ahd_stat_timer(void *arg) ahd_enable_coalescing(ahd, enint_coal); #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_INT_COALESCING) != 0) - printf("%s: Interrupt coalescing " + printk("%s: Interrupt coalescing " "now %sabled. Cmds %d\n", ahd_name(ahd), (enint_coal & ENINT_COALESCE) ? "en" : "dis", @@ -7981,48 +8910,42 @@ ahd_stat_timer(void *arg) ahd_timer_reset(&ahd->stat_timer, AHD_STAT_UPDATE_US, ahd_stat_timer, ahd); ahd_unlock(ahd, &s); - ahd_list_unlock(&l); } /****************************** Status Processing *****************************/ -void -ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb) -{ - if (scb->hscb->shared_data.istatus.scsi_status != 0) { - ahd_handle_scsi_status(ahd, scb); - } else { - ahd_calc_residual(ahd, scb); - ahd_done(ahd, scb); - } -} -void +static void ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) { - struct hardware_scb *hscb; - u_int qfreeze_cnt; + struct hardware_scb *hscb; + int paused; /* * The sequencer freezes its select-out queue * anytime a SCSI status error occurs. We must - * handle the error and decrement the QFREEZE count - * to allow the sequencer to continue. + * handle the error and increment our qfreeze count + * to allow the sequencer to continue. We don't + * bother clearing critical sections here since all + * operations are on data structures that the sequencer + * is not touching once the queue is frozen. */ hscb = scb->hscb; + if (ahd_is_paused(ahd)) { + paused = 1; + } else { + paused = 0; + ahd_pause(ahd); + } + /* Freeze the queue until the client sees the error. */ ahd_freeze_devq(ahd, scb); ahd_freeze_scb(scb); - qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT); - if (qfreeze_cnt == 0) { - printf("%s: Bad status with 0 qfreeze count!\n", ahd_name(ahd)); - } else { - qfreeze_cnt--; - ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt); - } - if (qfreeze_cnt == 0) - ahd_outb(ahd, SEQ_FLAGS2, - ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN); + ahd->qfreeze_cnt++; + ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt); + + if (paused == 0) + ahd_unpause(ahd); /* Don't want to clobber the original sense code */ if ((scb->flags & SCB_SENSE) != 0) { @@ -8048,9 +8971,9 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_SENSE) != 0) { ahd_print_path(ahd, scb); - printf("SCB 0x%x Received PKT Status of 0x%x\n", + printk("SCB 0x%x Received PKT Status of 0x%x\n", SCB_GET_TAG(scb), siu->status); - printf("\tflags = 0x%x, sense len = 0x%x, " + printk("\tflags = 0x%x, sense len = 0x%x, " "pktfail = 0x%x\n", siu->flags, scsi_4btoul(siu->sense_length), scsi_4btoul(siu->pkt_failures_length)); @@ -8059,27 +8982,27 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) if ((siu->flags & SIU_RSPVALID) != 0) { ahd_print_path(ahd, scb); if (scsi_4btoul(siu->pkt_failures_length) < 4) { - printf("Unable to parse pkt_failures\n"); + printk("Unable to parse pkt_failures\n"); } else { switch (SIU_PKTFAIL_CODE(siu)) { case SIU_PFC_NONE: - printf("No packet failure found\n"); + printk("No packet failure found\n"); break; case SIU_PFC_CIU_FIELDS_INVALID: - printf("Invalid Command IU Field\n"); + printk("Invalid Command IU Field\n"); break; case SIU_PFC_TMF_NOT_SUPPORTED: - printf("TMF not supportd\n"); + printk("TMF not supported\n"); break; case SIU_PFC_TMF_FAILED: - printf("TMF failed\n"); + printk("TMF failed\n"); break; case SIU_PFC_INVALID_TYPE_CODE: - printf("Invalid L_Q Type code\n"); + printk("Invalid L_Q Type code\n"); break; case SIU_PFC_ILLEGAL_REQUEST: - printf("Illegal request\n"); + printk("Illegal request\n"); default: break; } @@ -8092,7 +9015,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) scb->flags |= SCB_PKT_SENSE; #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_SENSE) != 0) - printf("Sense data available\n"); + printk("Sense data available\n"); #endif } ahd_done(ahd, scb); @@ -8110,7 +9033,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_SENSE) { ahd_print_path(ahd, scb); - printf("SCB %d: requests Check Status\n", + printk("SCB %d: requests Check Status\n", SCB_GET_TAG(scb)); } #endif @@ -8138,7 +9061,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) #ifdef AHD_DEBUG if (ahd_debug & AHD_SHOW_SENSE) { ahd_print_path(ahd, scb); - printf("Sending Sense\n"); + printk("Sending Sense\n"); } #endif scb->sg_count = 0; @@ -8187,15 +9110,10 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) ahd_setup_data_scb(ahd, scb); scb->flags |= SCB_SENSE; ahd_queue_scb(ahd, scb); - /* - * Ensure we have enough time to actually - * retrieve the sense. - */ - ahd_scb_timer_reset(scb, 5 * 1000000); break; } case SCSI_STATUS_OK: - printf("%s: Interrupted for staus of 0???\n", + printk("%s: Interrupted for status of 0???\n", ahd_name(ahd)); /* FALLTHROUGH */ default: @@ -8204,10 +9122,21 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) } } +static void +ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb) +{ + if (scb->hscb->shared_data.istatus.scsi_status != 0) { + ahd_handle_scsi_status(ahd, scb); + } else { + ahd_calc_residual(ahd, scb); + ahd_done(ahd, scb); + } +} + /* * Calculate the residual for a just completed SCB. */ -void +static void ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb) { struct hardware_scb *hscb; @@ -8259,7 +9188,7 @@ ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb) return; } else if ((resid_sgptr & SG_OVERRUN_RESID) != 0) { ahd_print_path(ahd, scb); - printf("data overrun detected Tag == 0x%x.\n", + printk("data overrun detected Tag == 0x%x.\n", SCB_GET_TAG(scb)); ahd_freeze_devq(ahd, scb); ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR); @@ -8299,7 +9228,7 @@ ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb) #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_MISC) != 0) { ahd_print_path(ahd, scb); - printf("Handled %sResidual of %d bytes\n", + printk("Handled %sResidual of %d bytes\n", (scb->flags & SCB_SENSE) ? "Sense " : "", resid); } #endif @@ -8339,7 +9268,7 @@ ahd_queue_lstate_event(struct ahd_softc *ahd, struct ahd_tmode_lstate *lstate, if (pending == AHD_TMODE_EVENT_BUFFER_SIZE) { xpt_print_path(lstate->path); - printf("immediate event %x:%x lost\n", + printk("immediate event %x:%x lost\n", lstate->event_buffer[lstate->event_r_idx].event_type, lstate->event_buffer[lstate->event_r_idx].event_arg); lstate->event_r_idx++; @@ -8406,13 +9335,12 @@ ahd_dumpseq(struct ahd_softc* ahd) max_prog = 2048; ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); - ahd_outb(ahd, PRGMCNT, 0); - ahd_outb(ahd, PRGMCNT+1, 0); + ahd_outw(ahd, PRGMCNT, 0); for (i = 0; i < max_prog; i++) { uint8_t ins_bytes[4]; ahd_insb(ahd, SEQRAM, ins_bytes, 4); - printf("0x%08x\n", ins_bytes[0] << 24 + printk("0x%08x\n", ins_bytes[0] << 24 | ins_bytes[1] << 16 | ins_bytes[2] << 8 | ins_bytes[3]); @@ -8426,7 +9354,7 @@ ahd_loadseq(struct ahd_softc *ahd) struct cs cs_table[num_critical_sections]; u_int begin_set[num_critical_sections]; u_int end_set[num_critical_sections]; - struct patch *cur_patch; + const struct patch *cur_patch; u_int cs_count; u_int cur_cs; u_int i; @@ -8436,13 +9364,14 @@ ahd_loadseq(struct ahd_softc *ahd) u_int sg_prefetch_cnt_limit; u_int sg_prefetch_align; u_int sg_size; + u_int cacheline_mask; uint8_t download_consts[DOWNLOAD_CONST_COUNT]; if (bootverbose) - printf("%s: Downloading Sequencer Program...", + printk("%s: Downloading Sequencer Program...", ahd_name(ahd)); -#if DOWNLOAD_CONST_COUNT != 7 +#if DOWNLOAD_CONST_COUNT != 8 #error "Download Const Mismatch" #endif /* @@ -8478,6 +9407,9 @@ ahd_loadseq(struct ahd_softc *ahd) /* Round down to the nearest power of 2. */ while (powerof2(sg_prefetch_align) == 0) sg_prefetch_align--; + + cacheline_mask = sg_prefetch_align - 1; + /* * If the cacheline boundary is greater than half our prefetch RAM * we risk not being able to fetch even a single complete S/G @@ -8518,12 +9450,12 @@ ahd_loadseq(struct ahd_softc *ahd) download_consts[PKT_OVERRUN_BUFOFFSET] = (ahd->overrun_buf - (uint8_t *)ahd->qoutfifo) / 256; download_consts[SCB_TRANSFER_SIZE] = SCB_TRANSFER_SIZE_1BYTE_LUN; + download_consts[CACHELINE_MASK] = cacheline_mask; cur_patch = patches; downloaded = 0; skip_addr = 0; ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE|LOADRAM); - ahd_outb(ahd, PRGMCNT, 0); - ahd_outb(ahd, PRGMCNT+1, 0); + ahd_outw(ahd, PRGMCNT, 0); for (i = 0; i < sizeof(seqprog)/4; i++) { if (ahd_check_patch(ahd, &cur_patch, i, &skip_addr) == 0) { @@ -8562,7 +9494,7 @@ ahd_loadseq(struct ahd_softc *ahd) if (cs_count != 0) { cs_count *= sizeof(struct cs); - ahd->critical_sections = malloc(cs_count, M_DEVBUF, M_NOWAIT); + ahd->critical_sections = kmalloc(cs_count, GFP_ATOMIC); if (ahd->critical_sections == NULL) panic("ahd_loadseq: Could not malloc"); memcpy(ahd->critical_sections, cs_table, cs_count); @@ -8570,21 +9502,21 @@ ahd_loadseq(struct ahd_softc *ahd) ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS|FASTMODE); if (bootverbose) { - printf(" %d instructions downloaded\n", downloaded); - printf("%s: Features 0x%x, Bugs 0x%x, Flags 0x%x\n", + printk(" %d instructions downloaded\n", downloaded); + printk("%s: Features 0x%x, Bugs 0x%x, Flags 0x%x\n", ahd_name(ahd), ahd->features, ahd->bugs, ahd->flags); } } static int -ahd_check_patch(struct ahd_softc *ahd, struct patch **start_patch, +ahd_check_patch(struct ahd_softc *ahd, const struct patch **start_patch, u_int start_instr, u_int *skip_addr) { - struct patch *cur_patch; - struct patch *last_patch; + const struct patch *cur_patch; + const struct patch *last_patch; u_int num_patches; - num_patches = sizeof(patches)/sizeof(struct patch); + num_patches = ARRAY_SIZE(patches); last_patch = &patches[num_patches]; cur_patch = *start_patch; @@ -8615,7 +9547,7 @@ ahd_check_patch(struct ahd_softc *ahd, struct patch **start_patch, static u_int ahd_resolve_seqaddr(struct ahd_softc *ahd, u_int address) { - struct patch *cur_patch; + const struct patch *cur_patch; int address_offset; u_int skip_addr; u_int i; @@ -8631,7 +9563,7 @@ ahd_resolve_seqaddr(struct ahd_softc *ahd, u_int address) if (skip_addr > i) { int end_addr; - end_addr = MIN(address, skip_addr); + end_addr = min(address, skip_addr); address_offset += end_addr - i; i = skip_addr; } else { @@ -8745,18 +9677,8 @@ sized: return (last_probe); } -void -ahd_dump_all_cards_state(void) -{ - struct ahd_softc *list_ahd; - - TAILQ_FOREACH(list_ahd, &ahd_tailq, links) { - ahd_dump_card_state(list_ahd); - } -} - int -ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries, +ahd_print_register(const ahd_reg_parse_entry_t *table, u_int num_entries, const char *name, u_int address, u_int value, u_int *cur_column, u_int wrap_point) { @@ -8764,12 +9686,12 @@ ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries, u_int printed_mask; if (cur_column != NULL && *cur_column >= wrap_point) { - printf("\n"); + printk("\n"); *cur_column = 0; } - printed = printf("%s[0x%x]", name, value); + printed = printk("%s[0x%x]", name, value); if (table == NULL) { - printed += printf(" "); + printed += printk(" "); *cur_column += printed; return (printed); } @@ -8784,7 +9706,7 @@ ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries, == table[entry].mask)) continue; - printed += printf("%s%s", + printed += printk("%s%s", printed_mask == 0 ? ":(" : "|", table[entry].name); printed_mask |= table[entry].mask; @@ -8795,9 +9717,9 @@ ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries, break; } if (printed_mask != 0) - printed += printf(") "); + printed += printk(") "); else - printed += printf(" "); + printed += printk(" "); if (cur_column != NULL) *cur_column += printed; return (printed); @@ -8823,22 +9745,25 @@ ahd_dump_card_state(struct ahd_softc *ahd) } saved_modes = ahd_save_modes(ahd); ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); - printf(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n" + printk(">>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<\n" "%s: Dumping Card State at program address 0x%x Mode 0x%x\n", ahd_name(ahd), - ahd_inb(ahd, CURADDR) | (ahd_inb(ahd, CURADDR+1) << 8), + ahd_inw(ahd, CURADDR), ahd_build_mode_state(ahd, ahd->saved_src_mode, ahd->saved_dst_mode)); if (paused) - printf("Card was paused\n"); + printk("Card was paused\n"); if (ahd_check_cmdcmpltqueues(ahd)) - printf("Completions are pending\n"); + printk("Completions are pending\n"); /* * Mode independent registers. */ cur_col = 0; + ahd_intstat_print(ahd_inb(ahd, INTSTAT), &cur_col, 50); + ahd_seloid_print(ahd_inb(ahd, SELOID), &cur_col, 50); + ahd_selid_print(ahd_inb(ahd, SELID), &cur_col, 50); ahd_hs_mailbox_print(ahd_inb(ahd, LOCAL_HS_MAILBOX), &cur_col, 50); ahd_intctl_print(ahd_inb(ahd, INTCTL), &cur_col, 50); ahd_seqintstat_print(ahd_inb(ahd, SEQINTSTAT), &cur_col, 50); @@ -8854,6 +9779,12 @@ ahd_dump_card_state(struct ahd_softc *ahd) ahd_seqintctl_print(ahd_inb(ahd, SEQINTCTL), &cur_col, 50); ahd_seq_flags_print(ahd_inb(ahd, SEQ_FLAGS), &cur_col, 50); ahd_seq_flags2_print(ahd_inb(ahd, SEQ_FLAGS2), &cur_col, 50); + ahd_qfreeze_count_print(ahd_inw(ahd, QFREEZE_COUNT), &cur_col, 50); + ahd_kernel_qfreeze_count_print(ahd_inw(ahd, KERNEL_QFREEZE_COUNT), + &cur_col, 50); + ahd_mk_message_scb_print(ahd_inw(ahd, MK_MESSAGE_SCB), &cur_col, 50); + ahd_mk_message_scsiid_print(ahd_inb(ahd, MK_MESSAGE_SCSIID), + &cur_col, 50); ahd_sstat0_print(ahd_inb(ahd, SSTAT0), &cur_col, 50); ahd_sstat1_print(ahd_inb(ahd, SSTAT1), &cur_col, 50); ahd_sstat2_print(ahd_inb(ahd, SSTAT2), &cur_col, 50); @@ -8866,8 +9797,8 @@ ahd_dump_card_state(struct ahd_softc *ahd) ahd_lqostat0_print(ahd_inb(ahd, LQOSTAT0), &cur_col, 50); ahd_lqostat1_print(ahd_inb(ahd, LQOSTAT1), &cur_col, 50); ahd_lqostat2_print(ahd_inb(ahd, LQOSTAT2), &cur_col, 50); - printf("\n"); - printf("\nSCB Count = %d CMDS_PENDING = %d LASTSCB 0x%x " + printk("\n"); + printk("\nSCB Count = %d CMDS_PENDING = %d LASTSCB 0x%x " "CURRSCB 0x%x NEXTSCB 0x%x\n", ahd->scb_data.numscbs, ahd_inw(ahd, CMDS_PENDING), ahd_inw(ahd, LASTSCB), ahd_inw(ahd, CURRSCB), @@ -8878,12 +9809,12 @@ ahd_dump_card_state(struct ahd_softc *ahd) CAM_LUN_WILDCARD, SCB_LIST_NULL, ROLE_UNKNOWN, /*status*/0, SEARCH_PRINT); saved_scb_index = ahd_get_scbptr(ahd); - printf("Pending list:"); + printk("Pending list:"); i = 0; LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) { if (i++ > AHD_SCB_MAX) break; - cur_col = printf("\n%3d FIFO_USE[0x%x] ", SCB_GET_TAG(scb), + cur_col = printk("\n%3d FIFO_USE[0x%x] ", SCB_GET_TAG(scb), ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT)); ahd_set_scbptr(ahd, SCB_GET_TAG(scb)); ahd_scb_control_print(ahd_inb_scbram(ahd, SCB_CONTROL), @@ -8891,16 +9822,16 @@ ahd_dump_card_state(struct ahd_softc *ahd) ahd_scb_scsiid_print(ahd_inb_scbram(ahd, SCB_SCSIID), &cur_col, 60); } - printf("\nTotal %d\n", i); + printk("\nTotal %d\n", i); - printf("Kernel Free SCB list: "); + printk("Kernel Free SCB list: "); i = 0; TAILQ_FOREACH(scb, &ahd->scb_data.free_scbs, links.tqe) { struct scb *list_scb; list_scb = scb; do { - printf("%d ", SCB_GET_TAG(list_scb)); + printk("%d ", SCB_GET_TAG(list_scb)); list_scb = LIST_NEXT(list_scb, collision_links); } while (list_scb && i++ < AHD_SCB_MAX); } @@ -8908,40 +9839,49 @@ ahd_dump_card_state(struct ahd_softc *ahd) LIST_FOREACH(scb, &ahd->scb_data.any_dev_free_scb_list, links.le) { if (i++ > AHD_SCB_MAX) break; - printf("%d ", SCB_GET_TAG(scb)); + printk("%d ", SCB_GET_TAG(scb)); } - printf("\n"); + printk("\n"); - printf("Sequencer Complete DMA-inprog list: "); + printk("Sequencer Complete DMA-inprog list: "); scb_index = ahd_inw(ahd, COMPLETE_SCB_DMAINPROG_HEAD); i = 0; while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) { ahd_set_scbptr(ahd, scb_index); - printf("%d ", scb_index); + printk("%d ", scb_index); scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); } - printf("\n"); + printk("\n"); - printf("Sequencer Complete list: "); + printk("Sequencer Complete list: "); scb_index = ahd_inw(ahd, COMPLETE_SCB_HEAD); i = 0; while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) { ahd_set_scbptr(ahd, scb_index); - printf("%d ", scb_index); + printk("%d ", scb_index); scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); } - printf("\n"); + printk("\n"); - printf("Sequencer DMA-Up and Complete list: "); + printk("Sequencer DMA-Up and Complete list: "); scb_index = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD); i = 0; while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) { ahd_set_scbptr(ahd, scb_index); - printf("%d ", scb_index); + printk("%d ", scb_index); scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); } - printf("\n"); + printk("\n"); + printk("Sequencer On QFreeze and Complete list: "); + scb_index = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD); + i = 0; + while (!SCBID_IS_NULL(scb_index) && i++ < AHD_SCB_MAX) { + ahd_set_scbptr(ahd, scb_index); + printk("%d ", scb_index); + scb_index = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE); + } + printk("\n"); ahd_set_scbptr(ahd, saved_scb_index); dffstat = ahd_inb(ahd, DFFSTAT); for (i = 0; i < 2; i++) { @@ -8952,7 +9892,7 @@ ahd_dump_card_state(struct ahd_softc *ahd) ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i); fifo_scbptr = ahd_get_scbptr(ahd); - printf("\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n", + printk("\n\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n", ahd_name(ahd), i, (dffstat & (FIFO0FREE << i)) ? "Free" : "Active", ahd_inw(ahd, LONGJMP_ADDR), fifo_scbptr); @@ -8968,20 +9908,20 @@ ahd_dump_card_state(struct ahd_softc *ahd) ahd_soffcnt_print(ahd_inb(ahd, SOFFCNT), &cur_col, 50); ahd_mdffstat_print(ahd_inb(ahd, MDFFSTAT), &cur_col, 50); if (cur_col > 50) { - printf("\n"); + printk("\n"); cur_col = 0; } - cur_col += printf("SHADDR = 0x%x%x, SHCNT = 0x%x ", + cur_col += printk("SHADDR = 0x%x%x, SHCNT = 0x%x ", ahd_inl(ahd, SHADDR+4), ahd_inl(ahd, SHADDR), (ahd_inb(ahd, SHCNT) | (ahd_inb(ahd, SHCNT + 1) << 8) | (ahd_inb(ahd, SHCNT + 2) << 16))); if (cur_col > 50) { - printf("\n"); + printk("\n"); cur_col = 0; } - cur_col += printf("HADDR = 0x%x%x, HCNT = 0x%x ", + cur_col += printk("HADDR = 0x%x%x, HCNT = 0x%x ", ahd_inl(ahd, HADDR+4), ahd_inl(ahd, HADDR), (ahd_inb(ahd, HCNT) @@ -8996,55 +9936,58 @@ ahd_dump_card_state(struct ahd_softc *ahd) } #endif } - printf("\nLQIN: "); + printk("\nLQIN: "); for (i = 0; i < 20; i++) - printf("0x%x ", ahd_inb(ahd, LQIN + i)); - printf("\n"); + printk("0x%x ", ahd_inb(ahd, LQIN + i)); + printk("\n"); ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); - printf("%s: LQISTATE = 0x%x, LQOSTATE = 0x%x, OPTIONMODE = 0x%x\n", + printk("%s: LQISTATE = 0x%x, LQOSTATE = 0x%x, OPTIONMODE = 0x%x\n", ahd_name(ahd), ahd_inb(ahd, LQISTATE), ahd_inb(ahd, LQOSTATE), ahd_inb(ahd, OPTIONMODE)); - printf("%s: OS_SPACE_CNT = 0x%x MAXCMDCNT = 0x%x\n", + printk("%s: OS_SPACE_CNT = 0x%x MAXCMDCNT = 0x%x\n", ahd_name(ahd), ahd_inb(ahd, OS_SPACE_CNT), ahd_inb(ahd, MAXCMDCNT)); + printk("%s: SAVED_SCSIID = 0x%x SAVED_LUN = 0x%x\n", + ahd_name(ahd), ahd_inb(ahd, SAVED_SCSIID), + ahd_inb(ahd, SAVED_LUN)); ahd_simode0_print(ahd_inb(ahd, SIMODE0), &cur_col, 50); - printf("\n"); + printk("\n"); ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN); cur_col = 0; ahd_ccscbctl_print(ahd_inb(ahd, CCSCBCTL), &cur_col, 50); - printf("\n"); + printk("\n"); ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode); - printf("%s: REG0 == 0x%x, SINDEX = 0x%x, DINDEX = 0x%x\n", + printk("%s: REG0 == 0x%x, SINDEX = 0x%x, DINDEX = 0x%x\n", ahd_name(ahd), ahd_inw(ahd, REG0), ahd_inw(ahd, SINDEX), ahd_inw(ahd, DINDEX)); - printf("%s: SCBPTR == 0x%x, SCB_NEXT == 0x%x, SCB_NEXT2 == 0x%x\n", + printk("%s: SCBPTR == 0x%x, SCB_NEXT == 0x%x, SCB_NEXT2 == 0x%x\n", ahd_name(ahd), ahd_get_scbptr(ahd), ahd_inw_scbram(ahd, SCB_NEXT), ahd_inw_scbram(ahd, SCB_NEXT2)); - printf("CDB %x %x %x %x %x %x\n", + printk("CDB %x %x %x %x %x %x\n", ahd_inb_scbram(ahd, SCB_CDB_STORE), ahd_inb_scbram(ahd, SCB_CDB_STORE+1), ahd_inb_scbram(ahd, SCB_CDB_STORE+2), ahd_inb_scbram(ahd, SCB_CDB_STORE+3), ahd_inb_scbram(ahd, SCB_CDB_STORE+4), ahd_inb_scbram(ahd, SCB_CDB_STORE+5)); - printf("STACK:"); + printk("STACK:"); for (i = 0; i < ahd->stack_size; i++) { ahd->saved_stack[i] = ahd_inb(ahd, STACK)|(ahd_inb(ahd, STACK) << 8); - printf(" 0x%x", ahd->saved_stack[i]); + printk(" 0x%x", ahd->saved_stack[i]); } for (i = ahd->stack_size-1; i >= 0; i--) { ahd_outb(ahd, STACK, ahd->saved_stack[i] & 0xFF); ahd_outb(ahd, STACK, (ahd->saved_stack[i] >> 8) & 0xFF); } - printf("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n"); - ahd_platform_dump_card_state(ahd); + printk("\n<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>\n"); ahd_restore_modes(ahd, saved_modes); if (paused == 0) ahd_unpause(ahd); } +#if 0 void ahd_dump_scbs(struct ahd_softc *ahd) { @@ -9057,8 +10000,8 @@ ahd_dump_scbs(struct ahd_softc *ahd) saved_scb_index = ahd_get_scbptr(ahd); for (i = 0; i < AHD_SCB_MAX; i++) { ahd_set_scbptr(ahd, i); - printf("%3d", i); - printf("(CTRL 0x%x ID 0x%x N 0x%x N2 0x%x SG 0x%x, RSG 0x%x)\n", + printk("%3d", i); + printk("(CTRL 0x%x ID 0x%x N 0x%x N2 0x%x SG 0x%x, RSG 0x%x)\n", ahd_inb_scbram(ahd, SCB_CONTROL), ahd_inb_scbram(ahd, SCB_SCSIID), ahd_inw_scbram(ahd, SCB_NEXT), @@ -9066,10 +10009,11 @@ ahd_dump_scbs(struct ahd_softc *ahd) ahd_inl_scbram(ahd, SCB_SGPTR), ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR)); } - printf("\n"); + printk("\n"); ahd_set_scbptr(ahd, saved_scb_index); ahd_restore_modes(ahd, saved_modes); } +#endif /* 0 */ /**************************** Flexport Logic **********************************/ /* @@ -9143,7 +10087,7 @@ ahd_write_seeprom(struct ahd_softc *ahd, uint16_t *buf, return (error); /* - * Write the data. If we don't get throught the loop at + * Write the data. If we don't get through the loop at * least once, the arguments were invalid. */ retval = EINVAL; @@ -9172,12 +10116,12 @@ ahd_write_seeprom(struct ahd_softc *ahd, uint16_t *buf, /* * Wait ~100us for the serial eeprom to satisfy our request. */ -int +static int ahd_wait_seeprom(struct ahd_softc *ahd) { int cnt; - cnt = 20; + cnt = 5000; while ((ahd_inb(ahd, SEESTAT) & (SEEARBACK|SEEBUSY)) != 0 && --cnt) ahd_delay(5); @@ -9190,7 +10134,7 @@ ahd_wait_seeprom(struct ahd_softc *ahd) * Validate the two checksums in the per_channel * vital product data struct. */ -int +static int ahd_verify_vpd_cksum(struct vpd_config *vpd) { int i; @@ -9269,6 +10213,24 @@ ahd_release_seeprom(struct ahd_softc *ahd) /* Currently a no-op */ } +/* + * Wait at most 2 seconds for flexport arbitration to succeed. + */ +static int +ahd_wait_flexport(struct ahd_softc *ahd) +{ + int cnt; + + AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); + cnt = 1000000 * 2 / 5; + while ((ahd_inb(ahd, BRDCTL) & FLXARBACK) == 0 && --cnt) + ahd_delay(5); + + if (cnt == 0) + return (ETIMEDOUT); + return (0); +} + int ahd_write_flexport(struct ahd_softc *ahd, u_int addr, u_int value) { @@ -9310,24 +10272,6 @@ ahd_read_flexport(struct ahd_softc *ahd, u_int addr, uint8_t *value) return (0); } -/* - * Wait at most 2 seconds for flexport arbitration to succeed. - */ -int -ahd_wait_flexport(struct ahd_softc *ahd) -{ - int cnt; - - AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); - cnt = 1000000 * 2 / 5; - while ((ahd_inb(ahd, BRDCTL) & FLXARBACK) == 0 && --cnt) - ahd_delay(5); - - if (cnt == 0) - return (ETIMEDOUT); - return (0); -} - /************************* Target Mode ****************************************/ #ifdef AHD_TARGET_MODE cam_status @@ -9351,8 +10295,8 @@ ahd_find_tmode_devs(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb, } else { u_int max_id; - max_id = (ahd->features & AHD_WIDE) ? 15 : 7; - if (ccb->ccb_h.target_id > max_id) + max_id = (ahd->features & AHD_WIDE) ? 16 : 8; + if (ccb->ccb_h.target_id >= max_id) return (CAM_TID_INVALID); if (ccb->ccb_h.target_lun >= AHD_NUM_LUNS) @@ -9435,7 +10379,7 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) && ccb->ccb_h.target_id != CAM_TARGET_WILDCARD) { u_long s; - printf("Configuring Target Mode\n"); + printk("Configuring Target Mode\n"); ahd_lock(ahd, &s); if (LIST_FIRST(&ahd->pending_scbs) != NULL) { ccb->ccb_h.status = CAM_BUSY; @@ -9464,7 +10408,7 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) /* Are we already enabled?? */ if (lstate != NULL) { xpt_print_path(ccb->ccb_h.path); - printf("Lun already enabled\n"); + printk("Lun already enabled\n"); ccb->ccb_h.status = CAM_LUN_ALRDY_ENA; return; } @@ -9476,7 +10420,7 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) * specific commands. */ ccb->ccb_h.status = CAM_REQ_INVALID; - printf("Non-zero Group Codes\n"); + printk("Non-zero Group Codes\n"); return; } @@ -9488,15 +10432,15 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) tstate = ahd_alloc_tstate(ahd, target, channel); if (tstate == NULL) { xpt_print_path(ccb->ccb_h.path); - printf("Couldn't allocate tstate\n"); + printk("Couldn't allocate tstate\n"); ccb->ccb_h.status = CAM_RESRC_UNAVAIL; return; } } - lstate = malloc(sizeof(*lstate), M_DEVBUF, M_NOWAIT); + lstate = kmalloc(sizeof(*lstate), GFP_ATOMIC); if (lstate == NULL) { xpt_print_path(ccb->ccb_h.path); - printf("Couldn't allocate lstate\n"); + printk("Couldn't allocate lstate\n"); ccb->ccb_h.status = CAM_RESRC_UNAVAIL; return; } @@ -9506,9 +10450,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) xpt_path_target_id(ccb->ccb_h.path), xpt_path_lun_id(ccb->ccb_h.path)); if (status != CAM_REQ_CMP) { - free(lstate, M_DEVBUF); + kfree(lstate); xpt_print_path(ccb->ccb_h.path); - printf("Couldn't allocate path\n"); + printk("Couldn't allocate path\n"); ccb->ccb_h.status = CAM_RESRC_UNAVAIL; return; } @@ -9523,13 +10467,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) if ((ahd->features & AHD_MULTI_TID) != 0) { u_int targid_mask; - targid_mask = ahd_inb(ahd, TARGID) - | (ahd_inb(ahd, TARGID + 1) << 8); - + targid_mask = ahd_inw(ahd, TARGID); targid_mask |= target_mask; - ahd_outb(ahd, TARGID, targid_mask); - ahd_outb(ahd, TARGID+1, (targid_mask >> 8)); - + ahd_outw(ahd, TARGID, targid_mask); ahd_update_scsiid(ahd, targid_mask); } else { u_int our_id; @@ -9580,7 +10520,7 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) ahd_unlock(ahd, &s); ccb->ccb_h.status = CAM_REQ_CMP; xpt_print_path(ccb->ccb_h.path); - printf("Lun now enabled for target mode\n"); + printk("Lun now enabled for target mode\n"); } else { struct scb *scb; int i, empty; @@ -9599,7 +10539,7 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) ccbh = &scb->io_ctx->ccb_h; if (ccbh->func_code == XPT_CONT_TARGET_IO && !xpt_path_comp(ccbh->path, ccb->ccb_h.path)){ - printf("CTIO pending\n"); + printk("CTIO pending\n"); ccb->ccb_h.status = CAM_REQ_INVALID; ahd_unlock(ahd, &s); return; @@ -9607,12 +10547,12 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) } if (SLIST_FIRST(&lstate->accept_tios) != NULL) { - printf("ATIOs pending\n"); + printk("ATIOs pending\n"); ccb->ccb_h.status = CAM_REQ_INVALID; } if (SLIST_FIRST(&lstate->immed_notifies) != NULL) { - printf("INOTs pending\n"); + printk("INOTs pending\n"); ccb->ccb_h.status = CAM_REQ_INVALID; } @@ -9622,9 +10562,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) } xpt_print_path(ccb->ccb_h.path); - printf("Target mode disabled\n"); + printk("Target mode disabled\n"); xpt_free_path(lstate->path); - free(lstate, M_DEVBUF); + kfree(lstate); ahd_pause(ahd); /* Can we clean up the target too? */ @@ -9643,14 +10583,9 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) if (ahd->features & AHD_MULTI_TID) { u_int targid_mask; - targid_mask = ahd_inb(ahd, TARGID) - | (ahd_inb(ahd, TARGID + 1) - << 8); - + targid_mask = ahd_inw(ahd, TARGID); targid_mask &= ~target_mask; - ahd_outb(ahd, TARGID, targid_mask); - ahd_outb(ahd, TARGID+1, - (targid_mask >> 8)); + ahd_outw(ahd, TARGID, targid_mask); ahd_update_scsiid(ahd, targid_mask); } } @@ -9676,7 +10611,7 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) ahd_outb(ahd, SCSISEQ1, scsiseq1); if ((ahd->features & AHD_MULTIROLE) == 0) { - printf("Configuring Initiator Mode\n"); + printk("Configuring Initiator Mode\n"); ahd->flags &= ~AHD_TARGETROLE; ahd->flags |= AHD_INITIATORROLE; ahd_pause(ahd); @@ -9734,7 +10669,7 @@ ahd_update_scsiid(struct ahd_softc *ahd, u_int targid_mask) #endif } -void +static void ahd_run_tqinfifo(struct ahd_softc *ahd, int paused) { struct target_cmd *cmd; @@ -9751,7 +10686,7 @@ ahd_run_tqinfifo(struct ahd_softc *ahd, int paused) cmd->cmd_valid = 0; ahd_dmamap_sync(ahd, ahd->shared_data_dmat, - ahd->shared_data_dmamap, + ahd->shared_data_map.dmamap, ahd_targetcmd_offset(ahd, ahd->tqinfifonext), sizeof(struct target_cmd), BUS_DMASYNC_PREREAD); @@ -9810,7 +10745,7 @@ ahd_handle_target_cmd(struct ahd_softc *ahd, struct target_cmd *cmd) ahd->flags &= ~AHD_TQINFIFO_BLOCKED; #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_TQIN) != 0) - printf("Incoming command from %d for %d:%d%s\n", + printk("Incoming command from %d for %d:%d%s\n", initiator, target, lun, lstate == ahd->black_hole ? "(Black Holed)" : ""); #endif @@ -9857,7 +10792,7 @@ ahd_handle_target_cmd(struct ahd_softc *ahd, struct target_cmd *cmd) default: /* Only copy the opcode. */ atio->cdb_len = 1; - printf("Reserved or VU command code type encountered\n"); + printk("Reserved or VU command code type encountered\n"); break; } @@ -9874,7 +10809,7 @@ ahd_handle_target_cmd(struct ahd_softc *ahd, struct target_cmd *cmd) */ #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_TQIN) != 0) - printf("Received Immediate Command %d:%d:%d - %p\n", + printk("Received Immediate Command %d:%d:%d - %p\n", initiator, target, lun, ahd->pending_device); #endif ahd->pending_device = lstate; |
