#ifndef __KERNEL_DRIVER_H
#define __KERNEL_DRIVER_H
#ifdef __cplusplus
extern "C"
{
#endif
#include <sys/types.h>
#include <kernel/proc.h>
#include <kernel/handle.h>
/*!
* \ingroup kernel
* \defgroup dev Device Manager
* @{
*/
#include <os/devreq.h>
typedef struct request_t request_t;
//! Contains information on a request issued to a device driver
struct request_t
{
//! Specifies the request code (one of DEV_xxx)
dword code; // in
//! Indicates the result of the request
status_t result; // out
//! Triggered when the request has completed
handle_t* event; // out when calling devRequest;
// in wrt driver
//! Points to the next request in a driver's request list
request_t* next;
/* Internal members */
size_t user_length; // original user length
request_t *kernel_request; // in user mode, points to the copy made in kernel space
size_t original_request_size; // in kernel mode, the size of the original request
int queued; // is this request queued?
union
{
//! General parameters for a buffered request
struct
{
//! The buffer used
addr_t buffer;
//! Size of the buffer in bytes
size_t length;
//! The position where the buffered operation is to start
/*! Ignored for character stream devices. */
qword pos;
} buffered;
//! Parameters for a DEV_OPEN request
struct
{
//! Specifies the parameters passed to devOpen()
const wchar_t* params;
} open;
//! Parameters for a DEV_READ request
struct
{
//! Specifies the buffer into which data are read
void* buffer; // out
//! Specifies the number of bytes to read, and indicates the number
//! of bytes actually read
size_t length; // in/out
//! Specifies the offset where reading is to start
/*! Ignored for character stream devices. */
qword pos; // in
} read;
//! Parameters for a DEV_WRITE request
struct
{
//! Specifies the buffer from which data are written
const void* buffer; // in
//! Specifies the number of bytes to write, and indicates the number
//! of bytes actually written
size_t length; // in/out
//! Specifies the offset where writing is to start
/*! Ignored for character stream devices. */
qword pos; // in
} write;
//! Parameters for a DEV_IOCTL request
struct
{
//! Specifies a buffer containing ioctl parameters and data
void* buffer; // in/out
//! Specifies the size of the buffer
size_t length; // in/out
//! Specifies the IOCTL function to perform
dword code; // in
} ioctl;
//! Parameters for a DEV_ISR request
struct
{
//! Specifies the IRQ which was triggered
byte irq; // in
} isr;
//! Parameters for an FS_OPEN request
struct
{
const wchar_t* name; // in
size_t name_length; // in
struct file_t* fd; // out
} fs_open, fs_create;
//! Parameters for an FS_MOUNT request
struct
{
const wchar_t* name; // in
size_t name_length; // in
struct device_t* dev; // in
} fs_mount;
//! Parameters for FS_READ and FS_WRITE requests
struct
{
addr_t buffer; // out
size_t length; // in/out
struct file_t* fd; // in
} fs_read, fs_write, fs_getlength;
//! Parameters for an FS_CLOSE request
struct
{
struct file_t* fd; // in
} fs_close;
//! Parameters for a FS_IOCTL request
struct
{
//! Specifies a buffer containing ioctl parameters and data
void* buffer; // in/out
//! Specifies the size of the buffer
size_t length; // in/out
//! Specifies the IOCTL function to perform
dword code; // in
struct file_t* fd;
} fs_ioctl;
} params;
};
typedef struct device_t device_t;
typedef struct driver_t driver_t;
//! The prototype of the driver's request function
typedef bool (*DEVREQ)(device_t*, request_t*);
typedef struct device_config_t device_config_t;
//! The kernel structure used to contain information on each device
/*!
* Since it is the device driver's responsibility to allocate memory for this
* structure, the driver author may place additional fields after this
* structure. For example, it is possible to use an instance of this structure
* as the first member of a larger one.
*/
struct device_t
{
//! The driver that registered this device
driver_t* driver;
//! The function to be called for each device request
DEVREQ request;
//! Pointer to the device's first queued request, if any
request_t *req_first,
//! Pointer to the device's last queued request, if any
*req_last;
device_config_t *config;
};
typedef struct device_resource_t device_resource_t;
enum { dresMemory, dresIo, dresIrq };
struct device_resource_t
{
int cls;
union
{
struct
{
addr_t base;
size_t length;
} memory;
struct
{
addr_t base;
size_t length;
} io;
byte irq;
} u;
};
struct device_config_t
{
device_t *parent;
word vendor_id, device_id;
dword subsystem;
int num_resources;
device_resource_t *resources;
};
//! The kernel structure used to maintain each device driver DLL
struct driver_t
{
//! The module used to load this driver
module_t* mod;
device_t* (*add_device)(driver_t*, const wchar_t*, device_config_t*);
device_t* (*mount_fs)(driver_t*, const wchar_t*, device_t*);
};
device_t* devOpen(const wchar_t* name, const wchar_t* params);
bool devClose(device_t* dev);
bool devRemove(device_t* dev);
status_t devRequest(device_t* dev, request_t* req);
status_t devRequestSync(device_t* dev, request_t* req);
bool devRegisterIrq(device_t* dev, byte irq, bool install);
driver_t* devInstallNewDevice(const wchar_t* name, device_config_t* cfg);
bool devRegister(const wchar_t* name, device_t* dev, device_config_t* cfg);
void devStartRequest(device_t* dev, request_t* req);
void devFinishRequest(device_t* dev, request_t* req);
status_t devReadSync(device_t* dev, qword pos, void* buffer, size_t* length);
status_t devWriteSync(device_t* dev, qword pos, const void* buffer, size_t* length);
status_t devUserRequest(device_t* dev, request_t* req, size_t size);
status_t devUserFinishRequest(request_t* req, bool delete_event);
dword devFindResource(const device_config_t *cfg, int cls, int index);
#define devIsBufferedRequest(code) (((int) (code)) < 0)
bool STDCALL drvInit(driver_t*);
void msleep(dword ms);
//@}
/*!
* \defgroup drivers Device Drivers
*/
#ifdef __cplusplus
}
#endif
#endif