diff --git a/kernel/trunk/core/exports.inc b/kernel/trunk/core/exports.inc index 278e36565b..8bf11681df 100644 --- a/kernel/trunk/core/exports.inc +++ b/kernel/trunk/core/exports.inc @@ -85,6 +85,10 @@ iglobal szStrchr db 'strchr',0 szStrrchr db 'strrchr',0 + szDiskAdd db 'DiskAdd',0 + szDiskDel db 'DiskDel',0 + szDiskMediaChanged db 'DiskMediaChanged',0 + align 16 kernel_export: @@ -160,6 +164,10 @@ kernel_export: dd szStrchr , strchr dd szStrrchr , strrchr + dd szDiskAdd , disk_add + dd szDiskDel , disk_del + dd szDiskMediaChanged, disk_media_changed + exp_lfb: dd szLFBAddress , 0 dd 0 ;terminator, must be zero diff --git a/kernel/trunk/docs/drivers_api.txt b/kernel/trunk/docs/drivers_api.txt new file mode 100644 index 0000000000..9c71a1e420 --- /dev/null +++ b/kernel/trunk/docs/drivers_api.txt @@ -0,0 +1,75 @@ +All functions are stdcall unless mentioned otherwise. + +=== Disk === +The kernel exports the functions 'DiskAdd', 'DiskMediaChanged', 'DiskDel' for +drivers. They must be called in the following order: DiskAdd, then zero or +more DiskMediaChanged, then optionally DiskDel. The driver must not call +two functions in parallel, including two calls to DiskMediaChanged. + +void* DiskAdd(DISKFUNC* functions, const char* name, void* userdata, int flags); +; The pointer 'functions' must be valid at least until the disk will be deleted +; (until DISKFUNC.close is called). +; The pointer 'name' can be invalid after this function returns. +; It should point to ASCIIZ-string without leading '/' in latin lowercase and +; digits, like 'usbhd0'. +; The value 'userdata' is any pointer-sized data, passed as is to all +; callbacks. +DISK_NO_INSERT_NOTIFICATION = 1 +; The bitfield 'flags' has currently only one bit defined. If it is set, the +; driver will never call DiskMediaChanged(hDisk, true), so the kernel must scan +; for media insertion when the operation is requested. +struc DISKFUNC +{ + .strucsize dd ? + .close dd ? +; void close(void* userdata); +; Optional. +; The last function that is called for the given disk. The kernel calls it when +; the kernel has finished all operations with the disk and it is safe to free +; all driver-specific data identified by 'userdata'. + .closemedia dd ? +; void closemedia(void* userdata); +; Optional. +; The kernel calls this function when it finished all processing with the +; current media. If media is removed, the driver should decline all requests +; to that media with DISK_STATUS_NO_MEDIA, even if new media is inserted, +; until this function is called. If media is removed, a new call to +; DiskMediaChanged(hDisk, true) is not allowed until this function is called. + .querymedia dd ? +; int querymedia(void* userdata, DISKMEDIAINFO* info); +; return value: 0 = success, otherwise = error + .read dd ? +; int read(void* userdata, void* buffer, __int64 startsector, +; int* numsectors); +; return value: 0 = success, otherwise = error + .write dd ? +; int write(void* userdata, const void* buffer, __int64 startsector, +; int* numsectors); +; Optional. +; return value: 0 = success, otherwise = error + .flush dd ? +; int flush(void* userdata); +; Optional. +; Flushes the hardware cache, if it exists. Note that a driver should not +; implement a software cache for read/write, since they are called from the +; kernel cache manager. +} +struc DISKMEDIAINFO +{ + .flags dd ? +DISK_MEDIA_READONLY = 1 + .sectorsize dd ? + .capacity dq ? +} +void DiskDel(void* hDisk); +; This function informs the kernel that the disk should be deleted from the +; system. This function removes the disk from the global file system; however, +; it is possible that active operations with the disk are still running. When +; the disk is actually removed, the kernel calls the 'close' function, which +; can free all device-related resources. +void DiskMediaChanged(void* hDisk, int newstate); +; This function informs the kernel that a media has been inserted, removed or +; changed. 'newstate' should be zero if currently there is no media inserted +; and nonzero in the other case. This function must not be called with nonzero +; 'newstate' from any of callbacks. This function must not be called if another +; call to this function is active. diff --git a/kernel/trunk/fs/disk.inc b/kernel/trunk/fs/disk.inc index 39cce17be5..4a57c7e9be 100644 --- a/kernel/trunk/fs/disk.inc +++ b/kernel/trunk/fs/disk.inc @@ -633,10 +633,12 @@ lock dec [partition_buffer_users] ; no, we must allocate ; Note that 'read' callback operates with 64-bit sector numbers, so we must ; push additional zero as a high dword of sector number. mov al, DISKFUNC.read - stdcall disk_call_driver, ebx, ebp, 0, 1 + push 1 + stdcall disk_call_driver, ebx, ebp, 0, esp + pop ecx ; 6. If the read has failed, abort the loop. - test eax, eax - jz .mbr_failed + dec ecx + jnz .mbr_failed ; 7. Check the MBR/EBR signature. If it is wrong, abort the loop. ; Soon we will access the partition table which starts at ebx+0x1BE, ; so we can fill its address right now. If we do it now, then the addressing