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

📄 adwlib.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	/*	 * Clear the rest of LRAM.	 */	for (; addr < ADW_CONDOR_MEMSIZE/2; addr++)		adw_outw(adw, ADW_RAM_DATA, 0);	/*	 * Verify the microcode checksum.	 */	checksum = 0;	adw_outw(adw, ADW_RAM_ADDR, 0);	for (addr = 0; addr < adw_mcode_size/2; addr++)		checksum += adw_inw(adw, ADW_RAM_DATA);	if (checksum != adw_mcode_chksum) {		printf("%s: Firmware load failed!\n", adw_name(adw));		return (-1);	}	/*	 * Restore the RISC memory BIOS region.	 */	for (addr = 0; addr < ADW_MC_BIOSLEN; addr++)		adw_lram_write_8(adw, addr + ADW_MC_BIOSLEN, biosmem[addr]);	/*	 * Calculate and write the microcode code checksum to	 * the microcode code checksum location.	 */	addr = adw_lram_read_16(adw, ADW_MC_CODE_BEGIN_ADDR) / 2;	end_addr = adw_lram_read_16(adw, ADW_MC_CODE_END_ADDR) / 2;	checksum = 0;	for (; addr < end_addr; addr++)		checksum += mcodebuf[addr];	adw_lram_write_16(adw, ADW_MC_CODE_CHK_SUM, checksum);	/*	 * Initialize microcode operating variables	 */	adw_lram_write_16(adw, ADW_MC_ADAPTER_SCSI_ID, adw->initiator_id);	/*	 * Leave WDTR and SDTR negotiation disabled until the XPT has	 * informed us of device capabilities, but do set the ultra mask	 * in case we receive an SDTR request from the target before we	 * negotiate.  We turn on tagged queuing at the microcode level	 * for all devices, and modulate this on a per command basis.	 */	adw_lram_write_16(adw, ADW_MC_ULTRA_ABLE, adw->user_ultra);	adw_lram_write_16(adw, ADW_MC_DISC_ENABLE, adw->user_discenb);	adw_lram_write_16(adw, ADW_MC_TAGQNG_ABLE, ~0);	/*	 * Set SCSI_CFG0 Microcode Default Value.	 *	 * The microcode will set the SCSI_CFG0 register using this value	 * after it is started.	 */	adw_lram_write_16(adw, ADW_MC_DEFAULT_SCSI_CFG0,			  ADW_SCSI_CFG0_PARITY_EN|ADW_SCSI_CFG0_SEL_TMO_LONG|			  ADW_SCSI_CFG0_OUR_ID_EN|adw->initiator_id);  	/*	 * Determine SCSI_CFG1 Microcode Default Value.	 *	 * The microcode will set the SCSI_CFG1 register using this value	 * after it is started below.	 */	scsicfg1 = adw_inw(adw, ADW_SCSI_CFG1);	/*	 * If all three connectors are in use, return an error.	 */	if ((scsicfg1 & ADW_SCSI_CFG1_ILLEGAL_CABLE_CONF_A_MASK) == 0	 || (scsicfg1 & ADW_SCSI_CFG1_ILLEGAL_CABLE_CONF_B_MASK) == 0) {		printf("%s: Illegal Cable Config!\n", adw_name(adw));		printf("%s: Only Two Ports may be used at a time!\n",		       adw_name(adw));		return (-1);	}	/*	 * If the internal narrow cable is reversed all of the SCSI_CTRL	 * register signals will be set. Check for and return an error if	 * this condition is found.	 */	if ((adw_inw(adw, ADW_SCSI_CTRL) & 0x3F07) == 0x3F07) {		printf("%s: Illegal Cable Config!\n", adw_name(adw));		printf("%s: Internal cable is reversed!\n", adw_name(adw));	        return (-1);	}	/*	 * If this is a differential board and a single-ended device	 * is attached to one of the connectors, return an error.	 */	if ((scsicfg1 & ADW_SCSI_CFG1_DIFF_MODE) != 0	 && (scsicfg1 & ADW_SCSI_CFG1_DIFF_SENSE) == 0) {		printf("%s: A Single Ended Device is attached to our "		       "differential bus!\n", adw_name(adw));	        return (-1);	}	/*	 * Perform automatic termination control if desired.	 */	if (term_scsicfg1 == 0) {        	switch(scsicfg1 & ADW_SCSI_CFG1_CABLE_DETECT) {		case (ADW_SCSI_CFG1_INT16_MASK|ADW_SCSI_CFG1_INT8_MASK):		case (ADW_SCSI_CFG1_INT16_MASK|		      ADW_SCSI_CFG1_INT8_MASK|ADW_SCSI_CFG1_EXT8_MASK):		case (ADW_SCSI_CFG1_INT16_MASK|		      ADW_SCSI_CFG1_INT8_MASK|ADW_SCSI_CFG1_EXT16_MASK):		case (ADW_SCSI_CFG1_INT16_MASK|		      ADW_SCSI_CFG1_EXT8_MASK|ADW_SCSI_CFG1_EXT16_MASK):		case (ADW_SCSI_CFG1_INT8_MASK|		      ADW_SCSI_CFG1_EXT8_MASK|ADW_SCSI_CFG1_EXT16_MASK):		case (ADW_SCSI_CFG1_INT16_MASK|ADW_SCSI_CFG1_INT8_MASK|		      ADW_SCSI_CFG1_EXT8_MASK|ADW_SCSI_CFG1_EXT16_MASK):			/* Two out of three cables missing.  Both on. */			term_scsicfg1 |= ADW_SCSI_CFG1_TERM_CTL_L				      |  ADW_SCSI_CFG1_TERM_CTL_H;			break;		case (ADW_SCSI_CFG1_INT16_MASK):		case (ADW_SCSI_CFG1_INT16_MASK|ADW_SCSI_CFG1_EXT8_MASK):		case (ADW_SCSI_CFG1_INT16_MASK|ADW_SCSI_CFG1_EXT16_MASK):		case (ADW_SCSI_CFG1_INT8_MASK|ADW_SCSI_CFG1_EXT16_MASK):		case (ADW_SCSI_CFG1_EXT8_MASK|ADW_SCSI_CFG1_EXT16_MASK):			/* No two 16bit cables present.  High on. */			term_scsicfg1 |= ADW_SCSI_CFG1_TERM_CTL_H;			break;		case (ADW_SCSI_CFG1_INT8_MASK):		case (ADW_SCSI_CFG1_INT8_MASK|ADW_SCSI_CFG1_EXT8_MASK):			/* Wide -> Wide or Narrow -> Wide. Both off */			break;		}        }	/* Tell the user about our decission */	switch (term_scsicfg1 & ADW_SCSI_CFG1_TERM_CTL_MASK) {	case ADW_SCSI_CFG1_TERM_CTL_MASK:		printf("High & Low Termination Enabled, ");		break;	case ADW_SCSI_CFG1_TERM_CTL_H:		printf("High Termination Enabled, ");		break;	case ADW_SCSI_CFG1_TERM_CTL_L:		printf("Low Termination Enabled, ");		break;	default:		break;	}	/*	 * Invert the TERM_CTL_H and TERM_CTL_L bits and then	 * set 'scsicfg1'. The TERM_POL bit does not need to be	 * referenced, because the hardware internally inverts	 * the Termination High and Low bits if TERM_POL is set.	 */	term_scsicfg1 = ~term_scsicfg1 & ADW_SCSI_CFG1_TERM_CTL_MASK;	scsicfg1 &= ~ADW_SCSI_CFG1_TERM_CTL_MASK;	scsicfg1 |= term_scsicfg1 | ADW_SCSI_CFG1_TERM_CTL_MANUAL;	/*	 * Set SCSI_CFG1 Microcode Default Value	 *	 * Set filter value and possibly modified termination control	 * bits in the Microcode SCSI_CFG1 Register Value.	 *	 * The microcode will set the SCSI_CFG1 register using this value	 * after it is started below.	 */	adw_lram_write_16(adw, ADW_MC_DEFAULT_SCSI_CFG1,			  scsicfg1 | ADW_SCSI_CFG1_FLTR_11_TO_20NS);	/*	 * Only accept selections on our initiator target id.	 * This may change in target mode scenarios...	 */	adw_lram_write_16(adw, ADW_MC_DEFAULT_SEL_MASK,			  (0x01 << adw->initiator_id));	/*	 * Link all the RISC Queue Lists together in a doubly-linked	 * NULL terminated list.	 *	 * Skip the NULL (0) queue which is not used.	 */	for (i = 1, addr = ADW_MC_RISC_Q_LIST_BASE + ADW_MC_RISC_Q_LIST_SIZE;	     i < ADW_MC_RISC_Q_TOTAL_CNT;	     i++, addr += ADW_MC_RISC_Q_LIST_SIZE) {	        /*		 * Set the current RISC Queue List's		 * RQL_FWD and RQL_BWD pointers in a		 * one word write and set the state		 * (RQL_STATE) to free.		 */		adw_lram_write_16(adw, addr, ((i + 1) | ((i - 1) << 8)));		adw_lram_write_8(adw, addr + RQL_STATE, ADW_MC_QS_FREE);	}	/*	 * Set the Host and RISC Queue List pointers.	 *	 * Both sets of pointers are initialized with the same values:	 * ADW_MC_RISC_Q_FIRST(0x01) and ADW_MC_RISC_Q_LAST (0xFF).	 */	adw_lram_write_8(adw, ADW_MC_HOST_NEXT_READY, ADW_MC_RISC_Q_FIRST);	adw_lram_write_8(adw, ADW_MC_HOST_NEXT_DONE, ADW_MC_RISC_Q_LAST);	adw_lram_write_8(adw, ADW_MC_RISC_NEXT_READY, ADW_MC_RISC_Q_FIRST);	adw_lram_write_8(adw, ADW_MC_RISC_NEXT_DONE, ADW_MC_RISC_Q_LAST);	/*	 * Set up the last RISC Queue List (255) with a NULL forward pointer.	 */	adw_lram_write_16(adw, addr, (ADW_MC_NULL_Q + ((i - 1) << 8)));	adw_lram_write_8(adw, addr + RQL_STATE, ADW_MC_QS_FREE);	adw_outb(adw, ADW_INTR_ENABLES,		 ADW_INTR_ENABLE_HOST_INTR|ADW_INTR_ENABLE_GLOBAL_INTR);	adw_outw(adw, ADW_PC, adw_lram_read_16(adw, ADW_MC_CODE_BEGIN_ADDR));	return (0);}/* * Send an idle command to the chip and optionally wait for completion. */voidadw_idle_cmd_send(struct adw_softc *adw, adw_idle_cmd_t cmd, u_int parameter){	int s;	adw->idle_command_cmp = 0;	s = splcam();		if (adw->idle_cmd != ADW_IDLE_CMD_COMPLETED)		printf("%s: Warning! Overlapped Idle Commands Attempted\n",		       adw_name(adw));	adw->idle_cmd = cmd;	adw->idle_cmd_param = parameter;	/*	 * Write the idle command value after the idle command parameter	 * has been written to avoid a race condition. If the order is not	 * followed, the microcode may process the idle command before the	 * parameters have been written to LRAM.	 */	adw_lram_write_16(adw, ADW_MC_IDLE_PARA_STAT, parameter);    	adw_lram_write_16(adw, ADW_MC_IDLE_CMD, cmd);	splx(s);}/* Wait for an idle command to complete */adw_idle_cmd_status_tadw_idle_cmd_wait(struct adw_softc *adw){	u_int		      timeout;	adw_idle_cmd_status_t status;	int		      s;	/* Wait for up to 10 seconds for the command to complete */	timeout = 10000;	while (--timeout) {       		if (adw->idle_command_cmp != 0)			break;		DELAY(1000);	}	if (timeout == 0)		panic("%s: Idle Command Timed Out!\n", adw_name(adw));	s = splcam();	status = adw_lram_read_16(adw, ADW_MC_IDLE_PARA_STAT);	splx(s);	return (status);}

⌨️ 快捷键说明

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