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

📄 ppfs.c

📁 windows ce 3.00 嵌入式操作系统源代码
💻 C
字号:
/*
 *		NK Kernel ppfs client code
 *
 *		Copyright (c) 1995-2000 Microsoft Corporation.  All rights reserved.
 *
 * Module Name:
 *
 *		ppfs.c
 *
 * Abstract:
 *
 *		This file implements the NK kernel ppfs client side interface
 *
 *
 */

#include "kernel.h"
#include "ethdbg.h"
#include "halether.h"
/* All strings must be <= 128 bytes including the null termination */

/* Message format: (assume little endians, lower address first>
 * -4      0       4     N-1       N       N+4
 * AA5555AA<header><data><checksum>5AA50A1A
 *
 * Header format:
 * 0       2       4
 * <opcode><length>
 * lsb          msb
 *
 * Length is 16 bit value. It includes all fields (== N)
 * Opcode is 16 bit value.  Current values are:
 * 0x0000 - boot (AA5555AA00000500FA5AA50A1A)
 * 0x0001 - init (AA5555AA01000500F95AA50A1A)
 * 0x0002 - open
 * 0x0003 - close
 * 0x0004 - read
 * 0x0005 - write
 * 0x0006 - seek
 * 0x0007 - delete
 * 0x0008 - findfirst
 * 0x0009 - findnext
 * 0x000A - rRegGet
 * 0x000B - rRegOpen
 * 0x000C - rRegClose
 * 0x000D - rRegEnum
 *
 *
 * Reply to a message will have the same opcode.  Bit15 is set to
 * indicate transmission failure.
 *
 * Data is stream of bytes
 *
 * Checksum is ~(sum of preceding N-1 bytes)
 *
 * Length of data is <length> - 5
 *
 */

extern CRITICAL_SECTION ppfscs;
extern int NoPPFS;						// parallel port not present flag

// If PPFS is running over ethernet, buffer up as much data as possible (up to
// EDBG_MAX_DATA_SIZE) to send to the other side.  The PpfsEthBuf memory is set
// up through the EdbgRegisterDfltClient call.
extern BOOL BufferedPPFS;
extern UCHAR *PpfsEthBuf;

// Local state variables for handling translation of the packet based ethernet
// commands to the byte read write commands used by the ppfs engine.
static UCHAR *pWritePtr, *pReadPtr;
static DWORD dwRemainingBytes;
static DWORD dwBytesWrittenToBuffer;

void  (* lpParallelPortSendByteFunc)(BYTE ch);
int   (* lpParallelPortGetByteFunc)(void);

// Routines for handling the buffering for PPFS over ether.
BOOL fill_edbg_buffer()
{
	DWORD dwLen = EDBG_MAX_DATA_SIZE;
	if (!pEdbgRecv(EDBG_SVC_PPSH, PpfsEthBuf,&dwLen, INFINITE)) {
		NoPPFS = TRUE;
		return FALSE;
	}
	dwRemainingBytes = dwLen;
	pReadPtr = PpfsEthBuf;
	return TRUE;
}

BOOL write_edbg_buffer()
{
	if (dwBytesWrittenToBuffer &&
		!pEdbgSend(EDBG_SVC_PPSH,PpfsEthBuf,dwBytesWrittenToBuffer)) {
		NoPPFS = TRUE;
		return FALSE;
	}
	dwBytesWrittenToBuffer = 0;
	pWritePtr = PpfsEthBuf;
	return TRUE;
}

// Functions for lpParallelPortxxxByteFunc, set up by calling
// SetKernelCommDev(KERNEL_SVC_PPSH,KERNEL_COMM_ETHER).
void ppfs_send_byte_ether(BYTE ch)
{
	*pWritePtr++ = ch;
	if (++dwBytesWrittenToBuffer == EDBG_MAX_DATA_SIZE)
		write_edbg_buffer();
}

int ppfs_get_byte_ether()
{
	// Refill buffer if necessary and return next byte
	if (dwRemainingBytes == 0) 
		 fill_edbg_buffer();
	dwRemainingBytes--;
	return *pReadPtr++;
}

int read_value(int *chksum) {
	int loop;
	int result;
	BYTE ch;
	for (loop = 0; loop < sizeof(int); loop++ ) {
		ch = lpParallelPortGetByteFunc();
		*chksum += ch;
		((LPBYTE)&result)[loop] = ch;
	}
	return result;
}

void write_value(int val, int *chksum) {
	int loop;
	BYTE ch;
	for (loop = 0; loop < 4; loop++) {
		ch = ((LPBYTE)&val)[loop];
		*chksum += ch;
		lpParallelPortSendByteFunc(ch);
	}
}

int read_header(int *chksum) {
	if (BufferedPPFS && !fill_edbg_buffer())
		return -1;
	if (read_value(chksum) != 0xaa5555aa)
		return -1;
	*chksum = 0;
	return read_value(chksum);
}

void write_header(int cmd, int *chksum) {
	if (BufferedPPFS) {
		dwBytesWrittenToBuffer = 0;
		pWritePtr = PpfsEthBuf;
	}
	write_value(0xaa5555aa,chksum);
	*chksum = 0;
	write_value(cmd,chksum);
}

void read_data(LPBYTE buf, int cnt, int *chksum) {
	BYTE ch;
	while (cnt--) {
		ch = lpParallelPortGetByteFunc();
		*chksum += ch;
		*buf++ = ch;
	}
}

void write_data(LPBYTE buf, int cnt, int *chksum) {
	while (cnt--) {
		*chksum += *buf;
		lpParallelPortSendByteFunc(*buf++);
	}
}

/* returns TRUE if success, FALSE if failure */
BOOL read_end(int checksum) {
	BYTE b;
	int tmp;
	b = lpParallelPortGetByteFunc();
	if (((checksum & 0xff) != b) ||
		(read_value(&tmp) != 0x1a0aa55a))
		return FALSE;
	return TRUE;
}

void write_end(int checksum) {
	int tmp;
	BYTE ch = ((checksum & 0xff) ^ 0xff);
	lpParallelPortSendByteFunc(ch);
	write_value(0x1a0aa55a,&tmp); /* Write out end of message signature */

	// If we're using ethernet, packet is all formatted and ready to go, send now
	if (BufferedPPFS)
		write_edbg_buffer();
}

int rlseeknocs(int fd, int off, int mode) {
	int chksum, result;
	if (NoPPFS)
		return -1;
	write_header(0x00110006,&chksum);	/* opcode = 0x0006, length = 17 */
	write_value(fd,&chksum);
	write_value(off,&chksum);
	write_value(mode,&chksum);
	write_end(chksum);
	if (read_header(&chksum) != 0x00090006) /* opcode = 0x0006, length = 9 */
		return -1;
	result = read_value(&chksum);
	if (!read_end(chksum))
		return -1;
	return result;
}

int rlseek(int fd, int off, int mode) {
	int result;
	EnterCriticalSection(&ppfscs);
	result = rlseeknocs(fd,off,mode);
	LeaveCriticalSection(&ppfscs);
	return result;
}

int rwriteshort(int fd, char *buf, int cnt) {
	int chksum, result;

	write_header(0x000d0005+(cnt<<16), &chksum); /* opcode = 0x0005, length = 13 + cnt */
	write_value(fd,&chksum);
	write_value(cnt,&chksum);
	write_data(buf,cnt,&chksum);
	write_end(chksum);
	if (read_header(&chksum) != 0x00090005) /* opcode = 0x0005, length = 9        */
		return -1;
	result = read_value(&chksum);
	if (!read_end(chksum))
		return -1;
	return result;
}

int rwrite(int fd, char *buf, int cnt) {
	int csize, fullsize;
	int result, result2;
	char *buf2 = buf;
	if (NoPPFS)
		return -1;
	fullsize = cnt;
	LockPages(buf,fullsize,0,LOCKFLAG_READ);
	EnterCriticalSection(&ppfscs);
	result2 = 0;
	while (cnt) {
		csize = ( cnt > 32*1024 ? 32*1024 : cnt);
		if ((result = rwriteshort(fd,buf2,csize)) == -1) {
			result2 = -1;
			break;
		}
		result2 += result;
		cnt -= csize;
		buf2 += csize;
	}
	LeaveCriticalSection(&ppfscs);
	UnlockPages(buf,fullsize);
	return result2;
}

int rreadshort(int fd, char *buf, int cnt) {
	int chksum, result, size;
	write_header(0x000d0004, &chksum); /* opcode = 0x0004, length = 13 */
	write_value(fd, &chksum);
	write_value(cnt,&chksum);
	write_end(chksum);
	result = read_header(&chksum);
	if ((result & 0xffff) != 0x0004)
		return -1;
	size = ((result >> 16) & 0xffff) - 9; /* subtract header & chksum */
	result = read_value(&chksum);
	read_data(buf,size,&chksum);
	if (!read_end(chksum))
		return -1;
	return result;
}

int rreadnocs(int fd, char *buf, int cnt) {
	int csize, fullsize;
	int result, result2;
	char *buf2 = buf;
	if (NoPPFS)
		return -1;
	fullsize = cnt;
	result2 = 0;
	while (cnt) {
		csize = ( cnt > 32*1024 ? 32*1024 : cnt);
		if ((result = rreadshort(fd,buf2,csize)) == -1) {
			result2 = -1;
			break;
		}
		result2 += result;
		cnt -= csize;
		buf2 += csize;
    }
	return result2;
}

int rread(int fd, char *buf, int cnt) {
	int result;
	if (NoPPFS)
		return -1;
	LockPages(buf,cnt,0,LOCKFLAG_WRITE);
	EnterCriticalSection(&ppfscs);
	result = rreadnocs(fd,buf,cnt);
	LeaveCriticalSection(&ppfscs);
	UnlockPages(buf,cnt);
	return result;
}

int rreadseek(int fd, char *buf, int cnt, int pos) {
	int ret;
	LockPages(buf,cnt,0,LOCKFLAG_WRITE);
	EnterCriticalSection(&ppfscs);
	ret = rlseeknocs(fd,pos,0);
	if (ret != pos)
		ret = 0;
	else
		ret = rreadnocs(fd,buf,cnt);
	LeaveCriticalSection(&ppfscs);
	UnlockPages(buf,cnt);
	return ret;
}

int rclose(int fd) {
	int chksum, result;

	EnterCriticalSection(&ppfscs);
	if (NoPPFS) {
		LeaveCriticalSection(&ppfscs);
		return -1;
	}
	write_header(0x00090003, &chksum); /* opcode = 0x0003, length = 9 */
	write_value(fd,&chksum);
	write_end(chksum);
	if (read_header(&chksum) != 0x00090003) {
		LeaveCriticalSection(&ppfscs);
		return -1;
	}
	result = read_value(&chksum);
	if (!read_end(chksum)) {
		LeaveCriticalSection(&ppfscs);
		return -1;
	}
	LeaveCriticalSection(&ppfscs);
	return result;
}

#define MAX_FILENAME_LEN 256

void SC_PPSHRestart(void) {
	NoPPFS = 0;
}

int ropen(WCHAR *name, int mode) {
	int chksum, result, len;
	char fname[MAX_FILENAME_LEN];
	len = strlenW(name)+1;
	KUnicodeToAscii(fname,name,MAX_FILENAME_LEN);
	if (NoPPFS)
		return -1;
	EnterCriticalSection(&ppfscs);
	write_header(0x00090002 + (len<<16), &chksum); /* opcode = 0x0002, length = 9 + strlen + 1 */
	write_value(mode,&chksum);
	write_data(fname,len,&chksum);
	write_end(chksum);
	if (read_header(&chksum) != 0x00090002) {
		LeaveCriticalSection(&ppfscs);
		return -1;
	}
	result = read_value(&chksum);
	if (!read_end(chksum)) {
		LeaveCriticalSection(&ppfscs);
		return -1;
	}
	LeaveCriticalSection(&ppfscs);
	return result;
}

// Registration database access functions for kernel debug support initialization
int rRegOpen(DWORD hKey, CHAR *szName, LPDWORD lphKey) {
	int chksum, len;
	if (NoPPFS)
		return -1;
	len = strlen(szName)+1;
	EnterCriticalSection(&ppfscs);
	write_header(0x0009000B + (len<<16), &chksum); /* opcode = 0x000B, length = 9 + strlen + 1 */
	write_value(hKey,&chksum);
	write_data(szName,len,&chksum);
	write_end(chksum);
	if (read_header(&chksum) != 0x0009000B) {
		LeaveCriticalSection(&ppfscs);
		return -1;
	}
	*lphKey = read_value(&chksum);
	if (!read_end(chksum)) {
		LeaveCriticalSection(&ppfscs);
		return -1;
	}
	LeaveCriticalSection(&ppfscs);
	return 0;
}

int rRegClose(DWORD hKey) {
	int chksum, result;
	if (NoPPFS)
		return -1;
	EnterCriticalSection(&ppfscs);
	write_header(0x0009000C, &chksum); /* opcode = 0x000C, length = 9 */
	write_value(hKey,&chksum);
	write_end(chksum);
	if (read_header(&chksum) != 0x0009000C) {
		LeaveCriticalSection(&ppfscs);
		return -1;
	}
	result = read_value(&chksum);
	if (!read_end(chksum)) {
		LeaveCriticalSection(&ppfscs);
		return -1;
	}
	LeaveCriticalSection(&ppfscs);
	return result;
}

int rRegGet(DWORD hKey, CHAR *szName, LPDWORD lpdwType,
                LPBYTE lpbData, LPDWORD lpdwSize) {
	int chksum, result, len;
	if (NoPPFS)
		return -1;
	len = strlen(szName)+1;
	EnterCriticalSection(&ppfscs);
	write_header(0x0009000A + (len<<16), &chksum); /* opcode = 0x000A, length = 9 + strlen + 1 */
	write_value(hKey,&chksum);
	write_data(szName,len,&chksum);
	write_end(chksum);
	result = read_header(&chksum);
	if ((result & 0xffff) != 0x000A)
	{
    	LeaveCriticalSection(&ppfscs);
		return 0;
    }		
	len = ((result >> 16) & 0xffff) - 9; /* subtract header & chksum */
	*lpdwType = read_value(&chksum);
	*lpdwSize = len;
	read_data(lpbData,len,&chksum);
	if (!read_end(chksum)) {
		LeaveCriticalSection(&ppfscs);
		return 0;
	}
	LeaveCriticalSection(&ppfscs);
	return 1;
}

int rRegEnum(DWORD hKey, DWORD dwIndex, LPBYTE lpbData, LPDWORD lpdwSize) {
	int chksum, result, len;
	if (NoPPFS)
		return -1;
	EnterCriticalSection(&ppfscs);
	write_header(0x000D000D, &chksum); /* opcode = 0x000A, length = 13 */
	write_value(hKey,&chksum);
	write_value(dwIndex,&chksum);
	write_end(chksum);
	result = read_header(&chksum);
	if ((result & 0xffff) != 0x000D)
	{
    	LeaveCriticalSection(&ppfscs);
		return -1;
    }		
	len = ((result >> 16) & 0xffff) - 9; /* subtract header & chksum */
	result = read_value(&chksum);
	*lpdwSize = len;
	read_data(lpbData,len,&chksum);
	if (!read_end(chksum)) {
		LeaveCriticalSection(&ppfscs);
		return -1;
	}
	LeaveCriticalSection(&ppfscs);
	return result;
}

// Routine for sending debug messages over PPSH.  Note the problem with the PPFS CS here -
// if we are called to put out a debug message while in a sys call, we can't block on the CS,
// but we can't just start sending data, because if someone is called into the loader, the
// other end will get confused (PPFS protocol can't handle packets within other packets).

#define MAX_DEBUGSTRING_LEN 512

// Prevent multiple LOW per HIGHADJ fixup problem
#if defined(PPC)
#pragma optimize("", off)
#endif

void 
PpfsWriteDebugString(unsigned short *name) {
	int chksum, len;
	char fname[MAX_DEBUGSTRING_LEN];
	if (NoPPFS)
		return;

	if (!InSysCall())
		EnterCriticalSection(&ppfscs);
	else if (ppfscs.OwnerThread) {
		// Can't block and someone is using the loader, just dump message to debug serial port
		OEMWriteDebugString(name);
		return;
    }
	len = strlenW(name)+1;
	KUnicodeToAscii(fname,name,MAX_DEBUGSTRING_LEN);
    
	write_header(0x0009000f + (len<<16), &chksum); /* opcode = 0x000f, length = 9 + strlen + 1 */
	write_value(len,&chksum);
	write_data(fname,len,&chksum);
	write_end(chksum);
	if (!InSysCall())
		LeaveCriticalSection(&ppfscs);    
	return;
}

#if defined(PPC)
#pragma optimize("", on)
#endif

⌨️ 快捷键说明

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