Starting to wire up readfile.

This commit is contained in:
Ben Vanik 2013-10-16 00:23:05 -07:00
parent da2f7f1ea5
commit 803e4998de
9 changed files with 223 additions and 82 deletions

View File

@ -13,24 +13,30 @@
#include <xenia/kernel/modules/xboxkrnl/objects/xevent.h> #include <xenia/kernel/modules/xboxkrnl/objects/xevent.h>
using namespace std;
using namespace xe; using namespace xe;
using namespace xe::kernel; using namespace xe::kernel;
using namespace xe::kernel::xboxkrnl; using namespace xe::kernel::xboxkrnl;
XAsyncRequest::XAsyncRequest( XAsyncRequest::XAsyncRequest(
XObject* object, KernelState* kernel_state, XObject* object,
CompletionCallback callback, void* callback_context) : CompletionCallback callback, void* callback_context) :
object_(object), kernel_state_(kernel_state), object_(object),
callback_(callback), callback_context_(callback_context), callback_(callback), callback_context_(callback_context),
wait_event_(0),
apc_routine_(0), apc_context_(0) { apc_routine_(0), apc_context_(0) {
object_->Retain(); object_->Retain();
} }
XAsyncRequest::~XAsyncRequest() { XAsyncRequest::~XAsyncRequest() {
if (wait_event_) { for (vector<XEvent*>::iterator it = wait_events_.begin();
wait_event_->Release(); it != wait_events_.end(); ++it) {
(*it)->Release();
} }
object_->Release(); object_->Release();
} }
void XAsyncRequest::AddWaitEvent(XEvent* ev) {
ev->Retain();
wait_events_.push_back(ev);
}

View File

@ -20,6 +20,7 @@ namespace xe {
namespace kernel { namespace kernel {
namespace xboxkrnl { namespace xboxkrnl {
class KernelState;
class XEvent; class XEvent;
class XObject; class XObject;
@ -29,24 +30,24 @@ public:
typedef void (*CompletionCallback)(XAsyncRequest* request, void* context); typedef void (*CompletionCallback)(XAsyncRequest* request, void* context);
XAsyncRequest( XAsyncRequest(
XObject* object, KernelState* kernel_state, XObject* object,
CompletionCallback callback, void* callback_context); CompletionCallback callback, void* callback_context);
virtual ~XAsyncRequest(); virtual ~XAsyncRequest();
KernelState* kernel_state() const { return kernel_state_; }
XObject* object() const { return object_; } XObject* object() const { return object_; }
XEvent* wait_event() const { return wait_event_; } void AddWaitEvent(XEvent* ev);
uint32_t apc_routine() const { return apc_routine_; }
uint32_t apc_context() const { return apc_context_; }
// Complete(result) // Complete(result)
protected: protected:
KernelState* kernel_state_;
XObject* object_; XObject* object_;
CompletionCallback callback_; CompletionCallback callback_;
void* callback_context_; void* callback_context_;
XEvent* wait_event_; std::vector<XEvent*> wait_events_;
uint32_t apc_routine_; uint32_t apc_routine_;
uint32_t apc_context_; uint32_t apc_context_;
}; };

View File

@ -13,10 +13,15 @@
#include <xenia/common.h> #include <xenia/common.h>
#include <xenia/core.h> #include <xenia/core.h>
#include <xenia/kernel/xbox.h>
namespace xe { namespace xe {
namespace kernel { namespace kernel {
namespace xboxkrnl { namespace xboxkrnl {
class XAsyncRequest;
namespace fs { namespace fs {
@ -67,6 +72,16 @@ public:
//virtual void Query() = 0; //virtual void Query() = 0;
X_STATUS Read(void* buffer, size_t buffer_length, size_t byte_offset,
size_t* out_bytes_read) {
return X_STATUS_NOT_IMPLEMENTED;
}
X_STATUS Read(void* buffer, size_t buffer_length, size_t byte_offset,
XAsyncRequest* request) {
// queue completion of failure
return X_STATUS_NOT_IMPLEMENTED;
}
virtual MemoryMapping* CreateMemoryMapping( virtual MemoryMapping* CreateMemoryMapping(
xe_file_mode file_mode, const size_t offset, const size_t length) = 0; xe_file_mode file_mode, const size_t offset, const size_t length) = 0;
}; };

View File

@ -9,6 +9,8 @@
#include <xenia/kernel/modules/xboxkrnl/objects/xfile.h> #include <xenia/kernel/modules/xboxkrnl/objects/xfile.h>
#include <xenia/kernel/modules/xboxkrnl/async_request.h>
#include <xenia/kernel/modules/xboxkrnl/fs/entry.h>
#include <xenia/kernel/modules/xboxkrnl/objects/xevent.h> #include <xenia/kernel/modules/xboxkrnl/objects/xevent.h>
@ -20,13 +22,41 @@ using namespace xe::kernel::xboxkrnl::fs;
XFile::XFile(KernelState* kernel_state, FileEntry* entry) : XFile::XFile(KernelState* kernel_state, FileEntry* entry) :
entry_(entry), entry_(entry),
position_(0),
XObject(kernel_state, kTypeFile) { XObject(kernel_state, kTypeFile) {
async_event_ = new XEvent(kernel_state);
async_event_->Initialize(false, false);
} }
XFile::~XFile() { XFile::~XFile() {
// TODO(benvanik): signal that the file is closing?
async_event_->Set(0, false);
async_event_->Delete();
}
X_STATUS XFile::Wait(uint32_t wait_reason, uint32_t processor_mode,
uint32_t alertable, uint64_t* opt_timeout) {
// Wait until some async operation completes.
return async_event_->Wait(
wait_reason, processor_mode, alertable, opt_timeout);
}
X_STATUS XFile::Read(void* buffer, size_t buffer_length, size_t byte_offset,
size_t* out_bytes_read) {
if (byte_offset == -1) {
// Read from current position.
}
X_STATUS result = entry_->Read(buffer, buffer_length, byte_offset, out_bytes_read);
if (XSUCCEEDED(result)) {
position_ += *out_bytes_read;
}
return result;
} }
X_STATUS XFile::Read(void* buffer, size_t buffer_length, size_t byte_offset, X_STATUS XFile::Read(void* buffer, size_t buffer_length, size_t byte_offset,
XAsyncRequest* request) { XAsyncRequest* request) {
return X_STATUS_ACCESS_DENIED; // Also tack on our event so that any waiters wake.
request->AddWaitEvent(async_event_);
position_ = byte_offset;
return entry_->Read(buffer, buffer_length, byte_offset, request);
} }

View File

@ -13,25 +13,41 @@
#include <xenia/kernel/modules/xboxkrnl/xobject.h> #include <xenia/kernel/modules/xboxkrnl/xobject.h>
#include <xenia/kernel/xbox.h> #include <xenia/kernel/xbox.h>
#include <xenia/kernel/modules/xboxkrnl/async_request.h>
#include <xenia/kernel/modules/xboxkrnl/fs/entry.h>
namespace xe { namespace xe {
namespace kernel { namespace kernel {
namespace xboxkrnl { namespace xboxkrnl {
class XAsyncRequest;
class XEvent;
namespace fs {
class FileEntry;
}
class XFile : public XObject { class XFile : public XObject {
public: public:
XFile(KernelState* kernel_state, fs::FileEntry* entry); XFile(KernelState* kernel_state, fs::FileEntry* entry);
virtual ~XFile(); virtual ~XFile();
virtual X_STATUS Wait(uint32_t wait_reason, uint32_t processor_mode,
uint32_t alertable, uint64_t* opt_timeout);
// TODO(benvanik): Create/Open
X_STATUS Read(void* buffer, size_t buffer_length, size_t byte_offset,
size_t* out_bytes_read);
X_STATUS Read(void* buffer, size_t buffer_length, size_t byte_offset, X_STATUS Read(void* buffer, size_t buffer_length, size_t byte_offset,
XAsyncRequest* request); XAsyncRequest* request);
private: private:
fs::FileEntry* entry_; fs::FileEntry* entry_;
XEvent* async_event_;
// TODO(benvanik): create flags, open state, etc.
size_t position_;
}; };

View File

@ -10,8 +10,10 @@
#include <xenia/kernel/modules/xboxkrnl/xboxkrnl_io.h> #include <xenia/kernel/modules/xboxkrnl/xboxkrnl_io.h>
#include <xenia/kernel/shim_utils.h> #include <xenia/kernel/shim_utils.h>
#include <xenia/kernel/modules/xboxkrnl/async_request.h>
#include <xenia/kernel/modules/xboxkrnl/kernel_state.h> #include <xenia/kernel/modules/xboxkrnl/kernel_state.h>
#include <xenia/kernel/modules/xboxkrnl/xboxkrnl_private.h> #include <xenia/kernel/modules/xboxkrnl/xboxkrnl_private.h>
#include <xenia/kernel/modules/xboxkrnl/objects/xevent.h>
#include <xenia/kernel/modules/xboxkrnl/objects/xfile.h> #include <xenia/kernel/modules/xboxkrnl/objects/xfile.h>
@ -105,6 +107,16 @@ SHIM_CALL NtOpenFile_shim(
SHIM_SET_RETURN(X_STATUS_NO_SUCH_FILE); SHIM_SET_RETURN(X_STATUS_NO_SUCH_FILE);
} }
class xeNtReadFileState {
public:
uint32_t x;
};
void xeNtReadFileCompleted(XAsyncRequest* request, xeNtReadFileState* state) {
// TODO(benvanik): set io_status_block_ptr
delete request;
delete state;
}
SHIM_CALL NtReadFile_shim( SHIM_CALL NtReadFile_shim(
xe_ppc_state_t* ppc_state, KernelState* state) { xe_ppc_state_t* ppc_state, KernelState* state) {
uint32_t file_handle = SHIM_GET_ARG_32(0); uint32_t file_handle = SHIM_GET_ARG_32(0);
@ -115,10 +127,10 @@ SHIM_CALL NtReadFile_shim(
uint32_t buffer = SHIM_GET_ARG_32(5); uint32_t buffer = SHIM_GET_ARG_32(5);
uint32_t buffer_length = SHIM_GET_ARG_32(6); uint32_t buffer_length = SHIM_GET_ARG_32(6);
uint32_t byte_offset_ptr = SHIM_GET_ARG_32(7); uint32_t byte_offset_ptr = SHIM_GET_ARG_32(7);
uint32_t key = SHIM_GET_ARG_32(8); size_t byte_offset = byte_offset_ptr ? SHIM_MEM_64(byte_offset_ptr) : 0;
XELOGD( XELOGD(
"NtReadFile(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %d, %d, %.8X)", "NtReadFile(%.8X, %.8X, %.8X, %.8X, %.8X, %.8X, %d, %d)",
file_handle, file_handle,
event_handle, event_handle,
apc_routine_ptr, apc_routine_ptr,
@ -126,24 +138,69 @@ SHIM_CALL NtReadFile_shim(
io_status_block_ptr, io_status_block_ptr,
buffer, buffer,
buffer_length, buffer_length,
byte_offset_ptr, byte_offset_ptr);
key);
// Async not supported yet. // Async not supported yet.
XEASSERTNULL(apc_routine_ptr); XEASSERTNULL(apc_routine_ptr);
X_STATUS result = X_STATUS_INVALID_HANDLE; X_STATUS result = X_STATUS_SUCCESS;
uint32_t info = 0; uint32_t info = 0;
// Grab event to signal.
XEvent* ev = NULL;
bool signal_event = false;
if (event_handle) {
result = state->object_table()->GetObject(
event_handle, (XObject**)&ev);
}
// Grab file.
XFile* file = NULL; XFile* file = NULL;
if (XSUCCEEDED(result)) {
result = state->object_table()->GetObject( result = state->object_table()->GetObject(
file_handle, (XObject**)&file); file_handle, (XObject**)&file);
if (result == X_STATUS_SUCCESS) { }
// TODO(benvanik): read!
file->Release(); // Execute read.
result = X_STATUS_SUCCESS; if (XSUCCEEDED(result)) {
info = 0; // number of bytes read // Reset event before we begin.
if (ev) {
ev->Reset();
}
// TODO(benvanik): async path.
if (true) {
// Synchronous request.
if (byte_offset == 0xFFFFFFFFfffffffe) {
// FILE_USE_FILE_POINTER_POSITION
byte_offset = -1;
}
// Read now.
size_t bytes_read = 0;
result = file->Read(
SHIM_MEM_ADDR(buffer), buffer_length, byte_offset,
&bytes_read);
if (XSUCCEEDED(result)) {
info = (int32_t)bytes_read;
}
// Mark that we should signal the event now. We do this after
// we have written the info out.
signal_event = true;
} else {
// X_STATUS_PENDING if not returning immediately.
// XFile is waitable and signalled after each async req completes.
// reset the input event (->Reset())
/*xeNtReadFileState* call_state = new xeNtReadFileState();
XAsyncRequest* request = new XAsyncRequest(
state, file,
(XAsyncRequest::CompletionCallback)xeNtReadFileCompleted,
call_state);*/
//result = file->Read(buffer, buffer_length, byte_offset, request);
result = X_STATUS_PENDING;
info = 0;
}
} }
if (io_status_block_ptr) { if (io_status_block_ptr) {
@ -151,6 +208,16 @@ SHIM_CALL NtReadFile_shim(
SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information SHIM_SET_MEM_32(io_status_block_ptr + 4, info); // Information
} }
if (file) {
file->Release();
}
if (ev) {
if (signal_event) {
ev->Set(0, false);
}
ev->Release();
}
SHIM_SET_RETURN(result); SHIM_SET_RETURN(result);
} }

View File

@ -73,6 +73,10 @@ void XObject::Release() {
} }
} }
X_STATUS XObject::Delete() {
return shared_kernel_state_->object_table()->RemoveHandle(handle_);
}
X_STATUS XObject::Wait(uint32_t wait_reason, uint32_t processor_mode, X_STATUS XObject::Wait(uint32_t wait_reason, uint32_t processor_mode,
uint32_t alertable, uint64_t* opt_timeout) { uint32_t alertable, uint64_t* opt_timeout) {
return X_STATUS_SUCCESS; return X_STATUS_SUCCESS;

View File

@ -57,6 +57,7 @@ public:
bool ReleaseHandle(); bool ReleaseHandle();
void Retain(); void Retain();
void Release(); void Release();
X_STATUS Delete();
// Reference() // Reference()
// Dereference() // Dereference()

View File

@ -33,6 +33,7 @@ typedef uint32_t X_STATUS;
#define X_STATUS_USER_APC ((uint32_t)0x000000C0L) #define X_STATUS_USER_APC ((uint32_t)0x000000C0L)
#define X_STATUS_ALERTED ((uint32_t)0x00000101L) #define X_STATUS_ALERTED ((uint32_t)0x00000101L)
#define X_STATUS_TIMEOUT ((uint32_t)0x00000102L) #define X_STATUS_TIMEOUT ((uint32_t)0x00000102L)
#define X_STATUS_PENDING ((uint32_t)0x00000103L)
#define X_STATUS_UNSUCCESSFUL ((uint32_t)0xC0000001L) #define X_STATUS_UNSUCCESSFUL ((uint32_t)0xC0000001L)
#define X_STATUS_NOT_IMPLEMENTED ((uint32_t)0xC0000002L) #define X_STATUS_NOT_IMPLEMENTED ((uint32_t)0xC0000002L)
#define X_STATUS_ACCESS_VIOLATION ((uint32_t)0xC0000005L) #define X_STATUS_ACCESS_VIOLATION ((uint32_t)0xC0000005L)