📄 biosial.c
字号:
return MV_TRUE;
}
/*******************************************************************************
* waitForKeystroke - Wait for a key pressed by user
*
*
* DESCRIPTION:
* Utilizes BIOS 8 interrupt 16h, this function waits for a key pressed
* by the user
*
* INPUT:
* None
*
* RETURN:
* None
*
*******************************************************************************/
void waitForKeystroke (void)
{
_asm
{
pusha
mov ah, 0x0
waitForKeystrok_:
int 0x16
cmp al, 0
je waitForKeystrok_
popa
nop
nop
}
}
/*******************************************************************************
* readSegmentOffset8bit - Read 8bit from pointer indicated by segment:offset
*
*
* DESCRIPTION:
* Read 16bit from pointer indicated by segment:offset
*
* INPUT:
* segment_ - Segment of requested data
* offset_ - Offset within the segment of the request data
*
* RETURN:
* 8bit of data that is requested
*
*******************************************************************************/
unsigned char readSegmentOffset8bit (unsigned short segment_, unsigned short offset_)
{
unsigned char value = 0;
_asm
{
pusha
push fs
mov di, segment_
mov fs,di
mov di, offset_
mov cl, fs:[di]
mov value, cl
pop fs
popa
}
return value;
}
/*******************************************************************************
* writeSegmentOffset8bit - Writes 8bit to a 8bit memory indicated by segment:offset
*
*
* DESCRIPTION:
* Read 16bit from pointer indicated by segment:offset
*
* INPUT:
* segment_ - Segment of the memory to write to
* offset_ - Offset within the segment of the request data
* value_ - Value of the data to be written
*
* RETURN:
* None
*
*******************************************************************************/
void writeSegmentOffset8bit (unsigned short segment_, unsigned short offset_, unsigned char value_)
{
_asm
{
pusha
push fs
mov di, segment_
mov fs,di
mov di, offset_
mov cl, value_
mov fs:[di], cl
pop fs
popa
}
return;
}
/*******************************************************************************
* readSegmentOffset16bit - Read 16bit from pointer indicated by segment:offset
*
*
* DESCRIPTION:
* Read 16bit from pointer indicated by segment:offset
*
* INPUT:
* segment_ - Segment of requested data
* offset_ - Offset within the segment of the request data
*
* RETURN:
* 16bit of data that is requested
*
*******************************************************************************/
unsigned short readSegmentOffset16bit (unsigned short segment_, unsigned short offset_)
{
unsigned short value = 0;
_asm
{
pusha
push fs
mov di, segment_
mov fs,di
mov di, offset_
mov cx, fs:[di]
mov value, cx
pop fs
popa
}
return value;
}
/*******************************************************************************
* writeSegmentOffset16bit - Writes 16bit to a 16bit memory indicated by segment:offset
*
*
* DESCRIPTION:
* Read 16bit from pointer indicated by segment:offset
*
* INPUT:
* segment_ - Segment of the memory to write to
* offset_ - Offset within the segment of the request data
* value_ - Value of the data to be written
*
* RETURN:
* None
*
*******************************************************************************/
void writeSegmentOffset16bit (unsigned short segment_, unsigned short offset_, unsigned short value_)
{
_asm
{
pusha
push fs
mov di, segment_
mov fs,di
mov di, offset_
mov cx, value_
mov fs:[di], cx
pop fs
popa
}
return;
}
/*******************************************************************************
* memcpySegmentOffset32bitForward - Memory copy within segment
*
*
* DESCRIPTION:
* Copies memory from source to destination within same segment, each read
* write of 32 bit. The copy process is done from the end of the buffer
* to the start, due to overlapping issues.
*
* INPUT:
* segment_ - Segment of requested data
* offset_ - Offset within the segment of the request data
*
* RETURN:
* 16bit of data that is requested
*
*******************************************************************************/
void memcpySegmentOffset32bitForward (unsigned short segment_,
unsigned short destinationOffset_,
unsigned short sourceOffset_,
unsigned short byteCount_)
{
_asm
{
pusha
push fs
push ecx
mov di, segment_
mov fs,di
mov di, destinationOffset_
mov si, sourceOffset_
mov ax, byteCount_
add di, ax
add si, ax
copyLoop:
sub di, 4
sub si, 4
mov ecx, fs:[si]
mov fs:[di], ecx
sub ax, 4
jnz copyLoop
pop ecx
pop fs
popa
}
}
#define WRITE_ATA_COMMAND_REG(addr, data, reg, isLast) \
do{ \
*(addr) = MV_CPU_TO_LE16((((MV_U8)(data)) & 0xff) | ((reg) << 8) | (isLast)); \
} while(0)
/* Calculate the base address of the registers for a SATA channel */
MV_U32 edmaRegOffst[MV_SATA_CHANNELS_NUM] = {0x22000, 0x24000, 0x26000, 0x28000,
0x32000, 0x34000, 0x36000, 0x38000};
#define getEdmaRegOffset(x) edmaRegOffst[(x)]
MV_U32 generate32Addr (MV_U16 segment, MV_U16 offset)
{
MV_U32 addr = 0;
addr = (((MV_U32)segment) << 4) & 0x000ffff0;
addr = addr + (MV_U32) offset;
return addr;
}
MV_U8 requestIO (MV_U8 channelIndex, MV_U8 PMPort,
MV_U32 lowLBAAddress, MV_U16 highLBAAddress, MV_U16 sectorCount,
MV_UDMA_TYPE readWrite, MV_U16 bufferSegment, MV_U16 bufferOffset)
{
volatile MV_U16 *pCommand;
MV_SATA_EDMA_PRD_ENTRY *prdTable;
MV_DMA_REQUEST_QUEUE_ENTRY *pReqEntry;
MV_U32 edmaRegsOffset;
MV_U32 reqQEdmaAddr;
MV_U16 stackSegment = 0;
MV_U16 savedDataSegment = 0;
MV_U16 timerBase, timerChanges;
MV_U8 ATAStatus;
MV_BOOLEAN isEXT;
MV_U32 edmaErrorCause;
MV_U8 bufferAllignment;
MV_U8 savedBufferAllignment[8]; /* Used for 8byte buffer allignment */
MV_U8 temp;
MV_U32 bufferIOAddr = generate32Addr(bufferSegment, bufferOffset);
/*
* The following allocation is for PRD table and an EDMA request
* queue entry. The request queue entry is also used for the
* response queue completion entry.
* The PRD table and the request queue must be 32 byte alligned,
* so we need to allocate 32*3 for the allignment.
*/
unsigned char buffer[32*3];
edmaRegsOffset = getEdmaRegOffset(channelIndex);
/* Allign PRD table to 32 bytes */
prdTable = (MV_SATA_EDMA_PRD_ENTRY *)(((MV_U16)buffer & 0xfff0) + 0x10);
/* Request queue entry is 32bytes off the PRD table */
pReqEntry = (MV_DMA_REQUEST_QUEUE_ENTRY *)(((MV_U16)buffer & 0xfff0) + 0x30);
bufferAllignment = (MV_U8) bufferIOAddr & (requestedAllignment - 1);
/* If not 32 byte alligned then add another 16byte */
_asm {
mov stackSegment, ss
mov savedDataSegment, ds
mov ds, stackSegment
}
if((generate32Addr (stackSegment, (MV_U16)prdTable) & MV_BIT4))
{
prdTable = (MV_SATA_EDMA_PRD_ENTRY *)((MV_U16) prdTable + 0x10);
pReqEntry = (MV_DMA_REQUEST_QUEUE_ENTRY *)((MV_U16) pReqEntry + 0x10);
}
/* Populate the PRD table */
prdTable[0].highBaseAddr = 0;
prdTable[0].lowBaseAddr = bufferIOAddr - (MV_U32)bufferAllignment;
prdTable[0].byteCount = (MV_U16) (sectorCount * 512);
prdTable[0].flags = MV_EDMA_PRD_EOT_FLAG;
prdTable[0].reserved = 0;
/* Save the data for allignment */
for(temp = 0 ; temp < bufferAllignment ; temp ++)
{
savedBufferAllignment[temp] =
readSegmentOffset8bit(bufferSegment,
(bufferOffset - bufferAllignment) + temp);
}
/* Populate the request queue entry */
pReqEntry->prdHighAddr = 0;
pReqEntry->prdLowAddr = generate32Addr (stackSegment, (MV_U16)prdTable);
reqQEdmaAddr = generate32Addr (stackSegment, (MV_U16)pReqEntry);
pCommand = &pReqEntry->command[0];
if((lowLBAAddress + (MV_U32)sectorCount) & 0xf0000000)
{ /* Use LBA48 */
isEXT = MV_TRUE;
} else
{
isEXT = MV_FALSE;
}
/* Set the direction of the transaction (read/write) */
pReqEntry->controlFlags = (readWrite == MV_UDMA_TYPE_READ) ? 0x1 : 0x0;
pReqEntry->controlFlags |= ((((MV_U16)PMPort) & 0x000f) << 12);
if(isEXT == MV_TRUE)
{ /* READ/WRITE DMA EXT */
WRITE_ATA_COMMAND_REG(pCommand++,
(sectorCount & 0xFF00) >> 8,
MV_EDMA_ATA_SECTOR_COUNT_ADDR, 0);
WRITE_ATA_COMMAND_REG(pCommand++,
(sectorCount) & 0xFF,
MV_EDMA_ATA_SECTOR_COUNT_ADDR, 0);
WRITE_ATA_COMMAND_REG(pCommand++,
(lowLBAAddress & 0xFF000000)
>> 24,
MV_EDMA_ATA_LBA_LOW_ADDR, 0);
WRITE_ATA_COMMAND_REG(pCommand++,
(lowLBAAddress) &0xFF,
MV_EDMA_ATA_LBA_LOW_ADDR, 0);
WRITE_ATA_COMMAND_REG(pCommand++,
(highLBAAddress & 0xFF),
MV_EDMA_ATA_LBA_MID_ADDR, 0);
WRITE_ATA_COMMAND_REG(pCommand++,
(lowLBAAddress & 0xFF00) >> 8,
MV_EDMA_ATA_LBA_MID_ADDR, 0);
WRITE_ATA_COMMAND_REG(pCommand++,
(highLBAAddress & 0xFF00) >> 8,
MV_EDMA_ATA_LBA_HIGH_ADDR, 0);
WRITE_ATA_COMMAND_REG(pCommand++,
(lowLBAAddress & 0xFF0000)
>> 16,
MV_EDMA_ATA_LBA_HIGH_ADDR, 0);
WRITE_ATA_COMMAND_REG(pCommand++, MV_BIT6, MV_EDMA_ATA_DEVICE_ADDR,
0);
if(readWrite == MV_UDMA_TYPE_READ)
{
WRITE_ATA_COMMAND_REG(pCommand++, MV_ATA_COMMAND_READ_DMA_EXT,
MV_EDMA_ATA_COMMAND_ADDR, MV_BIT15);
} else
{
WRITE_ATA_COMMAND_REG(pCommand++, MV_ATA_COMMAND_WRITE_DMA_EXT,
MV_EDMA_ATA_COMMAND_ADDR, MV_BIT15);
}
} else
{ /* READ/WRITE DMA */
WRITE_ATA_COMMAND_REG(pCommand++,
(sectorCount) & 0xFF,
MV_EDMA_ATA_SECTOR_COUNT_ADDR, 0);
WRITE_ATA_COMMAND_REG(pCommand++,
(lowLBAAddress) & 0xFF,
MV_EDMA_ATA_LBA_LOW_ADDR, 0);
WRITE_ATA_COMMAND_REG(pCommand++,
(lowLBAAddress & 0xFF00) >> 8,
MV_EDMA_ATA_LBA_MID_ADDR, 0);
WRITE_ATA_COMMAND_REG(pCommand++,
(lowLBAAddress & 0xFF0000)
>> 16,
MV_EDMA_ATA_LBA_HIGH_ADDR, 0);
WRITE_ATA_COMMAND_REG(pCommand++,
MV_BIT6 | (MV_U8)((lowLBAAddress &
0xF000000) >> 24),
MV_EDMA_ATA_DEVICE_ADDR, 0);
if(readWrite == MV_UDMA_TYPE_READ)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -