mirror of
https://github.com/86Box/86Box.git
synced 2026-02-24 10:28:19 -07:00
Made ATAPI derived from SCSI. Added proper S/G emulation for SCSI DMA. Added SCSI CD-ROM emulation, preserving all the former ATAPI commands as well.
128 lines
2.7 KiB
C
128 lines
2.7 KiB
C
/* Copyright holders: SA1988
|
|
see COPYING for more details
|
|
*/
|
|
/*Scatter/Gather emulation*/
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "ibm.h"
|
|
|
|
#include "scattergather.h"
|
|
|
|
static uint8_t *SegmentBufferGet(SGBUF *SegmentBuf, uint32_t Data)
|
|
{
|
|
uint32_t DataSize;
|
|
uint8_t *Buffer;
|
|
|
|
if (SegmentBuf->SegmentIndex == SegmentBuf->SegmentNum
|
|
&& !SegmentBuf->SegmentLeft)
|
|
{
|
|
Data = 0;
|
|
return NULL;
|
|
}
|
|
|
|
DataSize = MIN(Data, SegmentBuf->SegmentLeft);
|
|
Buffer = SegmentBuf->SegmentPtrCur;
|
|
SegmentBuf->SegmentLeft -= Data;
|
|
|
|
if (!SegmentBuf->SegmentLeft)
|
|
{
|
|
SegmentBuf->SegmentIndex++;
|
|
|
|
if (SegmentBuf->SegmentIndex < SegmentBuf->SegmentNum)
|
|
{
|
|
SegmentBuf->SegmentPtrCur = SegmentBuf->SegmentPtr[SegmentBuf->SegmentIndex].Address;
|
|
SegmentBuf->SegmentLeft = SegmentBuf->SegmentPtr[SegmentBuf->SegmentIndex].Length;
|
|
}
|
|
|
|
Data = DataSize;
|
|
}
|
|
else
|
|
SegmentBuf->SegmentPtrCur = (uint8_t *)SegmentBuf->SegmentPtrCur + DataSize;
|
|
|
|
return Buffer;
|
|
}
|
|
|
|
uint8_t *SegmentBufferGetNextSegment(SGBUF *SegmentBuf, uint32_t Segment)
|
|
{
|
|
if (!Segment)
|
|
Segment = SegmentBuf->SegmentLeft;
|
|
|
|
return SegmentBufferGet(SegmentBuf, Segment);
|
|
}
|
|
|
|
uint32_t SegmentBufferCopy(SGBUF *SegmentDst, SGBUF *SegmentSrc, uint32_t Copy)
|
|
{
|
|
uint32_t Left = Copy;
|
|
while (Left)
|
|
{
|
|
uint32_t ThisCopy = MIN(MIN(SegmentDst->SegmentLeft, Left), SegmentSrc->SegmentLeft);
|
|
if (!ThisCopy)
|
|
break;
|
|
|
|
uint32_t Tmp = ThisCopy;
|
|
uint8_t *BufDst = SegmentBufferGet(SegmentDst, Tmp);
|
|
uint8_t *BufSrc = SegmentBufferGet(SegmentSrc, Tmp);
|
|
|
|
memcpy(BufSrc, BufDst, ThisCopy);
|
|
|
|
BufDst += ThisCopy;
|
|
BufSrc -= ThisCopy;
|
|
Left -= ThisCopy;
|
|
}
|
|
|
|
return Copy - Left;
|
|
}
|
|
|
|
uint32_t SegmentBufferCopyFromBuf(SGBUF *SegmentBuf, uint8_t *BufSrc, uint32_t Copy)
|
|
{
|
|
uint32_t Left = Copy;
|
|
|
|
while (Left)
|
|
{
|
|
uint32_t ThisCopy = Left;
|
|
uint8_t *BufDst = SegmentBufferGet(SegmentBuf, ThisCopy);
|
|
|
|
if (!ThisCopy)
|
|
break;
|
|
|
|
BufDst += ThisCopy;
|
|
Left -= ThisCopy;
|
|
BufSrc = (void *)((uintptr_t)BufSrc + ThisCopy);
|
|
}
|
|
|
|
return Copy - Left;
|
|
}
|
|
|
|
uint32_t SegmentBufferAdvance(SGBUF *SegmentBuf, uint32_t Advance)
|
|
{
|
|
uint32_t Left = Advance;
|
|
while (Left)
|
|
{
|
|
uint32_t ThisAdvance = Left;
|
|
SegmentBufferGet(SegmentBuf, ThisAdvance);
|
|
if (!ThisAdvance)
|
|
break;
|
|
|
|
Left -= ThisAdvance;
|
|
}
|
|
|
|
return Advance - Left;
|
|
}
|
|
|
|
void SegmentBufferInit(SGBUF *SegmentBuf, const SGSEG *SegmentPtr, uint32_t Segments)
|
|
{
|
|
SegmentBuf->SegmentPtr = SegmentPtr;
|
|
SegmentBuf->SegmentNum = (unsigned)Segments;
|
|
SegmentBuf->SegmentIndex = 0;
|
|
|
|
if (Segments && SegmentPtr)
|
|
{
|
|
SegmentBuf->SegmentPtrCur = SegmentPtr[0].Address;
|
|
SegmentBuf->SegmentLeft = SegmentPtr[0].Length;
|
|
}
|
|
else
|
|
{
|
|
SegmentBuf->SegmentPtrCur = NULL;
|
|
SegmentBuf->SegmentLeft = 0;
|
|
}
|
|
} |