⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aic79xx_core.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
		for (i = 0; i < ahd->num_critical_sections; i++, cs++) {						if (cs->begin < seqaddr && cs->end >= seqaddr)				break;		}		if (i == ahd->num_critical_sections)			break;		if (steps > AHD_MAX_STEPS) {			printf("%s: Infinite loop in critical section\n",			       ahd_name(ahd));			ahd_dump_card_state(ahd);			panic("critical section loop");		}		steps++;		if (stepping == FALSE) {			/*			 * Disable all interrupt sources so that the			 * sequencer will not be stuck by a pausing			 * interrupt condition while we attempt to			 * leave a critical section.			 */			ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);			simode0 = ahd_inb(ahd, SIMODE0);			simode3 = ahd_inb(ahd, SIMODE3);			lqimode0 = ahd_inb(ahd, LQIMODE0);			lqimode1 = ahd_inb(ahd, LQIMODE1);			lqomode0 = ahd_inb(ahd, LQOMODE0);			lqomode1 = ahd_inb(ahd, LQOMODE1);			ahd_outb(ahd, SIMODE0, 0);			ahd_outb(ahd, SIMODE3, 0);			ahd_outb(ahd, LQIMODE0, 0);			ahd_outb(ahd, LQIMODE1, 0);			ahd_outb(ahd, LQOMODE0, 0);			ahd_outb(ahd, LQOMODE1, 0);			ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);			simode1 = ahd_inb(ahd, SIMODE1);			ahd_outb(ahd, SIMODE1, 0);			ahd_outb(ahd, CLRINT, CLRSCSIINT);			ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) | STEP);			stepping = TRUE;		}		ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode);		ahd_outb(ahd, HCNTRL, ahd->unpause);		do {			ahd_delay(200);		} while (!ahd_is_paused(ahd));		ahd_update_modes(ahd);	}	if (stepping) {		ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);		ahd_outb(ahd, SIMODE0, simode0);		ahd_outb(ahd, SIMODE3, simode3);		ahd_outb(ahd, LQIMODE0, lqimode0);		ahd_outb(ahd, LQIMODE1, lqimode1);		ahd_outb(ahd, LQOMODE0, lqomode0);		ahd_outb(ahd, LQOMODE1, lqomode1);		ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);		ahd_outb(ahd, SIMODE1, simode1);		ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) & ~STEP);	}	ahd_restore_modes(ahd, saved_modes);}/* * Clear any pending interrupt status. */voidahd_clear_intstat(struct ahd_softc *ahd){	/* Clear any interrupt conditions this may have caused */	ahd_outb(ahd, CLRSINT1, CLRSELTIMEO|CLRATNO|CLRSCSIRSTI				|CLRBUSFREE|CLRSCSIPERR|CLRREQINIT);	ahd_outb(ahd, CLRSINT0, CLRSELDO|CLRSELDI|CLRSELINGO|CLRIOERR);	ahd_outb(ahd, CLRINT, CLRSCSIINT);}/**************************** Debugging Routines ******************************/#ifdef AHD_DEBUGuint32_t ahd_debug = AHD_DEBUG;#endifvoidahd_print_scb(struct scb *scb){	struct hardware_scb *hscb;	int i;	hscb = scb->hscb;	printf("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: ");	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",	       (uint32_t)((ahd_le64toh(hscb->dataptr) >> 32) & 0xFFFFFFFF),	       (uint32_t)(ahd_le64toh(hscb->dataptr) & 0xFFFFFFFF),	       ahd_le32toh(hscb->datacnt),	       ahd_le32toh(hscb->sgptr),	       SCB_GET_TAG(scb));	ahd_dump_sglist(scb);}voidahd_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;				addr = ahd_le64toh(sg_list[i].addr);				printf("sg[%d] - Addr 0x%x%x : Length %d\n",				       i,				       (uint32_t)((addr >> 32) & 0xFFFFFFFF),				       (uint32_t)(addr & 0xFFFFFFFF),				       ahd_le32toh(sg_list[i].len));			}		} else {			struct ahd_dma_seg *sg_list;			sg_list = (struct ahd_dma_seg*)scb->sg_list;			for (i = 0; i < scb->sg_count; i++) {				printf("sg[%d] - Addr 0x%x%x : Length %d\n",				       i,				       (ahd_le32toh(sg_list[i].len) >> 24				        & SG_HIGH_ADDR_BITS),				       ahd_le32toh(sg_list[i].addr),				       ahd_le32toh(sg_list[i].len)				       & AHD_SG_LEN_MASK);			}		}	}}/************************* Transfer Negotiation *******************************//* * Allocate per target mode instance (ID we respond to as a target) * transfer negotiation data structures. */static struct ahd_tmode_tstate *ahd_alloc_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel){	struct ahd_tmode_tstate *master_tstate;	struct ahd_tmode_tstate *tstate;	int i;	master_tstate = ahd->enabled_targets[ahd->our_id];	if (ahd->enabled_targets[scsi_id] != NULL	 && 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);	if (tstate == NULL)		return (NULL);	/*	 * If we have allocated a master tstate, copy user settings from	 * the master tstate (taken from SRAM or the EEPROM) for this	 * channel, but reset our current and goal settings to async/narrow	 * until an initiator talks to us.	 */	if (master_tstate != NULL) {		memcpy(tstate, master_tstate, sizeof(*tstate));		memset(tstate->enabled_luns, 0, sizeof(tstate->enabled_luns));		for (i = 0; i < 16; i++) {			memset(&tstate->transinfo[i].curr, 0,			      sizeof(tstate->transinfo[i].curr));			memset(&tstate->transinfo[i].goal, 0,			      sizeof(tstate->transinfo[i].goal));		}	} else		memset(tstate, 0, sizeof(*tstate));	ahd->enabled_targets[scsi_id] = tstate;	return (tstate);}#ifdef AHD_TARGET_MODE/* * Free per target mode instance (ID we respond to as a target) * transfer negotiation data structures. */static voidahd_free_tstate(struct ahd_softc *ahd, u_int scsi_id, char channel, int force){	struct ahd_tmode_tstate *tstate;	/*	 * Don't clean up our "master" tstate.	 * It has our default user settings.	 */	if (scsi_id == ahd->our_id	 && force == FALSE)		return;	tstate = ahd->enabled_targets[scsi_id];	if (tstate != NULL)		free(tstate, M_DEVBUF);	ahd->enabled_targets[scsi_id] = NULL;}#endif/* * Called when we have an active connection to a target on the bus, * this function finds the nearest period to the input period limited * by the capabilities of the bus connectivity of and sync settings for * the target. */voidahd_devlimited_syncrate(struct ahd_softc *ahd,			struct ahd_initiator_tinfo *tinfo,			u_int *period, u_int *ppr_options, role_t role){	struct	ahd_transinfo *transinfo;	u_int	maxsync;	if ((ahd_inb(ahd, SBLKCTL) & ENAB40) != 0	 && (ahd_inb(ahd, SSTAT2) & EXP_ACTIVE) == 0) {		maxsync = AHD_SYNCRATE_PACED;	} else {		maxsync = AHD_SYNCRATE_ULTRA;		/* Can't do DT related options on an SE bus */		*ppr_options &= MSG_EXT_PPR_QAS_REQ;	}	/*	 * Never allow a value higher than our current goal	 * period otherwise we may allow a target initiated	 * negotiation to go above the limit as set by the	 * user.  In the case of an initiator initiated	 * sync negotiation, we limit based on the user	 * setting.  This allows the system to still accept	 * incoming negotiations even if target initiated	 * negotiation is not performed.	 */	if (role == ROLE_TARGET)		transinfo = &tinfo->user;	else 		transinfo = &tinfo->goal;	*ppr_options &= (transinfo->ppr_options|MSG_EXT_PPR_PCOMP_EN);	if (transinfo->period == 0) {		*period = 0;		*ppr_options = 0;	} else {		*period = MAX(*period, transinfo->period);		ahd_find_syncrate(ahd, period, ppr_options, maxsync);	}}/* * Look up the valid period to SCSIRATE conversion in our table. * Return the period and offset that should be sent to the target * if this was the beginning of an SDTR. */voidahd_find_syncrate(struct ahd_softc *ahd, u_int *period,		  u_int *ppr_options, u_int maxsync){	/* Skip all PACED only entries if IU is not available */	if ((*ppr_options & MSG_EXT_PPR_IU_REQ) == 0	 && maxsync < AHD_SYNCRATE_DT)		maxsync = AHD_SYNCRATE_DT;	/* Skip all DT only entries if DT is not available */	if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0	 && maxsync < AHD_SYNCRATE_ULTRA2)		maxsync = AHD_SYNCRATE_ULTRA2;		if (*period < maxsync)		*period = maxsync;	if ((*ppr_options & MSG_EXT_PPR_DT_REQ) != 0	 && *period > AHD_SYNCRATE_MIN_DT)		*ppr_options &= ~MSG_EXT_PPR_DT_REQ;			if (*period > AHD_SYNCRATE_MIN)		*period = 0;	/* Honor PPR option conformance rules. */	if ((*ppr_options & MSG_EXT_PPR_IU_REQ) == 0)		*ppr_options &= (MSG_EXT_PPR_DT_REQ|MSG_EXT_PPR_QAS_REQ);	if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0)		*ppr_options &= MSG_EXT_PPR_QAS_REQ;}/* * Truncate the given synchronous offset to a value the * current adapter type and syncrate are capable of. */voidahd_validate_offset(struct ahd_softc *ahd,		    struct ahd_initiator_tinfo *tinfo,		    u_int period, u_int *offset, int wide,		    role_t role){	u_int maxoffset;	/* Limit offset to what we can do */	if (period == 0)		maxoffset = 0;	else if (period <= AHD_SYNCRATE_PACED)		maxoffset = MAX_OFFSET_PACED;	else		maxoffset = MAX_OFFSET;	*offset = MIN(*offset, maxoffset);	if (tinfo != NULL) {		if (role == ROLE_TARGET)			*offset = MIN(*offset, tinfo->user.offset);		else			*offset = MIN(*offset, tinfo->goal.offset);	}}/* * Truncate the given transfer width parameter to a value the * current adapter type is capable of. */voidahd_validate_width(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo,		   u_int *bus_width, role_t role){	switch (*bus_width) {	default:		if (ahd->features & AHD_WIDE) {			/* Respond Wide */			*bus_width = MSG_EXT_WDTR_BUS_16_BIT;			break;		}		/* FALLTHROUGH */	case MSG_EXT_WDTR_BUS_8_BIT:		*bus_width = MSG_EXT_WDTR_BUS_8_BIT;		break;	}	if (tinfo != NULL) {		if (role == ROLE_TARGET)			*bus_width = MIN(tinfo->user.width, *bus_width);		else			*bus_width = MIN(tinfo->goal.width, *bus_width);	}}/* * Update the bitmask of targets for which the controller should * negotiate with at the next convenient oportunity.  This currently * means the next time we send the initial identify messages for * a new transaction. */intahd_update_neg_request(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,		       struct ahd_tmode_tstate *tstate,		       struct ahd_initiator_tinfo *tinfo, int force){	u_int auto_negotiate_orig;	auto_negotiate_orig = tstate->auto_negotiate;	if (tinfo->curr.period != tinfo->goal.period	 || tinfo->curr.width != tinfo->goal.width	 || tinfo->curr.offset != tinfo->goal.offset	 || tinfo->curr.ppr_options != tinfo->goal.ppr_options	 || (force	  && (tinfo->goal.period != 0	   || tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT	   || tinfo->goal.ppr_options != 0)))		tstate->auto_negotiate |= devinfo->target_mask;	else		tstate->auto_negotiate &= ~devinfo->target_mask;	return (auto_negotiate_orig != tstate->auto_negotiate);}/* * Update the user/goal/curr tables of synchronous negotiation * parameters as well as, in the case of a current or active update, * any data structures on the host controller.  In the case of an * active update, the specified target is currently talking to us on * the bus, so the transfer parameter update must take effect * immediately. */voidahd_set_syncrate(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,		 u_int period, u_int offset, u_int ppr_options,		 u_int type, int paused){	struct	ahd_initiator_tinfo *tinfo;	struct	ahd_tmode_tstate *tstate;	u_int	old_period;	u_int	old_offset;	u_int	old_ppr;	int	active;	int	update_needed;	active = (type & AHD_TRANS_ACTIVE) == AHD_TRANS_ACTIVE;	update_needed = 0;	if (period == 0 || offset == 0) {		period = 0;		offset = 0;	}	tinfo = ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,				    devinfo->target, &tstate);	if ((type & AHD_TRANS_USER) != 0) {		tinfo->user.period = period;		tinfo->user.offset = offset;		tinfo->user.ppr_options = ppr_options;	}	if ((type & AHD_TRANS_GOAL) != 0) {		tinfo->goal.period = period;		tinfo->goal.offset = offset;		tinfo->goal.ppr_options = ppr_options;	}	old_period = tinfo->curr.period;	old_offset = tinfo->curr.offset;	old_ppr	   = tinfo->curr.ppr_options;	if ((type & AHD_TRANS_CUR) != 0	 && (old_period != period	  || old_offset != offset	  || old_ppr != ppr_options)) {		update_nee

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -