diff options
Diffstat (limited to 'tools/ioemu/iodev/harddrv.h')
-rw-r--r-- | tools/ioemu/iodev/harddrv.h | 765 |
1 files changed, 765 insertions, 0 deletions
diff --git a/tools/ioemu/iodev/harddrv.h b/tools/ioemu/iodev/harddrv.h new file mode 100644 index 0000000000..9320e614d5 --- /dev/null +++ b/tools/ioemu/iodev/harddrv.h @@ -0,0 +1,765 @@ +///////////////////////////////////////////////////////////////////////// +// $Id: harddrv.h,v 1.22.2.1 2004/02/06 22:14:36 danielg4 Exp $ +///////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2002 MandrakeSoft S.A. +// +// MandrakeSoft S.A. +// 43, rue d'Aboukir +// 75002 Paris - France +// http://www.linux-mandrake.com/ +// http://www.mandrakesoft.com/ +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +// SPARSE IMAGES HEADER +#define SPARSE_HEADER_MAGIC (0x02468ace) +#define SPARSE_HEADER_VERSION 1 +#define SPARSE_HEADER_SIZE (256) // Plenty of room for later +#define SPARSE_PAGE_NOT_ALLOCATED (0xffffffff) + + typedef struct + { + uint32 magic; + uint32 version; + uint32 pagesize; + uint32 numpages; + + uint32 padding[60]; + } sparse_header_t; + +#define STANDARD_HEADER_MAGIC "Bochs Virtual HD Image" +#define STANDARD_HEADER_VERSION (0x00010000) +#define STANDARD_HEADER_SIZE (512) + + + // WARNING : headers are kept in x86 (little) endianness + typedef struct + { + Bit8u magic[32]; + Bit8u type[16]; + Bit8u subtype[16]; + Bit32u version; + Bit32u header; + } standard_header_t; + +#define REDOLOG_TYPE "Redolog" +#define REDOLOG_SUBTYPE_UNDOABLE "Undoable" +#define REDOLOG_SUBTYPE_VOLATILE "Volatile" +#define REDOLOG_SUBTYPE_GROWING "Growing" +// #define REDOLOG_SUBTYPE_Z_UNDOABLE "z-Undoable" +// #define REDOLOG_SUBTYPE_Z_VOLATILE "z-Volatile" + +#define REDOLOG_PAGE_NOT_ALLOCATED (0xffffffff) + +#define UNDOABLE_REDOLOG_EXTENSION ".redolog" +#define UNDOABLE_REDOLOG_EXTENSION_LENGTH (strlen(UNDOABLE_REDOLOG_EXTENSION)) +#define VOLATILE_REDOLOG_EXTENSION ".XXXXXX" +#define VOLATILE_REDOLOG_EXTENSION_LENGTH (strlen(VOLATILE_REDOLOG_EXTENSION)) + + typedef struct + { + // the fields in the header are kept in little endian + Bit32u catalog; // #entries in the catalog + Bit32u bitmap; // bitmap size in bytes + Bit32u extent; // extent size in bytes + Bit64u disk; // disk size in bytes + } redolog_specific_header_t; + + typedef struct + { + standard_header_t standard; + redolog_specific_header_t specific; + + Bit8u padding[STANDARD_HEADER_SIZE - (sizeof (standard_header_t) + sizeof (redolog_specific_header_t))]; + } redolog_header_t; + +// htod : convert host to disk (little) endianness +// dtoh : convert disk (little) to host endianness +#if defined (BX_LITTLE_ENDIAN) +#define htod32(val) (val) +#define dtoh32(val) (val) +#define htod64(val) (val) +#define dtoh64(val) (val) +#else +#define htod32(val) ( (((val)&0xff000000)>>24) | (((val)&0xff0000)>>8) | (((val)&0xff00)<<8) | (((val)&0xff)<<24) ) +#define dtoh32(val) htod32(val) +#define htod64(val) ( (((val)&0xff00000000000000LL)>>56) | (((val)&0xff000000000000LL)>>40) | (((val)&0xff0000000000LL)>>24) | (((val)&0xff00000000LL)>>8) | (((val)&0xff000000LL)<<8) | (((val)&0xff0000LL)<<24) | (((val)&0xff00LL)<<40) | (((val)&0xffLL)<<56) ) +#define dtoh64(val) htod64(val) +#endif + +#ifndef INCLUDE_ONLY_HD_HEADERS + +typedef enum _sense { + SENSE_NONE = 0, SENSE_NOT_READY = 2, SENSE_ILLEGAL_REQUEST = 5, + SENSE_UNIT_ATTENTION = 6 +} sense_t; + +typedef enum _asc { + ASC_INV_FIELD_IN_CMD_PACKET = 0x24, + ASC_MEDIUM_NOT_PRESENT = 0x3a, + ASC_SAVING_PARAMETERS_NOT_SUPPORTED = 0x39, + ASC_LOGICAL_BLOCK_OOR = 0x21 +} asc_t; + +class LOWLEVEL_CDROM; + +class device_image_t +{ + public: + // Open a image. Returns non-negative if successful. + virtual int open (const char* pathname) = 0; + + // Close the image. + virtual void close () = 0; + + // Position ourselves. Return the resulting offset from the + // beginning of the file. + virtual off_t lseek (off_t offset, int whence) = 0; + + // Read count bytes to the buffer buf. Return the number of + // bytes read (count). + virtual ssize_t read (void* buf, size_t count) = 0; + + // Write count bytes from buf. Return the number of bytes + // written (count). + virtual ssize_t write (const void* buf, size_t count) = 0; + + unsigned cylinders; + unsigned heads; + unsigned sectors; +}; + +// FLAT MODE +class default_image_t : public device_image_t +{ + public: + // Open a image. Returns non-negative if successful. + int open (const char* pathname); + + // Open an image with specific flags. Returns non-negative if successful. + int open (const char* pathname, int flags); + + // Close the image. + void close (); + + // Position ourselves. Return the resulting offset from the + // beginning of the file. + off_t lseek (off_t offset, int whence); + + // Read count bytes to the buffer buf. Return the number of + // bytes read (count). + ssize_t read (void* buf, size_t count); + + // Write count bytes from buf. Return the number of bytes + // written (count). + ssize_t write (const void* buf, size_t count); + + private: + int fd; + +}; + +// CONCAT MODE +class concat_image_t : public device_image_t +{ + public: + // Default constructor + concat_image_t(); + + // Open a image. Returns non-negative if successful. + int open (const char* pathname); + + // Close the image. + void close (); + + // Position ourselves. Return the resulting offset from the + // beginning of the file. + off_t lseek (off_t offset, int whence); + + // Read count bytes to the buffer buf. Return the number of + // bytes read (count). + ssize_t read (void* buf, size_t count); + + // Write count bytes from buf. Return the number of bytes + // written (count). + ssize_t write (const void* buf, size_t count); + + private: +#define BX_CONCAT_MAX_IMAGES 8 + int fd_table[BX_CONCAT_MAX_IMAGES]; + off_t start_offset_table[BX_CONCAT_MAX_IMAGES]; + off_t length_table[BX_CONCAT_MAX_IMAGES]; + void increment_string (char *str); + int maxfd; // number of entries in tables that are valid + + // notice if anyone does sequential read or write without seek in between. + // This can be supported pretty easily, but needs additional checks. + // 0=something other than seek was last operation + // 1=seek was last operation + int seek_was_last_op; + + // the following variables tell which partial image file to use for + // the next read and write. + int index; // index into table + int fd; // fd to use for reads and writes + off_t thismin, thismax; // byte offset boundary of this image +}; + +// SPARSE MODE +class sparse_image_t : public device_image_t +{ + +// Format of a sparse file: +// 256 byte header, containing details such as page size and number of pages +// Page indirection table, mapping virtual pages to physical pages within file +// Physical pages till end of file + + public: + // Default constructor + sparse_image_t(); + + // Open a image. Returns non-negative if successful. + int open (const char* pathname); + + // Close the image. + void close (); + + // Position ourselves. Return the resulting offset from the + // beginning of the file. + off_t lseek (off_t offset, int whence); + + // Read count bytes to the buffer buf. Return the number of + // bytes read (count). + ssize_t read (void* buf, size_t count); + + // Write count bytes from buf. Return the number of bytes + // written (count). + ssize_t write (const void* buf, size_t count); + + private: + int fd; + +#ifdef _POSIX_MAPPED_FILES + void * mmap_header; + size_t mmap_length; + size_t system_pagesize_mask; +#endif + uint32 * pagetable; + + // Header is written to disk in little-endian (x86) format + // Thus needs to be converted on big-endian systems before read + // The pagetable is also kept little endian + + sparse_header_t header; + + uint32 pagesize; + int pagesize_shift; + uint32 pagesize_mask; + + off_t data_start; + off_t underlying_filesize; + + char * pathname; + + off_t position; + + uint32 position_virtual_page; + uint32 position_physical_page; + uint32 position_page_offset; + + off_t underlying_current_filepos; + + off_t total_size; + + void panic(const char * message); + off_t +#ifndef PARANOID + sparse_image_t:: +#endif + get_physical_offset(); + void +#ifndef PARANOID + sparse_image_t:: +#endif + set_virtual_page(uint32 new_virtual_page); + void read_header(); + ssize_t read_page_fragment(uint32 read_virtual_page, uint32 read_page_offset, size_t read_size, void * buf); + + sparse_image_t * parent_image; +}; + +#if EXTERNAL_DISK_SIMULATOR +#include "external-disk-simulator.h" +#endif + +#if DLL_HD_SUPPORT +class dll_image_t : public device_image_t +{ + public: + // Open a image. Returns non-negative if successful. + int open (const char* pathname); + + // Close the image. + void close (); + + // Position ourselves. Return the resulting offset from the + // beginning of the file. + off_t lseek (off_t offset, int whence); + + // Read count bytes to the buffer buf. Return the number of + // bytes read (count). + ssize_t read (void* buf, size_t count); + + // Write count bytes from buf. Return the number of bytes + // written (count). + ssize_t write (const void* buf, size_t count); + + private: + int vunit,vblk; + +}; +#endif + +// REDOLOG class +class redolog_t +{ + public: + redolog_t(); + int make_header (const char* type, Bit64u size); + int create (const char* filename, const char* type, Bit64u size); + int create (int filedes, const char* type, Bit64u size); + int open (const char* filename, const char* type, Bit64u size); + void close (); + + off_t lseek (off_t offset, int whence); + ssize_t read (void* buf, size_t count); + ssize_t write (const void* buf, size_t count); + + private: + void print_header(); + int fd; + redolog_header_t header; // Header is kept in x86 (little) endianness + Bit32u *catalog; + Bit8u *bitmap; + Bit32u extent_index; + Bit32u extent_offset; + Bit32u extent_next; + + Bit32u bitmap_blocs; + Bit32u extent_blocs; +}; + +// GROWING MODE +class growing_image_t : public device_image_t +{ + public: + // Contructor + growing_image_t(Bit64u size); + + // Open a image. Returns non-negative if successful. + int open (const char* pathname); + + // Close the image. + void close (); + + // Position ourselves. Return the resulting offset from the + // beginning of the file. + off_t lseek (off_t offset, int whence); + + // Read count bytes to the buffer buf. Return the number of + // bytes read (count). + ssize_t read (void* buf, size_t count); + + // Write count bytes from buf. Return the number of bytes + // written (count). + ssize_t write (const void* buf, size_t count); + + private: + redolog_t *redolog; + Bit64u size; +}; + +// UNDOABLE MODE +class undoable_image_t : public device_image_t +{ + public: + // Contructor + undoable_image_t(Bit64u size, const char* redolog_name); + + // Open a image. Returns non-negative if successful. + int open (const char* pathname); + + // Close the image. + void close (); + + // Position ourselves. Return the resulting offset from the + // beginning of the file. + off_t lseek (off_t offset, int whence); + + // Read count bytes to the buffer buf. Return the number of + // bytes read (count). + ssize_t read (void* buf, size_t count); + + // Write count bytes from buf. Return the number of bytes + // written (count). + ssize_t write (const void* buf, size_t count); + + private: + redolog_t *redolog; // Redolog instance + default_image_t *ro_disk; // Read-only flat disk instance + Bit64u size; + char *redolog_name; // Redolog name +}; + + +// VOLATILE MODE +class volatile_image_t : public device_image_t +{ + public: + // Contructor + volatile_image_t(Bit64u size, const char* redolog_name); + + // Open a image. Returns non-negative if successful. + int open (const char* pathname); + + // Close the image. + void close (); + + // Position ourselves. Return the resulting offset from the + // beginning of the file. + off_t lseek (off_t offset, int whence); + + // Read count bytes to the buffer buf. Return the number of + // bytes read (count). + ssize_t read (void* buf, size_t count); + + // Write count bytes from buf. Return the number of bytes + // written (count). + ssize_t write (const void* buf, size_t count); + + private: + redolog_t *redolog; // Redolog instance + default_image_t *ro_disk; // Read-only flat disk instance + Bit64u size; + char *redolog_name; // Redolog name + char *redolog_temp; // Redolog temporary file name +}; + + +#if BX_COMPRESSED_HD_SUPPORT + +#include <zlib.h> + + +// Default compressed READ-ONLY image class +class z_ro_image_t : public device_image_t +{ + public: + // Contructor + z_ro_image_t(); + + // Open a image. Returns non-negative if successful. + int open (const char* pathname); + + // Close the image. + void close (); + + // Position ourselves. Return the resulting offset from the + // beginning of the file. + off_t lseek (off_t offset, int whence); + + // Read count bytes to the buffer buf. Return the number of + // bytes read (count). + ssize_t read (void* buf, size_t count); + + // Write count bytes from buf. Return the number of bytes + // written (count). + ssize_t write (const void* buf, size_t count); + + private: + off_t offset; + int fd; + gzFile gzfile; + +}; + +// Z-UNDOABLE MODE +class z_undoable_image_t : public device_image_t +{ + public: + // Contructor + z_undoable_image_t(Bit64u size, const char* redolog_name); + + // Open a image. Returns non-negative if successful. + int open (const char* pathname); + + // Close the image. + void close (); + + // Position ourselves. Return the resulting offset from the + // beginning of the file. + off_t lseek (off_t offset, int whence); + + // Read count bytes to the buffer buf. Return the number of + // bytes read (count). + ssize_t read (void* buf, size_t count); + + // Write count bytes from buf. Return the number of bytes + // written (count). + ssize_t write (const void* buf, size_t count); + + private: + redolog_t *redolog; // Redolog instance + z_ro_image_t *ro_disk; // Read-only compressed flat disk instance + Bit64u size; + char *redolog_name; // Redolog name +}; + +// Z-VOLATILE MODE +class z_volatile_image_t : public device_image_t +{ + public: + // Contructor + z_volatile_image_t(Bit64u size, const char* redolog_name); + + // Open a image. Returns non-negative if successful. + int open (const char* pathname); + + // Close the image. + void close (); + + // Position ourselves. Return the resulting offset from the + // beginning of the file. + off_t lseek (off_t offset, int whence); + + // Read count bytes to the buffer buf. Return the number of + // bytes read (count). + ssize_t read (void* buf, size_t count); + + // Write count bytes from buf. Return the number of bytes + // written (count). + ssize_t write (const void* buf, size_t count); + + private: + redolog_t *redolog; // Redolog instance + z_ro_image_t *ro_disk; // Read-only compressed flat disk instance + Bit64u size; + char *redolog_name; // Redolog name + char *redolog_temp; // Redolog temporary file name +}; + +#endif + + +typedef struct { + struct { + bx_bool busy; + bx_bool drive_ready; + bx_bool write_fault; + bx_bool seek_complete; + bx_bool drq; + bx_bool corrected_data; + bx_bool index_pulse; + unsigned index_pulse_count; + bx_bool err; + } status; + Bit8u error_register; + Bit8u head_no; + union { + Bit8u sector_count; + struct { +#ifdef BX_LITTLE_ENDIAN + unsigned c_d : 1; + unsigned i_o : 1; + unsigned rel : 1; + unsigned tag : 5; +#else /* BX_BIG_ENDIAN */ + unsigned tag : 5; + unsigned rel : 1; + unsigned i_o : 1; + unsigned c_d : 1; +#endif + } interrupt_reason; + }; + Bit8u sector_no; + union { + Bit16u cylinder_no; + Bit16u byte_count; + }; + Bit8u buffer[2048]; + Bit32u buffer_index; + Bit32u drq_index; + Bit8u current_command; + Bit8u sectors_per_block; + Bit8u lba_mode; + struct { + bx_bool reset; // 0=normal, 1=reset controller + bx_bool disable_irq; // 0=allow irq, 1=disable irq + } control; + Bit8u reset_in_progress; + Bit8u features; + } controller_t; + +struct sense_info_t { + sense_t sense_key; + struct { + Bit8u arr[4]; + } information; + struct { + Bit8u arr[4]; + } specific_inf; + struct { + Bit8u arr[3]; + } key_spec; + Bit8u fruc; + Bit8u asc; + Bit8u ascq; +}; + +struct error_recovery_t { + unsigned char data[8]; + + error_recovery_t (); +}; + +uint16 read_16bit(const uint8* buf) BX_CPP_AttrRegparmN(1); +uint32 read_32bit(const uint8* buf) BX_CPP_AttrRegparmN(1); + + +#ifdef LOWLEVEL_CDROM +# include "cdrom.h" +#endif + + +struct cdrom_t +{ + bx_bool ready; + bx_bool locked; +#ifdef LOWLEVEL_CDROM + LOWLEVEL_CDROM* cd; +#endif + uint32 capacity; + int next_lba; + int remaining_blocks; + struct currentStruct { + error_recovery_t error_recovery; + } current; +}; + +struct atapi_t +{ + uint8 command; + int drq_bytes; + int total_bytes_remaining; +}; + +#if BX_USE_HD_SMF +# define BX_HD_SMF static +# define BX_HD_THIS theHardDrive-> +#else +# define BX_HD_SMF +# define BX_HD_THIS this-> +#endif + +typedef enum { + IDE_NONE, IDE_DISK, IDE_CDROM +} device_type_t; + +class bx_hard_drive_c : public bx_hard_drive_stub_c { +public: + + bx_hard_drive_c(void); + virtual ~bx_hard_drive_c(void); + virtual void close_harddrive(void); + virtual void init(); + virtual void reset(unsigned type); + virtual Bit32u get_device_handle(Bit8u channel, Bit8u device); + virtual Bit32u get_first_cd_handle(void); + virtual unsigned get_cd_media_status(Bit32u handle); + virtual unsigned set_cd_media_status(Bit32u handle, unsigned status); + + virtual Bit32u virt_read_handler(Bit32u address, unsigned io_len) { + return read_handler (this, address, io_len); + } + virtual void virt_write_handler(Bit32u address, + Bit32u value, unsigned io_len) + { + write_handler(this, address, value, io_len); + } +#if !BX_USE_HD_SMF + Bit32u read(Bit32u address, unsigned io_len); + void write(Bit32u address, Bit32u value, unsigned io_len); +#endif + + static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); + static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); + +private: + + BX_HD_SMF bx_bool calculate_logical_address(Bit8u channel, off_t *sector) BX_CPP_AttrRegparmN(2); + BX_HD_SMF void increment_address(Bit8u channel) BX_CPP_AttrRegparmN(1); + BX_HD_SMF void identify_drive(Bit8u channel); + BX_HD_SMF void identify_ATAPI_drive(Bit8u channel); + BX_HD_SMF void command_aborted(Bit8u channel, unsigned command); + + BX_HD_SMF void init_send_atapi_command(Bit8u channel, Bit8u command, int req_length, int alloc_length, bool lazy = false) BX_CPP_AttrRegparmN(3); + BX_HD_SMF void ready_to_send_atapi(Bit8u channel) BX_CPP_AttrRegparmN(1); + BX_HD_SMF void raise_interrupt(Bit8u channel) BX_CPP_AttrRegparmN(1); + BX_HD_SMF void atapi_cmd_error(Bit8u channel, sense_t sense_key, asc_t asc); + BX_HD_SMF void init_mode_sense_single(Bit8u channel, const void* src, int size); + BX_HD_SMF void atapi_cmd_nop(Bit8u channel) BX_CPP_AttrRegparmN(1); + + // FIXME: + // For each ATA channel we should have one controller struct + // and an array of two drive structs + struct channel_t { + struct drive_t { + device_image_t* hard_drive; + device_type_t device_type; + // 512 byte buffer for ID drive command + // These words are stored in native word endian format, as + // they are fetched and returned via a return(), so + // there's no need to keep them in x86 endian format. + Bit16u id_drive[256]; + + controller_t controller; + cdrom_t cdrom; + sense_info_t sense; + atapi_t atapi; + + Bit8u model_no[41]; + } drives[2]; + unsigned drive_select; + + Bit16u ioaddr1; + Bit16u ioaddr2; + Bit8u irq; + + } channels[BX_MAX_ATA_CHANNEL]; + +#if BX_PDC20230C_VLBIDE_SUPPORT +// pdc20630c is only available for 1st ata channel + struct pdc20630c_t { + bx_bool prog_mode; + Bit8u prog_count; + Bit32u p1f3_value; + Bit32u p1f4_value; + } pdc20230c; +#endif + + }; +#endif // INCLUDE_ONLY_SPARSE_HEADER + |