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

📄 wvlan_hcfio.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 2 页
字号:
.DIAGRAM 1:	the test on rc checks whether a BAP initialization or a call to cmd_wait did ever fail. If so, the Hermes 	is assumed inoperable/defect, and all subsequent bap_ini/cmd_wait calls are nullified till hcf_disable 	clears the IFB_TimStat field. 2:	The PCMCIA card can be removed in the middle of the transfer. By depositing a "magic number" in the 	HREG_SW_0 register of the Hermes at initialization time and by verifying this location after     reading the string, it can be determined whether the card is still present and the return status is     set accordingly. 3:	The test on offset and fid in the IFB_BAP_<n> structure corresponding with the BAP entry parameter, 	assures that the BAP is only initialized if the current set of parameters specifies a location wich is 	not consecutive with the last read/write access. If initialization is needed, then:	  -	the select register is set	  -	the offset register is set	  -	the IFB_BAP_<n> structure is initialized	  - the offset register is monitored till a successful condition (no busy bit and no error bit) is 	  	detected or till the protection counter (calibrated at approx 1 second) expires	If the counter expires, this is reflected in IFB_TimStat, so all subsequent calls to hcfio_string	fail immediately ( see step 1) 4:	the offset register in the IFB_BAP_<n> structure is updated to be used as described in item 3 above  	on the next call10:	The NIC I/F is optimized for word transfer but it can only handle word transfer at a word boundary. 	Therefore an additional test must be done to handle the read preparation in case the begin address in 	NIC RAM is odd.    This situation is handled by first reading a single byte and secondly reading a string of WORDS with a    BYTE length of the requested length minus 1.	NOTE: MACRO IN_PORT_STRING possibly modifies p (depending on how the MSF-programmer chooses to construct	this macro, so pc_addr can not be used as parameter11:	At completion of the word based transfer, a test is made to determine whether 1 additional byte must be 	read (odd length starting at even address or even length starting at odd boundary)12: finally the optionally conversion of the first words from Little Endian to Native Endian format is done.20: first the optionally conversion of the first words from Native Endian to Little Endian format is done.	This implies that Endian conversion can ONLY take place at word boundaries.	Note that the difference with the IO_IN part of the logic is based on optimization considerations (both	speed and size) and the boundary condition to return the output buffer unchanged to the caller	Note also that the check on zero-length for output can not be the simple "skip all" as used for input, 	because the Data Corruption Detection needs some of the side effects of this code, specifically the 	BAP initialization21: As for the IO_IN part, the logic must first cope with odd begin addresses in NIC RAM and the bulk of the	transfer is done via OUT_PORT_STRING. Due to a flaw in the Hermes, writing the high byte corrupts the 	low byte. As a work around, the HCF reads the low byte deposited in NIC RAM by the previous 	hcfio_string, merges that byte with the first byte of the current Host RAM buffer into a word and	writes that word to NIC RAM via OUT_PORT_WORD. Since OUT_PORT_WORD converts from Native Endian to	Little Endian, while at this point of the procedure the Host buffer must have the correct Endianess,	the macro CNV_LITTLE_TO_INT counteracts this unwanted adjustment of OUT_PORT_WORD.22: At completion of the word based transfer, a test is made to determine whether 1 additional byte must be 	written30: The case of Data Corruption Detection:	First the NIC RAM pointer is aligned on a word boundary to cope with the problem of an odd number of	bytes written before. This is done by skipping one additional byte before the Data Corruption 	Detection Pattern is appended to the data already written to the NIC RAM.	Then 8 bytes fixed pattern is written. The justification of this is given in the NOTICE section below31: In order to read the pattern back, the BAP must be initialized to address the begin of the pattern.	The select register does not change, so only the offset register needs to be written, followed by	a wait for successful completion.40: To recognize the case that the NIC is removed during execution of hcfio_string, the same check as in	step 2 is done again.99:	In the past, one of the asserts in bap_ini (which no longer exists now it is assimilated in hcfio_string) 	catched if "offset" was invalid. By calling bap_ini with the original (offset + length), bap_ini would 	catch when the MSF passes the RID/FID boundary during the read process. It turned out that this feature 	did obscure the tracing during debugging so much that its total effect on the debugging process was 	considered detrimental, however re-institution can be considered depending on the bug you are chasing.NOTICEThe problem is that without known cause, the Hermes internal NIC RAM pointer misses its auto-increment causing two successive writes to NIC RAM to address the same location. As a consequence word <n> is overwritten and a word <n+j> is written at position <n+j-1>. Since the Hermes is unaware of this, nothing in the system is going to catch this, e.g. the frame is received on the other side with correct FCS. As a workaround, the HCF keeps track of where the NIC RAM pointer SHOULD be. After all hcf_put_data calls are done, in other words, when hcf_send is called, the HCF writes a number of words - the kludge pattern - after the MSF-data. Then it sets the NIC RAM pointer by means of a re-initialization of the BAP to where this kludge pattern SHOULD be and reads the first word. This first word must match the kludge pattern, otherwise, apparently, the auto-increment failed. We need to write more than 1 word otherwise if the previous use of that piece of NIC RAM would have left by chance the right "kludge" value just after the newly but incorrectly put data, the test would not trigger. By overwriting the next 3 words as well, we assume the likelihood of this to be sufficiently small. The frequency observed of this problem varies from 1 out of 1000 frames till to low to be noticeable. Just to be on the safe side we assume that the chance of an error is 10E-3. By writing 4 words we reduce the likelihood of an unnoticed problem to 10E-12, but of course this becomes tricky because we don't know whether the chances are independent. Note that the HCF notion of the NIC RAM pointer is a "logical" view in the RID/FID address space, while the Hermes has a completely different physical address value for this pointer, however that difference does not influence above reasoning..NOTE  Depending on the selected optimization options, using "register int reg" causes some obscure   optimization with si. As a result the code is longer. Therefore, do not invest time to optimize this code   that way during a "maintenance cycle". .NOTE  The IN_/OUT_PORT_WORD_/STRING macros are MSF-programmer defined and may or may not have side effects   on their parameters, therefore they can not handle expressions like "len/2". As a solution all these macros  must be called via "simple" variables, with no side effects like ++ and their contents is unpredictable  at completion of the macro  .NOTE  The implementation is choosen to have input, output and BAP setup all rolled into one monolithic  function rather than a more ameniable hcfio_in_string, hcfio_out_string and bap_ini to minimize the   stack usage during Interrupt Service (especially relevant for DOS drivers).NOTE  The local variable reg corresponds with a register of the appropriate BAP. This is possible by the   intentional choice of the addresses of the individual registers of the two BAPs and the macro used to   specify whether BAP_0 or BAP_1 should be used. The value of reg is changed in the flow of hcfio_string  because, depending on the context, reg is most optimal addressing the offset register or the data register.	 .ENDOC                          END DOCUMENTATION-------------------------------------------------------------------------------------------------------------*/int hcfio_string( IFBP ifbp, int bap, int fid, 				  int offset, wci_bufp pc_addr, int word_len, int tot_len, int type ) {hcf_io		reg = ifbp->IFB_IOBase + bap - HREG_DATA_0 + HREG_OFFSET_0;				//reg = offset registerhcf_32		prot_cnt = ifbp->IFB_TickIni;hcf_16  	*p1 = bap == BAP_0 ? ifbp->IFB_BAP_0 : ifbp->IFB_BAP_1;wci_bufp	cp;wci_recordp	wp = (wci_recordp)pc_addr;int			rc;int			tlen;#if HCF_ALIGN != 0#endif // HCF_ALIGN			/* assumption, writing words takes place only initial, never at odd NIC RAM addresses nor odd PC 			 * addresses	*/	if ( ( rc = ifbp->IFB_TimStat ) == HCF_SUCCESS ) {													/* 1 */	    if ( IN_PORT_WORD( ifbp->IFB_IOBase + HREG_SW_0 ) != HCF_MAGIC ) rc =  HCF_ERR_NO_NIC;			/* 2 */	}		if ( rc == HCF_SUCCESS ) {			/* make sure all preceeding BAP manipulation is settled */		while ( prot_cnt && IN_PORT_WORD( reg ) & (HCMD_BUSY|HREG_OFFSET_ERR) ) prot_cnt--;			if ( offset != (int)*p1 || fid != (int)*(p1+1) ) {												/* 3 */			OUT_PORT_WORD( reg - HREG_OFFSET_0 + HREG_SELECT_0, fid );			OUT_PORT_WORD( reg, offset & 0xFFFE );			*p1 = (hcf_16)offset;			*(p1+1) = (hcf_16)fid;			/* use type == IO_IN and len == 0 as a way to set the BAP for the futute, e.g. at the end of hcf_send *///			while ( prot_cnt-- && IN_PORT_WORD( reg ) & (HCMD_BUSY|HREG_OFFSET_ERR) ) /*NOP*/;			while ( tot_len && prot_cnt && IN_PORT_WORD( reg ) & (HCMD_BUSY|HREG_OFFSET_ERR) ) prot_cnt--;			if ( prot_cnt == 0 ) {				/* ;? It could be discussed whether the HREG_OFFSET_ERR bit should result in blocking NIC access 				 *	till next initialize */				rc = ifbp->IFB_TimStat = HCF_ERR_TIME_OUT;			}		}		*p1 += (hcf_16)tot_len;																			/* 4 */	}	reg += HREG_DATA_0 - HREG_OFFSET_0;												     // reg = data register	if ( rc == HCF_SUCCESS && type == IO_IN ) { 														//input		if ( tot_len ) {			if ( offset & 0x01 ) { /*odd	*/															/* 10*/				*pc_addr++ = IN_PORT_BYTE( reg+1 );				tot_len--;			}			cp = pc_addr;			tlen = DIV_BY_2( tot_len );			IN_PORT_STRING( reg, cp, tlen );			if ( tot_len & 1 ) *(pc_addr + tot_len - 1) = IN_PORT_BYTE( reg );							/* 11*/			while ( word_len-- ) {				CNV_LITTLE_TO_INT_NP( wp );																/* 12*/				wp++;			}		}	}	if ( rc == HCF_SUCCESS && type != IO_IN ) {											  //output and/or check		tlen = word_len;                                                                                /* 20*/		while ( tlen-- ) {                                                                              /* 20*/			OUT_PORT_WORD( reg, *(wci_recordp)pc_addr );			pc_addr += 2;		}//		tlen = offset + tot_len;		if ( tot_len && offset & 0x01 ) {																/* 21*/			OUT_PORT_WORD( reg, CNV_LITTLE_TO_INT( (*pc_addr <<8) + IN_PORT_BYTE( reg ) ) );			pc_addr++;			tot_len--;		}		word_len = DIV_BY_2( tot_len ) - word_len;	  //misuse no longer needed parameter as temporary variable		cp = pc_addr;		OUT_PORT_STRING( reg, cp, word_len );		if ( tot_len & 1 ) OUT_PORT_BYTE( reg, *(pc_addr + tot_len - 1) );								/* 22*/		if ( type == IO_OUT_CHECK /*&& *p1 != ifbp->IFB_FSBase */) {	//;?<HCF _L> should BE HARD CODED	/* 30*/			if ( *p1 & 0X01 ) (void)IN_PORT_WORD( reg );	//align on word boundary			OUT_PORT_WORD( reg, 0xCAFE );			OUT_PORT_WORD( reg, 0xABBA );			OUT_PORT_WORD( reg, 0xDEAD );			OUT_PORT_WORD( reg, 0xD00F );//!!		OUT_PORT_WORD( bap - HREG_OFFSET_0 + HREG_SELECT_0, fid );									/* 31*/			OUT_PORT_WORD( reg - HREG_DATA_0 + HREG_OFFSET_0, (*p1 + 1)&0xFFFE );			prot_cnt = ifbp->IFB_TickIni;			while ( prot_cnt && IN_PORT_WORD(reg - HREG_DATA_0 + HREG_OFFSET_0) & (HCMD_BUSY|HREG_OFFSET_ERR) ) prot_cnt--;			if ( prot_cnt == 0 ) {				rc = ifbp->IFB_TimStat = HCF_ERR_TIME_OUT;			}			if ( IN_PORT_WORD( reg ) != 0xCAFE ) {	 			rc = HCF_FAILURE;				ifbp->IFB_PIFRscInd = 1;//!			} else {//!				rc = HCF_SUCCESS;			}		}	}	if ( rc == HCF_SUCCESS ) {																			/* 40*/	    if ( IN_PORT_WORD( ifbp->IFB_IOBase + HREG_SW_0 ) != HCF_MAGIC ) rc =  HCF_ERR_NO_NIC;	}	//!	ASSERT( bap_ini( ifbp, bap, fid, (offset + len) & 0xFFFE) == HCF_SUCCESS )							/*99 */    return rc;}/* hcfio_string */

⌨️ 快捷键说明

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