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

📄 aic7xxx_core.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
			if (lastphase != P_BUSFREE) {				/*				 * Renegotiate with this device at the				 * next oportunity just in case this busfree				 * is due to a negotiation mismatch with the				 * device.				 */				ahc_force_renegotiation(ahc, &devinfo);			}			printf("Unexpected busfree %s\n"			       "SEQADDR == 0x%x\n",			       ahc_phase_table[i].phasemsg,			       ahc_inb(ahc, SEQADDR0)				| (ahc_inb(ahc, SEQADDR1) << 8));		}		ahc_outb(ahc, CLRINT, CLRSCSIINT);		ahc_restart(ahc);	} else {		printf("%s: Missing case in ahc_handle_scsiint. status = %x\n",		       ahc_name(ahc), status);		ahc_outb(ahc, CLRINT, CLRSCSIINT);	}}/* * Force renegotiation to occur the next time we initiate * a command to the current device. */static voidahc_force_renegotiation(struct ahc_softc *ahc, struct ahc_devinfo *devinfo){	struct	ahc_initiator_tinfo *targ_info;	struct	ahc_tmode_tstate *tstate;	targ_info = ahc_fetch_transinfo(ahc,					devinfo->channel,					devinfo->our_scsiid,					devinfo->target,					&tstate);	ahc_update_neg_request(ahc, devinfo, tstate,			       targ_info, AHC_NEG_IF_NON_ASYNC);}#define AHC_MAX_STEPS 2000voidahc_clear_critical_section(struct ahc_softc *ahc){	int	stepping;	int	steps;	u_int	simode0;	u_int	simode1;	if (ahc->num_critical_sections == 0)		return;	stepping = FALSE;	steps = 0;	simode0 = 0;	simode1 = 0;	for (;;) {		struct	cs *cs;		u_int	seqaddr;		u_int	i;		seqaddr = ahc_inb(ahc, SEQADDR0)			| (ahc_inb(ahc, SEQADDR1) << 8);		/*		 * Seqaddr represents the next instruction to execute, 		 * so we are really executing the instruction just		 * before it.		 */		if (seqaddr != 0)			seqaddr -= 1;		cs = ahc->critical_sections;		for (i = 0; i < ahc->num_critical_sections; i++, cs++) {						if (cs->begin < seqaddr && cs->end >= seqaddr)				break;		}		if (i == ahc->num_critical_sections)			break;		if (steps > AHC_MAX_STEPS) {			printf("%s: Infinite loop in critical section\n",			       ahc_name(ahc));			ahc_dump_card_state(ahc);			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.			 */			simode0 = ahc_inb(ahc, SIMODE0);			ahc_outb(ahc, SIMODE0, 0);			simode1 = ahc_inb(ahc, SIMODE1);			if ((ahc->features & AHC_DT) != 0)				/*				 * On DT class controllers, we				 * use the enhanced busfree logic.				 * Unfortunately we cannot re-enable				 * busfree detection within the				 * current connection, so we must				 * leave it on while single stepping.				 */				ahc_outb(ahc, SIMODE1, simode1 & ENBUSFREE);			else				ahc_outb(ahc, SIMODE1, 0);			ahc_outb(ahc, CLRINT, CLRSCSIINT);			ahc_outb(ahc, SEQCTL, ahc->seqctl | STEP);			stepping = TRUE;		}		if ((ahc->features & AHC_DT) != 0) {			ahc_outb(ahc, CLRSINT1, CLRBUSFREE);			ahc_outb(ahc, CLRINT, CLRSCSIINT);		}		ahc_outb(ahc, HCNTRL, ahc->unpause);		while (!ahc_is_paused(ahc))			ahc_delay(200);	}	if (stepping) {		ahc_outb(ahc, SIMODE0, simode0);		ahc_outb(ahc, SIMODE1, simode1);		ahc_outb(ahc, SEQCTL, ahc->seqctl);	}}/* * Clear any pending interrupt status. */voidahc_clear_intstat(struct ahc_softc *ahc){	/* Clear any interrupt conditions this may have caused */	ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRATNO|CLRSCSIRSTI				|CLRBUSFREE|CLRSCSIPERR|CLRPHASECHG|				CLRREQINIT);	ahc_flush_device_writes(ahc);	ahc_outb(ahc, CLRSINT0, CLRSELDO|CLRSELDI|CLRSELINGO); 	ahc_flush_device_writes(ahc);	ahc_outb(ahc, CLRINT, CLRSCSIINT);	ahc_flush_device_writes(ahc);}/**************************** Debugging Routines ******************************/#ifdef AHC_DEBUGuint32_t ahc_debug = AHC_DEBUG_OPTS;#endifvoidahc_print_scb(struct scb *scb){	int i;	struct hardware_scb *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.cdb); i++)		printf("%#02x", hscb->shared_data.cdb[i]);	printf("        dataptr:%#x datacnt:%#x sgptr:%#x tag:%#x\n",		ahc_le32toh(hscb->dataptr),		ahc_le32toh(hscb->datacnt),		ahc_le32toh(hscb->sgptr),		hscb->tag);	if (scb->sg_count > 0) {		for (i = 0; i < scb->sg_count; i++) {			printf("sg[%d] - Addr 0x%x%x : Length %d\n",			       i,			       (ahc_le32toh(scb->sg_list[i].len) >> 24			        & SG_HIGH_ADDR_BITS),			       ahc_le32toh(scb->sg_list[i].addr),			       ahc_le32toh(scb->sg_list[i].len));		}	}}/************************* Transfer Negotiation *******************************//* * Allocate per target mode instance (ID we respond to as a target) * transfer negotiation data structures. */static struct ahc_tmode_tstate *ahc_alloc_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel){	struct ahc_tmode_tstate *master_tstate;	struct ahc_tmode_tstate *tstate;	int i;	master_tstate = ahc->enabled_targets[ahc->our_id];	if (channel == 'B') {		scsi_id += 8;		master_tstate = ahc->enabled_targets[ahc->our_id_b + 8];	}	if (ahc->enabled_targets[scsi_id] != NULL	 && ahc->enabled_targets[scsi_id] != master_tstate)		panic("%s: ahc_alloc_tstate - Target already allocated",		      ahc_name(ahc));	tstate = (struct ahc_tmode_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));		tstate->ultraenb = 0;		for (i = 0; i < AHC_NUM_TARGETS; 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));	ahc->enabled_targets[scsi_id] = tstate;	return (tstate);}#ifdef AHC_TARGET_MODE/* * Free per target mode instance (ID we respond to as a target) * transfer negotiation data structures. */static voidahc_free_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel, int force){	struct ahc_tmode_tstate *tstate;	/*	 * Don't clean up our "master" tstate.	 * It has our default user settings.	 */	if (((channel == 'B' && scsi_id == ahc->our_id_b)	  || (channel == 'A' && scsi_id == ahc->our_id))	 && force == FALSE)		return;	if (channel == 'B')		scsi_id += 8;	tstate = ahc->enabled_targets[scsi_id];	if (tstate != NULL)		free(tstate, M_DEVBUF);	ahc->enabled_targets[scsi_id] = NULL;}#endif/* * Called when we have an active connection to a target on the bus, * this function finds the nearest syncrate to the input period limited * by the capabilities of the bus connectivity of and sync settings for * the target. */struct ahc_syncrate *ahc_devlimited_syncrate(struct ahc_softc *ahc,			struct ahc_initiator_tinfo *tinfo,			u_int *period, u_int *ppr_options, role_t role){	struct	ahc_transinfo *transinfo;	u_int	maxsync;	if ((ahc->features & AHC_ULTRA2) != 0) {		if ((ahc_inb(ahc, SBLKCTL) & ENAB40) != 0		 && (ahc_inb(ahc, SSTAT2) & EXP_ACTIVE) == 0) {			maxsync = AHC_SYNCRATE_DT;		} else {			maxsync = AHC_SYNCRATE_ULTRA;			/* Can't do DT on an SE bus */			*ppr_options &= ~MSG_EXT_PPR_DT_REQ;		}	} else if ((ahc->features & AHC_ULTRA) != 0) {		maxsync = AHC_SYNCRATE_ULTRA;	} else {		maxsync = AHC_SYNCRATE_FAST;	}	/*	 * 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;	if (transinfo->width == MSG_EXT_WDTR_BUS_8_BIT) {		maxsync = MAX(maxsync, AHC_SYNCRATE_ULTRA2);		*ppr_options &= ~MSG_EXT_PPR_DT_REQ;	}	if (transinfo->period == 0) {		*period = 0;		*ppr_options = 0;		return (NULL);	}	*period = MAX(*period, transinfo->period);	return (ahc_find_syncrate(ahc, 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. */struct ahc_syncrate *ahc_find_syncrate(struct ahc_softc *ahc, u_int *period,		  u_int *ppr_options, u_int maxsync){	struct ahc_syncrate *syncrate;	if ((ahc->features & AHC_DT) == 0)		*ppr_options &= ~MSG_EXT_PPR_DT_REQ;	/* Skip all DT only entries if DT is not available */	if ((*ppr_options & MSG_EXT_PPR_DT_REQ) == 0	 && maxsync < AHC_SYNCRATE_ULTRA2)		maxsync = AHC_SYNCRATE_ULTRA2;		for (syncrate = &ahc_syncrates[maxsync];	     syncrate->rate != NULL;	     syncrate++) {		/*		 * The Ultra2 table doesn't go as low		 * as for the Fast/Ultra cards.		 */		if ((ahc->features & AHC_ULTRA2) != 0		 && (syncrate->sxfr_u2 == 0))			break;		if (*period <= syncrate->period) {			/*			 * When responding to a target that requests			 * sync, the requested rate may fall between			 * two rates that we can output, but still be			 * a rate that we can receive.  Because of this,			 * we want to respond to the target with			 * the same rate that it sent to us even			 * if the period we use to send data to it			 * is lower.  Only lower the response period			 * if we must.			 */			if (syncrate == &ahc_syncrates[maxsync])				*period = syncrate->period;			/*			 * At some speeds, we only support			 * ST transfers.			 */		 	if ((syncrate->sxfr_u2 & ST_SXFR) != 0)				*ppr_options &= ~MSG_EXT_PPR_DT_REQ;			break;		}	}	if ((*period == 0)	 || (syncrate->rate == NULL)	 || ((ahc->features & AHC_ULTRA2) != 0	  && (syncrate->sxfr_u2 == 0))) {		/* Use asynchronous transfers. */		*period = 0;		syncrate = NULL;		*ppr_options &= ~MSG_EXT_PPR_DT_REQ;	}	return (syncrate);}/* * Convert from an entry in our syncrate table to the SCSI equivalent * sync "period" factor. */u_intahc_find_period(struct ahc_softc *ahc, u_int scsirate, u_int maxsync){	struct ahc_syncrate *syncrate;	if ((ahc->features & AHC_ULTRA2) != 0)		scsirate &= SXFR_ULTRA2;	else		scsirate &= SXFR;	syncrate = &ahc_syncrates[maxsync];	while (syncrate->rate != NULL) {		if ((ahc->features & AHC_ULTRA2) != 0) {			if (syncrate->sxfr_u2 == 0)				break;			else if (scsirate == (syncrate->sxfr_u2 & SXFR_ULTRA2))				return (syncrate->period);		} else if (scsirate == (syncrate->sxfr & SXFR)) {				return (syncrate->period);		}		syncrate++;	}	return (0); /* async */}/* * Truncate the given synchronous offset to a value the * current adapter type and syncrate are capable of. */voidahc_validate_offset(struct ahc_softc *ahc,		    struct ahc_initiator_tinfo *tinfo,		    struct ahc_syncrate *syncrate,		    u_int *offset, int wide, role_t role){	u_int maxoffset;	/* Limit offset to what we can do */	if (syncrate == NULL) {		maxoffset = 0;	} else if ((ahc->features & AHC_ULTRA2) != 0) {		maxoffset = MAX_OFFSET_ULTRA2;	} else {		if (wide)			maxoffset = MAX_OFFSET_16BIT;		else			maxoffset = MAX_OFFSET_8BIT;	}	*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

⌨️ 快捷键说明

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