📄 fs_flash_single.c
字号:
/*
* FLASH low-level FS driver, that uses the FIRST flash.
*
* !!! IMPORTANT NOTE !!!
*
* Given that this uses the FIRST flash, care must be taken to make
* sure that the filesystem doesn't clobber any existing code/data,
* or the System ID-Block at the end of the flash.
*
* Therefor, to compute what to pass to fs_format(), use the following
* code:
long fs_start; // where to start the filesystem
fs_start = END_OF_XMEMORY; // start at the end of xmem
fs_start = fs_start / FS_BLOCK_SIZE; // divide out the blocksize, to meet the requirements for fs_format
if((fs_start * FS_BLOCK_SIZE) != END_OF_XMEMORY) {
// rounding error - we need to move up one block so we don't clobber the
// end of the xmem area
fs_start++;
}
* END_OF_XMEMORY is defined in the BIOS. This code will make sure the value is on
* a nice FS_BLOCSIZE boundary. Because the value computed might be modified from
* the actuall END_OF_XMEMORY, to place it on the block boundary, it might be
* necessary to reserve more space in the BIOS than is necessary, to still get the
* same number of block in your filesystem.
*
* Unfortunetly, though, END_OF_XMEMORY is usually set to be the size of
* the entire flash XMEM area, to allow DynamicC to use the entire flash
* for program code. Therefor, to use this filesystem, you need to
* explicitly change the value of END_OF_XMEMORY in the BIOS. This can be done
* through the macro XMEM_RESERVE_SIZE at the top of the BIOS, in rabbitbios.c.
*
*
*/
/*** BeginHeader fs_block_init */
/* size of the block */
#ifndef FS_BLOCK_SIZE
#define FS_BLOCK_SIZE 4096L
#endif
#define FS_SECTOR_SIZE fs_sector_size
#define FS_SECTORS_PER_BLOCK (((int)FS_BLOCK_SIZE)/FS_SECTOR_SIZE)
#define FS_TEMPBUF_SIZE 1024
int fs_block_init(long baseaddress, int num_blocks);
int fs_block_read(int block_num, int offset, char *buf, int len);
int fs_block_write(int block_num, char *buf, int len);
int fs_block_move(long to, int block, int offset, int len);
char *fs_block_pushxpc(int block_num);
extern int fs_sector_size;
/*** EndHeader */
int fs_sector_size;
long fs_block_baseaddress;
int fs_block_num_blocks;
int fs_sector_offset;
/*
* Initilize the low-level driver, starting at baseaddress (relative to start of flash),
* with num_blocks blocks of size FS_BLOCK_SIZE
*/
//nodebug
int fs_block_init(long baseaddress, int num_blocks)
{
auto int *id_tab;
auto unsigned long sizeMask, idBlockAddr;
auto unsigned long sectorMask, flashDst, len;
/* sanity check these values? */
#ifdef _RAM_
#error "Flash filesystem will not work in RAM - use the RAM filesystem."
#endif
#ifdef FS_DEBUG_FLASH
printf("Initilizing FLASH fs driver at offset: %lx\n",baseaddress);
#endif
fs_block_baseaddress = baseaddress;
fs_block_num_blocks = num_blocks;
/* get flash sector size */
if(_FlashInfo.sectorSize != 0) {
fs_sector_size = _FlashInfo.sectorSize;
#ifdef FS_DEBUG_FLASH
printf("Flash sector size == %d\n",fs_sector_size);
#endif
} else {
/* FLASH TYPE NOT FOUND! */
#ifdef FS_DEBUG_FLASH
printf("Unknown flash type!\n");
#endif
return 1;
}
/* verify the block size relative to the sector size */
fs_sector_offset = (int)(FS_BLOCK_SIZE / FS_SECTOR_SIZE);
if((FS_BLOCK_SIZE < FS_SECTOR_SIZE) ||
((FS_SECTOR_SIZE*fs_sector_offset) != FS_BLOCK_SIZE)
) {
#ifdef FS_DEBUG_FLASH
printf("FS_BLOCK_SIZE is not a multiple of FS_SECTOR_SIZE!\n");
#endif
return 1;
}
/* verify the sector boundary */
fs_sector_offset = (int)(baseaddress / FS_SECTOR_SIZE); /* offset into flash, in sectors */
if((long)fs_sector_offset*FS_SECTOR_SIZE != baseaddress) {
#ifdef FS_DEBUG_FLASH
printf("Not on sector boundary!\n(FS_SECTOR_SIZE == %x, baseaddress == %lx, fs_sector_offset == %x)\n",
FS_SECTOR_SIZE,baseaddress,fs_sector_offset);
#endif
return 1; /* not on FS_SECTOR_SIZE boundary */
}
// check for write attempt into ID blocks...
if (SysIDBlock.idBlockSize != 0x0000) {
idBlockAddr = (unsigned long)_FlashInfo.sectorSize *
(unsigned long)_FlashInfo.numSectors;
sizeMask = idBlockAddr - 0x0001ul;
idBlockAddr = (idBlockAddr - SysIDBlock.idBlockSize) & sizeMask;
// this variable is reused later for something else!
sectorMask = (unsigned long)_FlashInfo.sectorSize;
sectorMask = ~sectorMask + 0x01ul;
idBlockAddr = idBlockAddr & sectorMask;
flashDst = fs_block_baseaddress;
len = fs_block_num_blocks*FS_BLOCK_SIZE;
if ( ((flashDst & sizeMask) >= idBlockAddr) ||
(((flashDst + len) & sizeMask) > idBlockAddr) ||
((flashDst + len) >= ((unsigned long)_FlashInfo.sectorSize * (unsigned long)_FlashInfo.numSectors))) {
#ifdef FS_DEBUG_FLASH
printf("Filesystem will overwrite the system ID block!\n");
#endif
return 1; // attempt to write to flash ID blocks
}
}
return 0;
}
/*
* read from block_num/offset into buf/len
* offset == number of bytes from beginning of the block
*/
nodebug
int fs_block_read(int block_num, int offset, char *buf, int len)
{
/*
* check the checksum here
*
* crc == block[16] & block[17]
* first byte == block[2] & block[3]
* last byte == block[4] & block[5]
*/
#ifdef FS_DEBUG_FLASH
if(offset != 0)
printf("FLASH> Reading from block %d, offset %d, len %d\n",block_num,offset,len);
#endif
return xmem2root(buf, (block_num*FS_BLOCK_SIZE) + offset + fs_block_baseaddress, len);
}
/*
* Replacement for xmem2xmem() - move a block of data from flash to xmem
*/
nodebug
int fs_block_move(long to, int block, int offset, int len)
{
#ifdef FS_DEBUG_FLASH
printf("FLASH> Moving from block %d, offset %d, len %d\n",block,offset,len);
#endif
return xmem2xmem(to, (block*FS_BLOCK_SIZE) + offset + fs_block_baseaddress, len);
}
/*
* Write the given block (described in buf/len),
* to block number block_num (always start at offset=0 in the block)
*/
nodebug
int fs_block_write(int block_num, char *buf, int len)
{
#ifdef FS_DEBUG_FLASH
printf("FLASH> Writing block %d\n",block_num);
#endif
return WriteFlash(fs_block_baseaddress + (block_num*FS_BLOCK_SIZE), buf, len);
}
/*
* write a sector out. (buf is a physical address, probably in xmem)
*/
//nodebug
root useix int fs_writesector(int sector, long buf, int len)
{
static char saveXPC;
static char flashBase;
static int flashAddr,retval;
static long addr32,src;
src = buf;
#ifdef FS_DEBUG_FLASH
printf("FLASH> Writing sector %d, %d bytes, from address 0x%lx\n",sector,len,buf);
#endif
if(len > FS_SECTOR_SIZE) {
#ifdef FS_DEBUG_FLASH
printf("\tError: len <%d> is larger than FS_SECTOR_SIZE <%d>!\n",len,FS_SECTOR_SIZE);
#endif
return 1;
}
// calculate xpc and offset of flash as xmem address
addr32 = fs_block_baseaddress + (sector*FS_SECTOR_SIZE) -0xe000ul;
flashBase = (char)((addr32&0x000ff000L)>>12);
flashAddr = (unsigned)((addr32&0x00000fffL)|0xe000L);
//printf("\tTarget sector: %02x:%04x\n",flashBase,flashAddr);
#asm
; save the XPC
ld a,xpc
ld (saveXPC),a
; turn off interrupts
push ip
ipset 3
; store the data in the flashwrite buffer
c xmem2xmem(FLASH_BUF_PHYS, src, len);
c ;
; set the XPC window
ld a,(flashBase)
ld xpc,a
; write the flash sector - 'a' should still have the XPC value!
ld hl,(flashAddr) // put offset in hl
ex de,hl // WriteFlash expects it in de
call _WriteFlash
ld (retval),hl // hl has return value
; Restore interrupts...
pop ip
; ...and the XPC
ld a,(saveXPC)
ld xpc,a
#endasm
if(retval)
printf("\tretval was: %d\n",retval);
return retval;
}
/*
* set the XPC such that the given block is in the window, and
* return a pointer to the beginning of the block, as accessable
* through the xpc window.
*/
nodebug
root char *fs_block_pushxpc(int block_num)
{
auto unsigned long addr32;
auto unsigned xAddr;
auto char xBase;
// calculate xpc and offset of flash as xmem address
addr32 = (fs_block_baseaddress + (block_num*FS_BLOCK_SIZE))-0xe000ul;
xBase = (char)((addr32&0x000ff000L)>>12);
xAddr = (unsigned)((addr32&0x00000fffL)|0xe000L);
// store the new XPC
#asm
ld a,(xBase)
ld xpc,a
#endasm
/* return a pointer to the buffer */
return (char *)xAddr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -