2001-10-03 17:10:38 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
2011-02-25 01:05:47 +03:00
|
|
|
// $Id$
|
2001-10-03 17:10:38 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
2011-06-13 13:32:39 +04:00
|
|
|
// Copyright (C) 2002-2011 The Bochs Project
|
2001-04-10 05:04:59 +04:00
|
|
|
//
|
|
|
|
// 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
|
2009-02-08 12:05:52 +03:00
|
|
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2006-03-07 21:16:41 +03:00
|
|
|
#ifndef BX_IODEV_HDDRIVE_H
|
|
|
|
#define BX_IODEV_HDDRIVE_H
|
|
|
|
|
2006-07-13 21:34:44 +04:00
|
|
|
#define MAX_MULTIPLE_SECTORS 16
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
typedef enum _sense {
|
2002-02-03 23:49:44 +03:00
|
|
|
SENSE_NONE = 0, SENSE_NOT_READY = 2, SENSE_ILLEGAL_REQUEST = 5,
|
|
|
|
SENSE_UNIT_ATTENTION = 6
|
2001-04-10 05:04:59 +04:00
|
|
|
} sense_t;
|
|
|
|
|
|
|
|
typedef enum _asc {
|
2005-10-02 14:16:54 +04:00
|
|
|
ASC_ILLEGAL_OPCODE = 0x20,
|
|
|
|
ASC_LOGICAL_BLOCK_OOR = 0x21,
|
2001-04-10 05:04:59 +04:00
|
|
|
ASC_INV_FIELD_IN_CMD_PACKET = 0x24,
|
2009-04-21 14:18:42 +04:00
|
|
|
ASC_MEDIUM_MAY_HAVE_CHANGED = 0x28,
|
2001-04-10 05:04:59 +04:00
|
|
|
ASC_SAVING_PARAMETERS_NOT_SUPPORTED = 0x39,
|
2005-10-02 14:16:54 +04:00
|
|
|
ASC_MEDIUM_NOT_PRESENT = 0x3a
|
2001-04-10 05:04:59 +04:00
|
|
|
} asc_t;
|
|
|
|
|
2005-11-06 14:07:01 +03:00
|
|
|
class device_image_t;
|
2001-04-10 05:04:59 +04:00
|
|
|
class LOWLEVEL_CDROM;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
struct {
|
2002-10-25 15:44:41 +04:00
|
|
|
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;
|
2001-04-10 05:04:59 +04:00
|
|
|
unsigned index_pulse_count;
|
2002-10-25 15:44:41 +04:00
|
|
|
bx_bool err;
|
2006-12-25 12:34:32 +03:00
|
|
|
} status;
|
2001-04-10 05:04:59 +04:00
|
|
|
Bit8u error_register;
|
|
|
|
Bit8u head_no;
|
|
|
|
union {
|
|
|
|
Bit8u sector_count;
|
|
|
|
struct {
|
2001-08-13 19:48:13 +04:00
|
|
|
#ifdef BX_LITTLE_ENDIAN
|
2001-04-10 05:04:59 +04:00
|
|
|
unsigned c_d : 1;
|
|
|
|
unsigned i_o : 1;
|
|
|
|
unsigned rel : 1;
|
|
|
|
unsigned tag : 5;
|
2001-08-13 19:48:13 +04:00
|
|
|
#else /* BX_BIG_ENDIAN */
|
|
|
|
unsigned tag : 5;
|
|
|
|
unsigned rel : 1;
|
|
|
|
unsigned i_o : 1;
|
|
|
|
unsigned c_d : 1;
|
|
|
|
#endif
|
2001-04-10 05:04:59 +04:00
|
|
|
} interrupt_reason;
|
|
|
|
};
|
|
|
|
Bit8u sector_no;
|
|
|
|
union {
|
|
|
|
Bit16u cylinder_no;
|
|
|
|
Bit16u byte_count;
|
|
|
|
};
|
2006-07-13 21:34:44 +04:00
|
|
|
Bit8u buffer[MAX_MULTIPLE_SECTORS*512 + 4];
|
2005-11-01 22:10:24 +03:00
|
|
|
Bit32u buffer_size;
|
2002-08-05 19:51:06 +04:00
|
|
|
Bit32u buffer_index;
|
|
|
|
Bit32u drq_index;
|
2001-04-10 05:04:59 +04:00
|
|
|
Bit8u current_command;
|
2006-07-13 21:34:44 +04:00
|
|
|
Bit8u multiple_sectors;
|
2011-04-02 17:19:52 +04:00
|
|
|
bx_bool lba_mode;
|
2005-10-30 17:14:03 +03:00
|
|
|
bx_bool packet_dma;
|
2006-07-19 23:18:42 +04:00
|
|
|
Bit8u mdma_mode;
|
2006-12-29 14:57:04 +03:00
|
|
|
Bit8u udma_mode;
|
2001-04-10 05:04:59 +04:00
|
|
|
struct {
|
2002-10-25 15:44:41 +04:00
|
|
|
bx_bool reset; // 0=normal, 1=reset controller
|
|
|
|
bx_bool disable_irq; // 0=allow irq, 1=disable irq
|
2006-12-25 12:34:32 +03:00
|
|
|
} control;
|
2001-04-10 05:04:59 +04:00
|
|
|
Bit8u reset_in_progress;
|
|
|
|
Bit8u features;
|
2006-12-25 12:34:32 +03:00
|
|
|
struct {
|
|
|
|
Bit8u feature;
|
|
|
|
Bit8u nsector;
|
|
|
|
Bit8u sector;
|
|
|
|
Bit8u lcyl;
|
|
|
|
Bit8u hcyl;
|
|
|
|
} hob;
|
|
|
|
Bit32u num_sectors;
|
|
|
|
bx_bool lba48;
|
|
|
|
} controller_t;
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
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 ();
|
|
|
|
};
|
|
|
|
|
2005-06-26 14:54:49 +04:00
|
|
|
Bit16u read_16bit(const Bit8u* buf) BX_CPP_AttrRegparmN(1);
|
|
|
|
Bit32u read_32bit(const Bit8u* buf) BX_CPP_AttrRegparmN(1);
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
|
|
|
|
struct cdrom_t
|
|
|
|
{
|
2002-10-25 15:44:41 +04:00
|
|
|
bx_bool ready;
|
|
|
|
bx_bool locked;
|
2001-04-10 05:04:59 +04:00
|
|
|
#ifdef LOWLEVEL_CDROM
|
|
|
|
LOWLEVEL_CDROM* cd;
|
|
|
|
#endif
|
2005-06-26 14:54:49 +04:00
|
|
|
Bit32u capacity;
|
2001-04-10 05:04:59 +04:00
|
|
|
int next_lba;
|
|
|
|
int remaining_blocks;
|
|
|
|
struct currentStruct {
|
|
|
|
error_recovery_t error_recovery;
|
|
|
|
} current;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct atapi_t
|
|
|
|
{
|
2005-06-26 14:54:49 +04:00
|
|
|
Bit8u command;
|
2001-04-10 05:04:59 +04:00
|
|
|
int drq_bytes;
|
|
|
|
int total_bytes_remaining;
|
|
|
|
};
|
|
|
|
|
|
|
|
#if BX_USE_HD_SMF
|
|
|
|
# define BX_HD_SMF static
|
2002-10-25 01:07:56 +04:00
|
|
|
# define BX_HD_THIS theHardDrive->
|
2011-07-24 18:11:10 +04:00
|
|
|
# define BX_HD_THIS_PTR theHardDrive
|
2001-04-10 05:04:59 +04:00
|
|
|
#else
|
|
|
|
# define BX_HD_SMF
|
|
|
|
# define BX_HD_THIS this->
|
2011-07-24 18:11:10 +04:00
|
|
|
# define BX_HD_THIS_PTR this
|
2001-04-10 05:04:59 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
typedef enum {
|
2002-09-23 00:56:12 +04:00
|
|
|
IDE_NONE, IDE_DISK, IDE_CDROM
|
2001-04-10 05:04:59 +04:00
|
|
|
} device_type_t;
|
|
|
|
|
2002-10-25 01:07:56 +04:00
|
|
|
class bx_hard_drive_c : public bx_hard_drive_stub_c {
|
2001-04-10 05:04:59 +04:00
|
|
|
public:
|
2006-03-07 21:16:41 +03:00
|
|
|
bx_hard_drive_c();
|
|
|
|
virtual ~bx_hard_drive_c();
|
2008-01-27 01:24:03 +03:00
|
|
|
virtual void init();
|
|
|
|
virtual void reset(unsigned type);
|
2002-10-25 01:07:56 +04:00
|
|
|
virtual Bit32u get_first_cd_handle(void);
|
2011-06-13 13:32:39 +04:00
|
|
|
virtual bx_bool get_cd_media_status(Bit32u handle);
|
|
|
|
virtual bx_bool set_cd_media_status(Bit32u handle, bx_bool status);
|
2005-02-08 21:32:27 +03:00
|
|
|
#if BX_SUPPORT_PCI
|
2005-10-30 17:14:03 +03:00
|
|
|
virtual bx_bool bmdma_read_sector(Bit8u channel, Bit8u *buffer, Bit32u *sector_size);
|
2005-02-08 21:32:27 +03:00
|
|
|
virtual bx_bool bmdma_write_sector(Bit8u channel, Bit8u *buffer);
|
|
|
|
virtual void bmdma_complete(Bit8u channel);
|
|
|
|
#endif
|
2006-05-27 19:54:49 +04:00
|
|
|
virtual void register_state(void);
|
2002-10-25 01:07:56 +04:00
|
|
|
|
2008-01-27 01:24:03 +03:00
|
|
|
virtual Bit32u virt_read_handler(Bit32u address, unsigned io_len)
|
|
|
|
{
|
|
|
|
return read_handler(this, address, io_len);
|
2002-10-25 01:07:56 +04:00
|
|
|
}
|
2008-01-27 01:24:03 +03:00
|
|
|
virtual void virt_write_handler(Bit32u address, Bit32u value, unsigned io_len)
|
2002-10-25 01:07:56 +04:00
|
|
|
{
|
|
|
|
write_handler(this, address, value, io_len);
|
|
|
|
}
|
2008-01-27 01:24:03 +03:00
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
#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);
|
|
|
|
|
2011-12-28 15:51:42 +04:00
|
|
|
static void seek_timer_handler(void *);
|
|
|
|
BX_HD_SMF void seek_timer(void);
|
2004-02-09 21:59:50 +03:00
|
|
|
|
2011-07-24 18:11:10 +04:00
|
|
|
static void runtime_config_handler(void *);
|
|
|
|
void runtime_config(void);
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
private:
|
|
|
|
|
2006-11-18 14:51:07 +03:00
|
|
|
BX_HD_SMF bx_bool calculate_logical_address(Bit8u channel, Bit64s *sector) BX_CPP_AttrRegparmN(2);
|
2011-04-02 17:19:52 +04:00
|
|
|
BX_HD_SMF void increment_address(Bit8u channel, Bit64s *sector) BX_CPP_AttrRegparmN(2);
|
2002-09-23 00:56:12 +04:00
|
|
|
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);
|
|
|
|
|
2008-09-18 21:18:36 +04:00
|
|
|
BX_HD_SMF void init_send_atapi_command(Bit8u channel, Bit8u command, int req_length, int alloc_length, bx_bool lazy = 0);
|
2003-03-03 02:59:12 +03:00
|
|
|
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);
|
2005-05-04 22:19:49 +04:00
|
|
|
BX_HD_SMF void atapi_cmd_error(Bit8u channel, sense_t sense_key, asc_t asc, bx_bool show);
|
2002-09-23 00:56:12 +04:00
|
|
|
BX_HD_SMF void init_mode_sense_single(Bit8u channel, const void* src, int size);
|
2003-03-03 02:59:12 +03:00
|
|
|
BX_HD_SMF void atapi_cmd_nop(Bit8u channel) BX_CPP_AttrRegparmN(1);
|
2005-02-08 21:32:27 +03:00
|
|
|
BX_HD_SMF bx_bool bmdma_present(void);
|
2006-02-07 00:27:34 +03:00
|
|
|
BX_HD_SMF void set_signature(Bit8u channel, Bit8u id);
|
2006-07-17 22:40:26 +04:00
|
|
|
BX_HD_SMF bx_bool ide_read_sector(Bit8u channel, Bit8u *buffer, Bit32u buffer_size);
|
|
|
|
BX_HD_SMF bx_bool ide_write_sector(Bit8u channel, Bit8u *buffer, Bit32u buffer_size);
|
2006-12-25 12:34:32 +03:00
|
|
|
BX_HD_SMF void lba48_transform(Bit8u channel, bx_bool lba48);
|
2002-09-23 00:56:12 +04:00
|
|
|
|
2011-06-13 13:32:39 +04:00
|
|
|
static Bit64s cdrom_status_handler(bx_param_c *param, int set, Bit64s val);
|
|
|
|
static const char* cdrom_path_handler(bx_param_string_c *param, int set,
|
|
|
|
const char *oldval, const char *val, int maxlen);
|
|
|
|
|
2002-09-23 00:56:12 +04:00
|
|
|
// FIXME:
|
|
|
|
// For each ATA channel we should have one controller struct
|
|
|
|
// and an array of two drive structs
|
|
|
|
struct channel_t {
|
|
|
|
struct drive_t {
|
2010-12-22 00:47:41 +03:00
|
|
|
device_image_t* hdimage;
|
2002-09-23 00:56:12 +04:00
|
|
|
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];
|
2006-12-26 20:08:12 +03:00
|
|
|
bx_bool identify_set;
|
2002-09-23 00:56:12 +04:00
|
|
|
|
|
|
|
controller_t controller;
|
|
|
|
cdrom_t cdrom;
|
|
|
|
sense_info_t sense;
|
|
|
|
atapi_t atapi;
|
|
|
|
|
|
|
|
Bit8u model_no[41];
|
2004-02-08 21:38:26 +03:00
|
|
|
int statusbar_id;
|
2006-08-05 11:49:31 +04:00
|
|
|
Bit8u device_num; // for ATAPI identify & inquiry
|
2011-07-24 18:11:10 +04:00
|
|
|
bx_bool status_changed;
|
2006-08-05 11:49:31 +04:00
|
|
|
} drives[2];
|
2002-09-23 00:56:12 +04:00
|
|
|
unsigned drive_select;
|
|
|
|
|
|
|
|
Bit16u ioaddr1;
|
|
|
|
Bit16u ioaddr2;
|
|
|
|
Bit8u irq;
|
|
|
|
|
2006-08-05 11:49:31 +04:00
|
|
|
} channels[BX_MAX_ATA_CHANNEL];
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2011-12-28 15:51:42 +04:00
|
|
|
int seek_timer_index;
|
2006-08-05 11:49:31 +04:00
|
|
|
Bit8u cdrom_count;
|
2012-01-20 19:56:17 +04:00
|
|
|
bx_bool pci_enabled;
|
2006-03-07 21:16:41 +03:00
|
|
|
};
|
2004-02-09 21:59:50 +03:00
|
|
|
|
2006-03-07 21:16:41 +03:00
|
|
|
#endif
|