Skip to content

Commit

Permalink
usb: fix remaining USB issues for OHCI in terms of cross-page buffers
Browse files Browse the repository at this point in the history
  • Loading branch information
Meulengracht committed May 12, 2023
1 parent 6ec83a5 commit 0b8aa1b
Show file tree
Hide file tree
Showing 17 changed files with 204 additions and 124 deletions.
4 changes: 2 additions & 2 deletions librt/libc/io/open.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ __read_large(
TRACE("__read_large: aligning buffer=0x%" PRIxIN ", align=0x%" PRIxIN,
buffer, bytesToAlign);
oserr = __file_read(handle, buffer, bytesToAlign, bytesReadOut);
if (oserr != OS_EOK) {
if (oserr != OS_EOK || *bytesReadOut == 0) {
return oserr;
}
adjustedPointer = (void*)((uintptr_t)buffer + bytesToAlign);
Expand Down Expand Up @@ -302,7 +302,7 @@ __write_large(
TRACE("__write_large: aligning buffer=0x%" PRIxIN ", align=0x%" PRIxIN,
buffer, bytesToAlign);
oserr = __file_write(handle, buffer, bytesToAlign, bytesWrittenOut);
if (oserr != OS_EOK) {
if (oserr != OS_EOK|| *bytesWrittenOut == 0) {
return oserr;
}
adjustedPointer = (void*)((uintptr_t)buffer + bytesToAlign);
Expand Down
2 changes: 1 addition & 1 deletion librt/libc/os/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#define __TRACE
//#define __TRACE
#define __need_quantity

#include <assert.h>
Expand Down
15 changes: 8 additions & 7 deletions librt/libc/stdio/fwrite.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ __prewrite_buffer(

size_t fwrite(const void* vptr, size_t size, size_t count, FILE* stream)
{
size_t wrcnt = size * count;
int written = 0;
size_t wrcnt = size * count;
int written = 0;
const char* p = vptr;
TRACE("fwrite(count=%u)", wrcnt);

if (vptr == NULL || stream == NULL) {
Expand Down Expand Up @@ -81,12 +82,12 @@ size_t fwrite(const void* vptr, size_t size, size_t count, FILE* stream)
// Fill the buffer before continuing, and flush if neccessary.
if (__FILE_IsBuffered(stream) && __FILE_BufferPosition(stream) > 0) {
int bytesAvailable = stream->BufferSize - __FILE_BufferPosition(stream);
int bytesWritten = __prewrite_buffer(stream, vptr, (int)wrcnt);
int bytesWritten = __prewrite_buffer(stream, p, (int)wrcnt);
if (bytesWritten) {
TRACE("fwrite: wrote %i bytes to internal buffer", bytesWritten);
written += bytesWritten;
wrcnt -= bytesWritten;
vptr = (const char*)vptr + bytesWritten;
p += bytesWritten;
}

// Should we flush?
Expand Down Expand Up @@ -120,13 +121,13 @@ size_t fwrite(const void* vptr, size_t size, size_t count, FILE* stream)
// than what can fit in the buffer space, which means we just fill the buffer
// and move on, or we need to write more than can fit.
if (__FILE_IsBuffered(stream) && chunkSize < stream->BufferSize) {
bytesWritten = __prewrite_buffer(stream, vptr, chunkSize);
bytesWritten = __prewrite_buffer(stream, p, chunkSize);
if (bytesWritten > 0) {
stream->Flags |= _IOMOD;
}
} else {
TRACE("fwrite: writing %u bytes directly", chunkSize);
bytesWritten = write(stream->IOD, vptr, chunkSize);
bytesWritten = write(stream->IOD, p, chunkSize);
}
TRACE("fwrite: wrote %i bytes", bytesWritten);

Expand All @@ -136,7 +137,7 @@ size_t fwrite(const void* vptr, size_t size, size_t count, FILE* stream)
} else if (bytesWritten > 0) {
written += bytesWritten;
wrcnt -= bytesWritten;
vptr = (const char*)vptr + bytesWritten;
p += bytesWritten;
}
}
funlockfile(stream);
Expand Down
1 change: 1 addition & 0 deletions librt/libddk/include/ddk/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
/* Global <always-on> definitions
* These are enabled no matter which kind of debugging is enabled */
#define STR(str) str
#define NOTICE(...) SystemDebug(OSSYSLOGLEVEL_TRACE, __VA_ARGS__)
#define DEBUG(...) SystemDebug(OSSYSLOGLEVEL_DEBUG, __VA_ARGS__)
#define WARNING(...) SystemDebug(OSSYSLOGLEVEL_WARNING, __VA_ARGS__)
#define WARNING_IF(cond, ...) { if ((cond)) { SystemDebug(OSSYSLOGLEVEL_WARNING, __VA_ARGS__); } }
Expand Down
5 changes: 1 addition & 4 deletions modules/filesystems/mfs/directory_operations.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,7 @@ FsReadFromDirectory(
if (position == (entry->BucketByteBoundary + bucketSize)) {
TRACE("read_metrics::position %u, limit %u", LODWORD(position),
LODWORD(entry->BucketByteBoundary + bucketSize));
oserr = MFSAdvanceToNextBucket(
mfs, entry,
mfs->SectorsPerBucket * mfs->SectorSize
);
oserr = MFSAdvanceToNextBucket(mfs, entry);
if (oserr != OS_EOK) {
if (oserr == OS_ENOENT) {
oserr = OS_EOK;
Expand Down
30 changes: 17 additions & 13 deletions modules/filesystems/mfs/file_operations.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ FsReadFromFile(
// Do we need to switch bucket?
// We do if the position we have read to equals end of bucket
if (position == (entry->BucketByteBoundary + (entry->DataBucketLength * bucketSizeBytes))) {
oserr = MFSAdvanceToNextBucket(mfs, entry, bucketSizeBytes);
oserr = MFSAdvanceToNextBucket(mfs, entry);
if (oserr != OS_EOK) {
if (oserr == OS_ENOENT) {
oserr = OS_EOK;
Expand Down Expand Up @@ -226,6 +226,19 @@ FsWriteToFile(

// Write in a loop to make sure we write all requested bytes
while (bytesToWrite) {
// Determine whether we need to switch bucket as the first step of writing. Do
// this to avoid switching buckets when writing the last byte of a file. There will
// always be enough space to write because of Ensure.
TRACE("FsWriteToFile: position=0x%llx, boundary at 0x%llx",
position, (entry->BucketByteBoundary + (entry->DataBucketLength * bucketSizeBytes)));
if (position == (entry->BucketByteBoundary + (entry->DataBucketLength * bucketSizeBytes))) {
oserr = MFSAdvanceToNextBucket(mfs, entry);
if (oserr != OS_EOK) {
ERROR("FsWriteToFile: failed to get next data bucket: %u", oserr);
break;
}
}

// Calculate which bucket, then the sector offset
// Then calculate how many sectors of the bucket we need to read
uint64_t bucketSector = MFS_GETSECTOR(mfs, entry->DataBucketPosition);
Expand All @@ -236,6 +249,8 @@ FsWriteToFile(
size_t sectorsWritten;
size_t byteCount;

TRACE("FsWriteToFile: position=0x%llx, entry->BucketByteBoundary=0x%llx",
position, entry->BucketByteBoundary);
TRACE("FsWriteToFile: bucketSector=0x%llx, sectorIndex=0x%" PRIxIN ", sectorOffset=0x%llx",
bucketSector, bucketSectorOffset, sectorIndex);

Expand Down Expand Up @@ -341,23 +356,12 @@ FsWriteToFile(
byteCount = (mfs->SectorSize * sectorsWritten) - bucketSectorOffset;
}

TRACE("FsWriteToFile: written 0x%" PRIuIN " bytes", byteCount);
TRACE("FsWriteToFile: written %" PRIuIN " bytes", byteCount);
*unitsWritten += byteCount;
accumOffset += byteCount;
position += byteCount;
bytesToWrite -= byteCount;
}

// Do we need to switch bucket?
// We do if the position we have read to equals end of bucket
TRACE("FsWriteToFile: position=0x%llx, boundary at 0x%llx",
position, (entry->BucketByteBoundary + (entry->DataBucketLength * bucketSizeBytes)));
if (position == (entry->BucketByteBoundary + (entry->DataBucketLength * bucketSizeBytes))) {
oserr = MFSAdvanceToNextBucket(mfs, entry, bucketSizeBytes);
if (oserr != OS_EOK) {
break;
}
}
}

// Store the new position we've calculated during the read operation.
Expand Down
4 changes: 1 addition & 3 deletions modules/filesystems/mfs/mfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -321,14 +321,12 @@ MFSBucketMapSetLinkAndLength(
* @brief
* @param mfs
* @param entry
* @param bucketSizeBytes
* @return
*/
extern oserr_t
MFSAdvanceToNextBucket(
_In_ FileSystemMFS_t* mfs,
_In_ MFSEntry_t* entry,
_In_ size_t bucketSizeBytes);
_In_ MFSEntry_t* entry);

/* MfsZeroBucket
* Wipes the given bucket and count with zero values
Expand Down
49 changes: 30 additions & 19 deletions modules/filesystems/mfs/utilities.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,10 @@ MfsEnsureRecordSpace(
size_t sectorCount = (size_t)(DIVUP((spaceRequired - entry->AllocatedSize), mfs->SectorSize));
size_t bucketCount = DIVUP(sectorCount, mfs->SectorsPerBucket);
uint32_t bucketPointer, previousBucketPointer;
MapRecord_t iterator, link;
MapRecord_t iterator, record;

// Perform the allocation of buckets
if (MFSBucketMapAllocate(mfs, bucketCount, &link) != OS_EOK) {
if (MFSBucketMapAllocate(mfs, bucketCount, &record) != OS_EOK) {
ERROR("Failed to allocate %u buckets for file", bucketCount);
return OS_EDEVFAULT;
}
Expand All @@ -193,20 +193,24 @@ MfsEnsureRecordSpace(
while (bucketPointer != MFS_ENDOFCHAIN) {
previousBucketPointer = bucketPointer;
if (MFSBucketMapGetLengthAndLink(mfs, bucketPointer, &iterator) != OS_EOK) {
ERROR("MfsEnsureRecordSpace failed to get link for bucket %u", bucketPointer);
ERROR("MfsEnsureRecordSpace: failed to get record for bucket %u", bucketPointer);
return OS_EDEVFAULT;
}
bucketPointer = iterator.Link;
}

// We have a special case if previous == MFS_ENDOFCHAIN
if (previousBucketPointer == MFS_ENDOFCHAIN) {
TRACE("MfsEnsureRecordSpace: initializing record %ms to start=0x%x, length=0x%x",
entry->Name, record.Link, record.Length);
// This means file had nothing allocated
entry->StartBucket = link.Link;
entry->StartLength = link.Length;
entry->StartBucket = record.Link;
entry->StartLength = record.Length;
} else {
if (MFSBucketMapSetLinkAndLength(mfs, previousBucketPointer, link.Link, link.Length, true) != OS_EOK) {
ERROR("Failed to set link for bucket %u", previousBucketPointer);
TRACE("MfsEnsureRecordSpace: extending record %ms at bucket=0x%x with link=0x%x, length=0x%x",
entry->Name, previousBucketPointer, record.Link, record.Length);
if (MFSBucketMapSetLinkAndLength(mfs, previousBucketPointer, record.Link, 0, false) != OS_EOK) {
ERROR("Failed to set record for bucket %u", previousBucketPointer);
return OS_EDEVFAULT;
}
}
Expand All @@ -233,33 +237,40 @@ MFSCloneBucketData(
oserr_t
MFSAdvanceToNextBucket(
_In_ FileSystemMFS_t* mfs,
_In_ MFSEntry_t* entry,
_In_ size_t bucketSizeBytes)
_In_ MFSEntry_t* entry)
{
MapRecord_t link;
MapRecord_t record;
uint32_t nextDataBucketPosition;
size_t bucketSizeBytes = mfs->SectorsPerBucket * mfs->SectorSize;
size_t currentLinkLength;

// We have to look up the link for current bucket
if (MFSBucketMapGetLengthAndLink(mfs, entry->DataBucketPosition, &link) != OS_EOK) {
ERROR("MFSAdvanceToNextBucket failed to get link for bucket %u", entry->DataBucketPosition);
// We have to look up the record for current bucket
if (MFSBucketMapGetLengthAndLink(mfs, entry->DataBucketPosition, &record) != OS_EOK) {
ERROR("MFSAdvanceToNextBucket failed to get record for bucket %u", entry->DataBucketPosition);
return OS_EDEVFAULT;
}
TRACE("MFSAdvanceToNextBucket: bucket 0x%x, record=0x%x, length=0x%x",
entry->DataBucketPosition, record.Link, record.Length);

// Check for EOL
if (link.Link == MFS_ENDOFCHAIN) {
if (record.Link == MFS_ENDOFCHAIN) {
return OS_ENOENT;
}
nextDataBucketPosition = link.Link;

// Lookup length of link
if (MFSBucketMapGetLengthAndLink(mfs, entry->DataBucketPosition, &link) != OS_EOK) {
currentLinkLength = (record.Length * bucketSizeBytes);
nextDataBucketPosition = record.Link;

// Lookup length of record
if (MFSBucketMapGetLengthAndLink(mfs, record.Link, &record) != OS_EOK) {
ERROR("Failed to get length for bucket %u", entry->DataBucketPosition);
return OS_EDEVFAULT;
}
TRACE("MFSAdvanceToNextBucket: bucket 0x%x, record=0x%x, length=0x%x",
nextDataBucketPosition, record.Link, record.Length);

// Store length & Update bucket boundary
entry->BucketByteBoundary += currentLinkLength;
entry->DataBucketPosition = nextDataBucketPosition;
entry->DataBucketLength = link.Length;
entry->BucketByteBoundary += (link.Length * bucketSizeBytes);
entry->DataBucketLength = record.Length;
return OS_EOK;
}
4 changes: 4 additions & 0 deletions modules/serial/usb/common/transfer.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
#include <os/spinlock.h>
#include <threads.h>

#define __XPAGE(_a) ((_a) & ~((uintptr_t)0xFFF))
#define __XPAGEOFFSET(_a) ((_a) & 0xFFF)
#define __XUPPAGE(_a) (__XPAGE(_a) + 0x1000)

#define __USBTRANSFER_FLAG_SHORT 0x1
#define __USBTRANSFER_FLAG_NOTIFIED 0x2
#define __USBTRANSFER_FLAG_SILENT 0x4
Expand Down
2 changes: 1 addition & 1 deletion modules/serial/usb/ohci/structures/itd.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ OHCITDIsochronous(
iTd->Flags |= OHCI_TD_ACTIVE;

iTd->Cbp = element->Data.OHCI.Page0;
iTd->BufferEnd = element->Data.OHCI.Page1 + element->Data.OHCI.Offsets[frameCount - 1];
iTd->BufferEnd = element->Data.OHCI.Page1;
for (int i = 0; i < frameCount; i++) {
iTd->Offsets[i] = element->Data.OHCI.Offsets[i];
iTd->OriginalOffsets[i] = element->Data.OHCI.Offsets[i];
Expand Down
39 changes: 32 additions & 7 deletions modules/serial/usb/ohci/structures/td.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ OHCITDSetup(
_In_ OhciTransferDescriptor_t* td,
_In_ struct TransferElement* element)
{
TRACE("OHCITDSetup(dataAddress=0x%x)", dataAddress);
TRACE("OHCITDSetup(dataAddress=0x%x)", element->Data.OHCI.Page0 + element->Data.OHCI.Offsets[0]);

/**
* When calling these initializers for TDs, the TDs have already been
Expand Down Expand Up @@ -60,7 +60,7 @@ OHCITDData(
_In_ struct TransferElement* element,
_In_ int toggle)
{
TRACE("OHCITDData(length=%u)", length);
TRACE("OHCITDData(length=%u)", element->Length);

/**
* When calling these initializers for TDs, the TDs have already been
Expand Down Expand Up @@ -160,11 +160,36 @@ OHCITDVerify(
// Calculate length transferred
// Take into consideration the N-1
if (__Transfer_IsAsync(scanContext->Transfer) && td->BufferEnd != 0) {
int bytesTransferred;
int bytesRequested = (int)(td->BufferEnd - td->OriginalCbp) + 1;

if (td->Cbp == 0) bytesTransferred = bytesRequested;
else bytesTransferred = (int)(td->Cbp - td->OriginalCbp);
uint32_t bytesTransferred;
uint32_t bytesRequested;

// Is CBP and BE crossing a page?
if (__XPAGE(td->OriginalCbp) != __XPAGE(td->BufferEnd)) {
uint32_t bytesPage0 = __XUPPAGE(td->OriginalCbp) - td->OriginalCbp;
uint32_t bytesPage1 = __XPAGEOFFSET(td->BufferEnd);
bytesRequested = bytesPage0 + bytesPage1 + 1;

if (td->Cbp == 0) {
bytesTransferred = bytesRequested;
} else {
// Partial transfer, we need to determine whether Cbp is on the
// page 0 or 1
if (__XPAGE(td->Cbp) == __XPAGE(td->OriginalCbp)) {
bytesTransferred = td->Cbp - td->OriginalCbp;
} else {
// We still did cross transfer
bytesTransferred = bytesPage0 + __XPAGEOFFSET(td->Cbp);
}
}
} else {
// Otherwise all transfers are done in the same page, much easier.
bytesRequested = (td->BufferEnd - td->OriginalCbp) + 1;
if (td->Cbp == 0) {
bytesTransferred = bytesRequested;
} else {
bytesTransferred = td->Cbp - td->OriginalCbp;
}
}
TRACE("OHCITDVerify: td has transferred %i bytes", bytesTransferred);

if (bytesTransferred < bytesRequested) {
Expand Down
Loading

0 comments on commit 0b8aa1b

Please sign in to comment.