mirror of
https://github.com/ipxe/ipxe
synced 2025-12-20 12:00:19 +03:00
Add the concept of a "user pointer" (similar to the void __user * in
the kernel), which encapsulates the information needed to refer to an external buffer. Under normal operation, this can just be a void * equivalent, but under -DKEEP_IT_REAL it would be a segoff_t equivalent. Use this concept to avoid the need for bounce buffers in int13.c, which reduces memory usage and opens up the possibility of using multi-sector reads. Extend the block-device API and the SCSI block device implementation to support multi-sector reads. Update iscsi.c to use user buffers. Move the obsolete portions of realmode.h to old_realmode.h. MS-DOS now boots an order of magnitude faster over iSCSI (~10 seconds from power-up to C:> prompt in bochs).
This commit is contained in:
@@ -8,6 +8,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <gpxe/uaccess.h>
|
||||
|
||||
/** A block device */
|
||||
struct block_device {
|
||||
/** Block size */
|
||||
@@ -19,21 +21,23 @@ struct block_device {
|
||||
*
|
||||
* @v blockdev Block device
|
||||
* @v block Block number
|
||||
* @v count Block count
|
||||
* @v buffer Data buffer
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int ( * read ) ( struct block_device *blockdev, uint64_t block,
|
||||
void *buffer );
|
||||
unsigned long count, userptr_t buffer );
|
||||
/**
|
||||
* Write block
|
||||
*
|
||||
* @v blockdev Block device
|
||||
* @v block Block number
|
||||
* @v count Block count
|
||||
* @v buffer Data buffer
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int ( * write ) ( struct block_device *blockdev, uint64_t block,
|
||||
const void *buffer );
|
||||
unsigned long count, userptr_t buffer );
|
||||
};
|
||||
|
||||
#endif /* _GPXE_BLOCKDEV_H */
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <gpxe/blockdev.h>
|
||||
#include <gpxe/uaccess.h>
|
||||
|
||||
/**
|
||||
* @defgroup scsiops SCSI operation codes
|
||||
@@ -123,14 +124,14 @@ struct scsi_command {
|
||||
/** CDB for this command */
|
||||
union scsi_cdb cdb;
|
||||
/** Data-out buffer (may be NULL) */
|
||||
const void *data_out;
|
||||
userptr_t data_out;
|
||||
/** Data-out buffer length
|
||||
*
|
||||
* Must be zero if @c data_out is NULL
|
||||
*/
|
||||
size_t data_out_len;
|
||||
/** Data-in buffer (may be NULL) */
|
||||
void *data_in;
|
||||
userptr_t data_in;
|
||||
/** Data-in buffer length
|
||||
*
|
||||
* Must be zero if @c data_in is NULL
|
||||
|
||||
24
src/include/gpxe/uaccess.h
Normal file
24
src/include/gpxe/uaccess.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef _GPXE_UACCESS_H
|
||||
#define _GPXE_UACCESS_H
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Access to external ("user") memory
|
||||
*
|
||||
* gPXE often needs to transfer data between internal and external
|
||||
* buffers. On i386, the external buffers may require access via a
|
||||
* different segment, and the buffer address cannot be encoded into a
|
||||
* simple void * pointer. The @c userptr_t type encapsulates the
|
||||
* information needed to identify an external buffer, and the
|
||||
* copy_to_user() and copy_from_user() functions provide methods for
|
||||
* transferring data between internal and external buffers.
|
||||
*
|
||||
* Note that userptr_t is an opaque type; in particular, performing
|
||||
* arithmetic upon a userptr_t is not allowed.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <bits/uaccess.h>
|
||||
|
||||
#endif /* _GPXE_UACCESS_H */
|
||||
Reference in New Issue
Block a user