DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/hardware/ide.cpp
00001 /*
00002  * IDE ATA/ATAPI and controller emulation for DOSBox-X
00003  * (C) 2012 Jonathan Campbell
00004 
00005  * [insert open source license here]
00006  */
00007 
00008 /* $Id: ide.cpp,v 1.49 2009-04-10 09:53:04 c2woody Exp $ */
00009 
00010 #include <math.h>
00011 #include <assert.h>
00012 #include "dosbox.h"
00013 #include "inout.h"
00014 #include "pic.h"
00015 #include "mem.h"
00016 #include "cpu.h"
00017 #include "ide.h"
00018 #include "mixer.h"
00019 #include "timer.h"
00020 #include "setup.h"
00021 #include "control.h"
00022 #include "callback.h"
00023 #include "bios_disk.h"
00024 #include "../src/dos/cdrom.h"
00025 
00026 #if defined(_MSC_VER)
00027 # pragma warning(disable:4244) /* const fmath::local::uint64_t to double possible loss of data */
00028 # pragma warning(disable:4305) /* truncation from double to float */
00029 #endif
00030 
00031 #ifdef _MSC_VER
00032 # define MIN(a,b) ((a) < (b) ? (a) : (b))
00033 #else
00034 # define MIN(a,b) std::min(a,b)
00035 #endif
00036 
00037 #if defined(_MSC_VER)
00038 # pragma warning(disable:4065) /* switch statement no case labels */
00039 #endif
00040 
00041 static unsigned char init_ide = 0;
00042 
00043 static const unsigned char IDE_default_IRQs[4] = {
00044     14, /* primary */
00045     15, /* secondary */
00046     11, /* tertiary */
00047     10  /* quaternary */
00048 };
00049 
00050 static const unsigned short IDE_default_bases[4] = {
00051     0x1F0,  /* primary */
00052     0x170,  /* secondary */
00053     0x1E8,  /* tertiary */
00054     0x168   /* quaternary */
00055 };
00056 
00057 static const unsigned short IDE_default_alts[4] = {
00058     0x3F6,  /* primary */
00059     0x376,  /* secondary */
00060     0x3EE,  /* tertiary */
00061     0x36E   /* quaternary */
00062 };
00063 
00064 bool fdc_takes_port_3F7();
00065 
00066 static void ide_pc98ctlio_w(Bitu port,Bitu val,Bitu iolen);
00067 static Bitu ide_pc98ctlio_r(Bitu port,Bitu iolen);
00068 static void ide_altio_w(Bitu port,Bitu val,Bitu iolen);
00069 static Bitu ide_altio_r(Bitu port,Bitu iolen);
00070 static void ide_baseio_w(Bitu port,Bitu val,Bitu iolen);
00071 static Bitu ide_baseio_r(Bitu port,Bitu iolen);
00072 bool GetMSCDEXDrive(unsigned char drive_letter,CDROM_Interface **_cdrom);
00073 
00074 enum IDEDeviceType {
00075     IDE_TYPE_NONE,
00076     IDE_TYPE_HDD=1,
00077     IDE_TYPE_CDROM
00078 };
00079 
00080 enum IDEDeviceState {
00081     IDE_DEV_READY=0,
00082     IDE_DEV_SELECT_WAIT,
00083     IDE_DEV_CONFUSED,
00084     IDE_DEV_BUSY,
00085     IDE_DEV_DATA_READ,
00086     IDE_DEV_DATA_WRITE,
00087     IDE_DEV_ATAPI_PACKET_COMMAND,
00088     IDE_DEV_ATAPI_BUSY
00089 };
00090 
00091 enum {
00092     IDE_STATUS_BUSY=0x80,
00093     IDE_STATUS_DRIVE_READY=0x40,
00094     IDE_STATUS_DRIVE_SEEK_COMPLETE=0x10,
00095     IDE_STATUS_DRQ=0x08,
00096     IDE_STATUS_ERROR=0x01
00097 };
00098 
00099 class IDEController;
00100 
00101 #if 0//unused
00102 static inline bool drivehead_is_lba48(uint8_t val) {
00103     return (val&0xE0) == 0x40;
00104 }
00105 #endif
00106 
00107 static inline bool drivehead_is_lba(uint8_t val) {
00108     return (val&0xE0) == 0xE0;
00109 }
00110 
00111 #if 0//unused
00112 static inline bool drivehead_is_chs(uint8_t val) {
00113     return (val&0xE0) == 0xA0;
00114 }
00115 #endif
00116 
00117 class IDEDevice {
00118 public:
00119     IDEController *controller;
00120     uint16_t feature,count,lba[3];  /* feature = BASE+1  count = BASE+2   lba[3] = BASE+3,+4,+5 */
00121     uint8_t command,drivehead,status; /* command/status = BASE+7  drivehead = BASE+6 */
00122     enum IDEDeviceType type;
00123     bool faked_command; /* if set, DOSBox is sending commands to itself */
00124     bool allow_writing;
00125     bool motor_on;
00126     bool asleep;
00127     IDEDeviceState state;
00128     /* feature: 0x1F1 (Word 00h in ATA specs)
00129          count: 0x1F2 (Word 01h in ATA specs)
00130         lba[3]: 0x1F3 (Word 02h) 0x1F4 (Word 03h) and 0x1F5 (Word 04h)
00131      drivehead: 0x1F6 (copy of last value written)
00132        command: 0x1F7 (Word 05h)
00133         status: 0x1F7 (value read back to IDE controller, including busy and drive ready bits as well as error status)
00134 
00135     In C/H/S modes lba[3] becomes lba[0]=sector lba[1]=cylinder-low lba[2]=cylinder-high and
00136     the code must read the 4-bit head number from drivehead[bits 3:0].
00137 
00138     "drivehead" in this struct is always maintained as a device copy of the controller's
00139     drivehead value. it is only updated on write, and not returned on read.
00140 
00141     "allow_writing" if set allows the DOS program/OS to write the registers. It is
00142     clear during command execution, obviously, so the state of the device is not confused
00143     while executing the command.
00144 
00145     Registers are 16-bit where applicable so future revisions of this code
00146     can support LBA48 commands */
00147 public:
00148     /* tweakable parameters */
00149     double ide_select_delay;    /* time between writing 0x1F6 and drive readiness */
00150     double ide_spinup_delay;    /* time it takes to spin the hard disk motor up to speed */
00151     double ide_spindown_delay;  /* time it takes for hard disk motor to spin down */
00152     double ide_identify_command_delay;
00153 public:
00154     IDEDevice(IDEController *c);
00155     virtual ~IDEDevice();
00156     virtual void host_reset_begin();    /* IDE controller -> upon setting bit 2 of alt (0x3F6) */
00157     virtual void host_reset_complete(); /* IDE controller -> upon setting bit 2 of alt (0x3F6) */
00158     virtual void select(uint8_t ndh,bool switched_to);
00159     virtual void deselect();
00160     virtual void abort_error();
00161     virtual void abort_normal();
00162     virtual void interface_wakeup();
00163     virtual void writecommand(uint8_t cmd);
00164     virtual Bitu data_read(Bitu iolen); /* read from 1F0h data port from IDE device */
00165     virtual void data_write(Bitu v,Bitu iolen);/* write to 1F0h data port to IDE device */
00166     virtual bool command_interruption_ok(uint8_t cmd);
00167     virtual void abort_silent();
00168 };
00169 
00170 class IDEATADevice:public IDEDevice {
00171 public:
00172     IDEATADevice(IDEController *c,unsigned char disk_index);
00173     virtual ~IDEATADevice();
00174     virtual void writecommand(uint8_t cmd);
00175 public:
00176     std::string id_serial;
00177     std::string id_firmware_rev;
00178     std::string id_model;
00179     unsigned char bios_disk_index;
00180     imageDisk *getBIOSdisk();
00181     void update_from_biosdisk();
00182     virtual Bitu data_read(Bitu iolen); /* read from 1F0h data port from IDE device */
00183     virtual void data_write(Bitu v,Bitu iolen);/* write to 1F0h data port to IDE device */
00184     virtual void generate_identify_device();
00185     virtual void prepare_read(Bitu offset,Bitu size);
00186     virtual void prepare_write(Bitu offset,Bitu size);
00187     virtual void io_completion();
00188     virtual bool increment_current_address(Bitu count=1);
00189 public:
00190     Bitu multiple_sector_max,multiple_sector_count;
00191     Bitu heads,sects,cyls,headshr,progress_count;
00192     Bitu phys_heads,phys_sects,phys_cyls;
00193     unsigned char sector[512 * 128] = {};
00194     Bitu sector_i,sector_total;
00195     bool geo_translate;
00196 };
00197 
00198 enum {
00199     LOAD_NO_DISC=0,
00200     LOAD_INSERT_CD,         /* user is "inserting" the CD */
00201     LOAD_IDLE,          /* disc is stationary, not spinning */
00202     LOAD_DISC_LOADING,      /* disc is "spinning up" */
00203     LOAD_DISC_READIED,      /* disc just "became ready" */
00204     LOAD_READY
00205 };
00206 
00207 class IDEATAPICDROMDevice:public IDEDevice {
00208 public:
00209     IDEATAPICDROMDevice(IDEController *c,unsigned char drive_index);
00210     virtual ~IDEATAPICDROMDevice();
00211     virtual void writecommand(uint8_t cmd);
00212 public:
00213     std::string id_serial;
00214     std::string id_firmware_rev;
00215     std::string id_model;
00216     unsigned char drive_index;
00217     CDROM_Interface *getMSCDEXDrive();
00218     void update_from_cdrom();
00219     virtual Bitu data_read(Bitu iolen); /* read from 1F0h data port from IDE device */
00220     virtual void data_write(Bitu v,Bitu iolen);/* write to 1F0h data port to IDE device */
00221     virtual void generate_identify_device();
00222     virtual void generate_mmc_inquiry();
00223     virtual void prepare_read(Bitu offset,Bitu size);
00224     virtual void prepare_write(Bitu offset,Bitu size);
00225     virtual void set_sense(unsigned char SK,unsigned char ASC=0,unsigned char ASCQ=0,unsigned int len=0);
00226     virtual bool common_spinup_response(bool trigger,bool wait);
00227     virtual void on_mode_select_io_complete();
00228     virtual void atapi_io_completion();
00229     virtual void io_completion();
00230     virtual void atapi_cmd_completion();
00231     virtual void on_atapi_busy_time();
00232     virtual void read_subchannel();
00233     virtual void play_audio_msf();
00234     virtual void pause_resume();
00235     virtual void play_audio10();
00236     virtual void mode_sense();
00237     virtual void read_toc();
00238 public:
00239     bool atapi_to_host;         /* if set, PACKET data transfer is to be read by host */
00240     double spinup_time;
00241     double spindown_timeout;
00242     double cd_insertion_time;
00243     Bitu host_maximum_byte_count;       /* host maximum byte count during PACKET transfer */
00244     std::string id_mmc_vendor_id;
00245     std::string id_mmc_product_id;
00246     std::string id_mmc_product_rev;
00247     Bitu LBA,TransferLength;
00248     int loading_mode;
00249     bool has_changed;
00250 public:
00251     unsigned char sense[256];
00252     Bitu sense_length;
00253     unsigned char atapi_cmd[12];
00254     unsigned char atapi_cmd_i,atapi_cmd_total;
00255     unsigned char sector[512*128];
00256     Bitu sector_i,sector_total;
00257 };
00258 
00259 class IDEController:public Module_base{
00260 public:
00261     int IRQ;
00262     bool int13fakeio;       /* on certain INT 13h calls, force IDE state as if BIOS had carried them out */
00263     bool int13fakev86io;        /* on certain INT 13h calls in virtual 8086 mode, trigger fake CPU I/O traps */
00264     bool enable_pio32;      /* enable 32-bit PIO (if disabled, attempts at 32-bit PIO are handled as if two 16-bit I/O) */
00265     bool ignore_pio32;      /* if 32-bit PIO enabled, but ignored, writes do nothing, reads return 0xFFFFFFFF */
00266     bool register_pnp;
00267     unsigned short alt_io;
00268     unsigned short base_io;
00269     unsigned char interface_index;
00270     IO_ReadHandleObject ReadHandler[8],ReadHandlerAlt[2];
00271     IO_WriteHandleObject WriteHandler[8],WriteHandlerAlt[2];
00272 public:
00273     IDEDevice* device[2];       /* IDE devices (master, slave) */
00274     Bitu select,status,drivehead;   /* which is selected, status register (0x1F7) but ONLY if no device exists at selection, drive/head register (0x1F6) */
00275     bool interrupt_enable;      /* bit 1 of alt (0x3F6) */
00276     bool host_reset;        /* bit 2 of alt */
00277     bool irq_pending;
00278     /* defaults for CD-ROM emulation */
00279     double spinup_time;
00280     double spindown_timeout;
00281     double cd_insertion_time;
00282 public:
00283     IDEController(Section* configuration,unsigned char index);
00284     void register_isapnp();
00285     void install_io_port();
00286     void raise_irq();
00287     void lower_irq();
00288     ~IDEController();
00289 };
00290 
00291 static IDEController* idecontroller[MAX_IDE_CONTROLLERS]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
00292 
00293 static void IDE_DelayedCommand(Bitu idx/*which IDE controller*/);
00294 static IDEController* GetIDEController(Bitu idx);
00295 
00296 static void IDE_ATAPI_SpinDown(Bitu idx/*which IDE controller*/) {
00297     IDEController *ctrl = GetIDEController(idx);
00298     if (ctrl == NULL) return;
00299 
00300     for (unsigned int i=0;i < 2;i++) {
00301         IDEDevice *dev = ctrl->device[i];
00302         if (dev == NULL) continue;
00303 
00304         if (dev->type == IDE_TYPE_HDD) {
00305         }
00306         else if (dev->type == IDE_TYPE_CDROM) {
00307             IDEATAPICDROMDevice *atapi = (IDEATAPICDROMDevice*)dev;
00308 
00309             if (atapi->loading_mode == LOAD_DISC_READIED || atapi->loading_mode == LOAD_READY) {
00310                 atapi->loading_mode = LOAD_IDLE;
00311                 LOG_MSG("ATAPI CD-ROM: spinning down\n");
00312             }
00313         }
00314         else {
00315             LOG_MSG("Unknown ATAPI spinup callback\n");
00316         }
00317     }
00318 }
00319 
00320 static void IDE_ATAPI_SpinUpComplete(Bitu idx/*which IDE controller*/);
00321 
00322 static void IDE_ATAPI_CDInsertion(Bitu idx/*which IDE controller*/) {
00323     IDEController *ctrl = GetIDEController(idx);
00324     if (ctrl == NULL) return;
00325 
00326     for (unsigned int i=0;i < 2;i++) {
00327         IDEDevice *dev = ctrl->device[i];
00328         if (dev == NULL) continue;
00329 
00330         if (dev->type == IDE_TYPE_HDD) {
00331         }
00332         else if (dev->type == IDE_TYPE_CDROM) {
00333             IDEATAPICDROMDevice *atapi = (IDEATAPICDROMDevice*)dev;
00334 
00335             if (atapi->loading_mode == LOAD_INSERT_CD) {
00336                 atapi->loading_mode = LOAD_DISC_LOADING;
00337                 LOG_MSG("ATAPI CD-ROM: insert CD to loading\n");
00338                 PIC_RemoveSpecificEvents(IDE_ATAPI_SpinDown,idx);
00339                 PIC_RemoveSpecificEvents(IDE_ATAPI_CDInsertion,idx);
00340                 PIC_AddEvent(IDE_ATAPI_SpinUpComplete,atapi->spinup_time/*ms*/,idx);
00341             }
00342         }
00343         else {
00344             LOG_MSG("Unknown ATAPI spinup callback\n");
00345         }
00346     }
00347 }
00348 
00349 static void IDE_ATAPI_SpinUpComplete(Bitu idx/*which IDE controller*/) {
00350     IDEController *ctrl = GetIDEController(idx);
00351     if (ctrl == NULL) return;
00352 
00353     for (unsigned int i=0;i < 2;i++) {
00354         IDEDevice *dev = ctrl->device[i];
00355         if (dev == NULL) continue;
00356 
00357         if (dev->type == IDE_TYPE_HDD) {
00358         }
00359         else if (dev->type == IDE_TYPE_CDROM) {
00360             IDEATAPICDROMDevice *atapi = (IDEATAPICDROMDevice*)dev;
00361 
00362             if (atapi->loading_mode == LOAD_DISC_LOADING) {
00363                 atapi->loading_mode = LOAD_DISC_READIED;
00364                 LOG_MSG("ATAPI CD-ROM: spinup complete\n");
00365                 PIC_RemoveSpecificEvents(IDE_ATAPI_SpinDown,idx);
00366                 PIC_RemoveSpecificEvents(IDE_ATAPI_CDInsertion,idx);
00367                 PIC_AddEvent(IDE_ATAPI_SpinDown,atapi->spindown_timeout/*ms*/,idx);
00368             }
00369         }
00370         else {
00371             LOG_MSG("Unknown ATAPI spinup callback\n");
00372         }
00373     }
00374 }
00375 
00376 /* returns "true" if command should proceed as normal, "false" if sense data was set and command should not proceed.
00377  * this function helps to enforce virtual "spin up" and "ready" delays. */
00378 bool IDEATAPICDROMDevice::common_spinup_response(bool trigger,bool wait) {
00379     if (loading_mode == LOAD_IDLE) {
00380         if (trigger) {
00381             LOG_MSG("ATAPI CD-ROM: triggered to spin up from idle\n");
00382             loading_mode = LOAD_DISC_LOADING;
00383             PIC_RemoveSpecificEvents(IDE_ATAPI_SpinDown,controller->interface_index);
00384             PIC_RemoveSpecificEvents(IDE_ATAPI_CDInsertion,controller->interface_index);
00385             PIC_AddEvent(IDE_ATAPI_SpinUpComplete,spinup_time/*ms*/,controller->interface_index);
00386         }
00387     }
00388     else if (loading_mode == LOAD_READY) {
00389         if (trigger) {
00390             PIC_RemoveSpecificEvents(IDE_ATAPI_SpinDown,controller->interface_index);
00391             PIC_RemoveSpecificEvents(IDE_ATAPI_CDInsertion,controller->interface_index);
00392             PIC_AddEvent(IDE_ATAPI_SpinDown,spindown_timeout/*ms*/,controller->interface_index);
00393         }
00394     }
00395 
00396     switch (loading_mode) {
00397         case LOAD_NO_DISC:
00398         case LOAD_INSERT_CD:
00399             set_sense(/*SK=*/0x02,/*ASC=*/0x3A); /* Medium Not Present */
00400             return false;
00401         case LOAD_DISC_LOADING:
00402             if (has_changed && !wait/*if command will block until LOADING complete*/) {
00403                 set_sense(/*SK=*/0x02,/*ASC=*/0x04,/*ASCQ=*/0x01); /* Medium is becoming available */
00404                 return false;
00405             }
00406             break;
00407         case LOAD_DISC_READIED:
00408             loading_mode = LOAD_READY;
00409             if (has_changed) {
00410                 if (trigger) has_changed = false;
00411                 set_sense(/*SK=*/0x02,/*ASC=*/0x28,/*ASCQ=*/0x00); /* Medium is ready (has changed) */
00412                 return false;
00413             }
00414             break;
00415         case LOAD_IDLE:
00416         case LOAD_READY:
00417             break;
00418         default:
00419             abort();
00420     }
00421 
00422     return true;
00423 }
00424 
00425 void IDEATAPICDROMDevice::read_subchannel() {
00426 //  unsigned char Format = atapi_cmd[2] & 0xF;
00427 //  unsigned char Track = atapi_cmd[6];
00428     unsigned char paramList = atapi_cmd[3];
00429     unsigned char attr,track,index;
00430     bool SUBQ = !!(atapi_cmd[2] & 0x40);
00431     bool TIME = !!(atapi_cmd[1] & 2);
00432     unsigned char *write;
00433     unsigned char astat;
00434     bool playing,pause;
00435     TMSF rel,abs;
00436 
00437     CDROM_Interface *cdrom = getMSCDEXDrive();
00438     if (cdrom == NULL) {
00439         LOG_MSG("WARNING: ATAPI READ TOC unable to get CDROM drive\n");
00440         prepare_read(0,8);
00441         return;
00442     }
00443 
00444     if (paramList == 0 || paramList > 3) {
00445         LOG_MSG("ATAPI READ SUBCHANNEL unknown param list\n");
00446         prepare_read(0,8);
00447         return;
00448     }
00449     else if (paramList == 2) {
00450         LOG_MSG("ATAPI READ SUBCHANNEL Media Catalog Number not supported\n");
00451         prepare_read(0,8);
00452         return;
00453     }
00454     else if (paramList == 3) {
00455         LOG_MSG("ATAPI READ SUBCHANNEL ISRC not supported\n");
00456         prepare_read(0,8);
00457         return;
00458     }
00459 
00460     /* get current subchannel position */
00461     if (!cdrom->GetAudioSub(attr,track,index,rel,abs)) {
00462         LOG_MSG("ATAPI READ SUBCHANNEL unable to read current pos\n");
00463         prepare_read(0,8);
00464         return;
00465     }
00466 
00467     if (!cdrom->GetAudioStatus(playing,pause))
00468         playing = pause = false;
00469 
00470     if (playing)
00471         astat = pause ? 0x12 : 0x11;
00472     else
00473         astat = 0x13;
00474 
00475     memset(sector,0,8);
00476     write = sector;
00477     *write++ = 0x00;
00478     *write++ = astat;/* AUDIO STATUS */
00479     *write++ = 0x00;/* SUBCHANNEL DATA LENGTH */
00480     *write++ = 0x00;
00481 
00482     if (SUBQ) {
00483         *write++ = 0x01;    /* subchannel data format code */
00484         *write++ = (attr >> 4) | 0x10;  /* ADR/CONTROL */
00485         *write++ = track;
00486         *write++ = index;
00487         if (TIME) {
00488             *write++ = 0x00;
00489             *write++ = abs.min;
00490             *write++ = abs.sec;
00491             *write++ = abs.fr;
00492             *write++ = 0x00;
00493             *write++ = rel.min;
00494             *write++ = rel.sec;
00495             *write++ = rel.fr;
00496         }
00497         else {
00498             uint32_t sec;
00499 
00500             sec = (abs.min*60u*75u)+(abs.sec*75u)+abs.fr - 150u;
00501             *write++ = (unsigned char)(sec >> 24u);
00502             *write++ = (unsigned char)(sec >> 16u);
00503             *write++ = (unsigned char)(sec >> 8u);
00504             *write++ = (unsigned char)(sec >> 0u);
00505 
00506             sec = (rel.min*60u*75u)+(rel.sec*75u)+rel.fr - 150u;
00507             *write++ = (unsigned char)(sec >> 24u);
00508             *write++ = (unsigned char)(sec >> 16u);
00509             *write++ = (unsigned char)(sec >> 8u);
00510             *write++ = (unsigned char)(sec >> 0u);
00511         }
00512     }
00513 
00514     {
00515         unsigned int x = (unsigned int)(write-sector) - 4;
00516         sector[2] = x >> 8;
00517         sector[3] = x;
00518     }
00519 
00520     prepare_read(0,MIN((unsigned int)(write-sector),(unsigned int)host_maximum_byte_count));
00521 #if 0
00522     LOG_MSG("SUBCH ");
00523     for (size_t i=0;i < sector_total;i++) LOG_MSG("%02x ",sector[i]);
00524     LOG_MSG("\n");
00525 #endif
00526 }
00527 
00528 void IDEATAPICDROMDevice::mode_sense() {
00529     unsigned char PAGE = atapi_cmd[2] & 0x3F;
00530 //  unsigned char SUBPAGE = atapi_cmd[3];
00531     unsigned char *write;
00532     unsigned int x;
00533 
00534     write = sector;
00535 
00536     /* Mode Parameter List MMC-3 Table 340 */
00537     /* - Mode parameter header */
00538     /* - Page(s) */
00539 
00540     /* Mode Parameter Header (response for 10-byte MODE SENSE) SPC-2 Table 148 */
00541     *write++ = 0x00;    /* MODE DATA LENGTH                     (MSB) */
00542     *write++ = 0x00;    /*                                      (LSB) */
00543     *write++ = 0x00;    /* MEDIUM TYPE */
00544     *write++ = 0x00;    /* DEVICE-SPECIFIC PARAMETER */
00545     *write++ = 0x00;    /* Reserved */
00546     *write++ = 0x00;    /* Reserved */
00547     *write++ = 0x00;    /* BLOCK DESCRIPTOR LENGTH              (MSB) */
00548     *write++ = 0x00;    /*                                      (LSB) */
00549     /* NTS: MMC-3 Table 342 says that BLOCK DESCRIPTOR LENGTH is zero, where it would be 8 for legacy units */
00550 
00551     /* Mode Page Format MMC-3 Table 341 */
00552     *write++ = PAGE;    /* PS|reserved|Page Code */
00553     *write++ = 0x00;    /* Page Length (n - 1) ... Length in bytes of the mode parameters that follow */
00554     switch (PAGE) {
00555         case 0x01: /* Read error recovery MMC-3 Section 6.3.4 table 344 */
00556             *write++ = 0x00;    /* +2 Error recovery Parameter  AWRE|ARRE|TB|RC|Reserved|PER|DTE|DCR */
00557             *write++ = 3;       /* +3 Read Retry Count */
00558             *write++ = 0x00;    /* +4 Reserved */
00559             *write++ = 0x00;    /* +5 Reserved */
00560             *write++ = 0x00;    /* +6 Reserved */
00561             *write++ = 0x00;    /* +7 Reserved */
00562             *write++ = 0x00;    /* +8 Write Retry Count (this is not yet CD burner) */
00563             *write++ = 0x00;    /* +9 Reserved */
00564             *write++ = 0x00;    /* +10 Recovery Time Limit (should be zero)         (MSB) */
00565             *write++ = 0x00;    /* +11                                              (LSB) */
00566             break;
00567         case 0x0E: /* CD-ROM audio control MMC-3 Section 6.3.7 table 354 */
00568                    /* also MMC-1 Section 5.2.3.1 table 97 */
00569             *write++ = 0x04;    /* +2 Reserved|IMMED=1|SOTC=0|Reserved */
00570             *write++ = 0x00;    /* +3 Reserved */
00571             *write++ = 0x00;    /* +4 Reserved */
00572             *write++ = 0x00;    /* +5 Reserved */
00573             *write++ = 0x00;    /* +6 Obsolete (75) */
00574             *write++ = 75;      /* +7 Obsolete (75) */
00575             *write++ = 0x01;    /* +8 output port 0 selection (0001b = channel 0) */
00576             *write++ = 0xFF;    /* +9 output port 0 volume (0xFF = 0dB atten.) */
00577             *write++ = 0x02;    /* +10 output port 1 selection (0010b = channel 1) */
00578             *write++ = 0xFF;    /* +11 output port 1 volume (0xFF = 0dB atten.) */
00579             *write++ = 0x00;    /* +12 output port 2 selection (none) */
00580             *write++ = 0x00;    /* +13 output port 2 volume (0x00 = mute) */
00581             *write++ = 0x00;    /* +14 output port 3 selection (none) */
00582             *write++ = 0x00;    /* +15 output port 3 volume (0x00 = mute) */
00583             break;
00584         case 0x2A: /* CD-ROM mechanical status MMC-3 Section 6.3.11 table 361 */
00585                                 /*    MSB            |             |             |             |              |               |              |       LSB */
00586             *write++ = 0x07;    /* +2 Reserved       |Reserved     |DVD-RAM read |DVD-R read   |DVD-ROM read  |   Method 2    | CD-RW read   | CD-R read */
00587             *write++ = 0x00;    /* +3 Reserved       |Reserved     |DVD-RAM write|DVD-R write  |   Reserved   |  Test Write   | CD-RW write  | CD-R write */
00588             *write++ = 0x71;    /* +4 Buffer Underrun|Multisession |Mode 2 form 2|Mode 2 form 1|Digital Port 2|Digital Port 1 |  Composite   | Audio play */
00589             *write++ = 0xFF;    /* +5 Read code bar  |UPC          |ISRC         |C2 Pointers  |R-W deintcorr | R-W supported |CDDA accurate |CDDA support */
00590             *write++ = 0x2F;    /* +6 Loading mechanism type                     |Reserved     |Eject         |Prevent Jumper |Lock state    |Lock */
00591                                 /*      0 (0x00) = Caddy
00592                                  *      1 (0x20) = Tray
00593                                  *      2 (0x40) = Popup
00594                                  *      3 (0x60) = Reserved
00595                                  *      4 (0x80) = Changer with indivually changeable discs
00596                                  *      5 (0xA0) = Changer using a magazine mechanism
00597                                  *      6 (0xC0) = Reserved
00598                                  *      6 (0xE0) = Reserved */
00599             *write++ = 0x03;    /* +7 Reserved       |Reserved     |R-W in leadin|Side chg cap |S/W slot sel  |Changer disc pr|Sep. ch. mute |Sep. volume levels */
00600 
00601             x = 176 * 8;        /* +8 maximum speed supported in kB: 8X  (obsolete in MMC-3) */
00602             *write++ = x>>8;
00603             *write++ = x;
00604 
00605             x = 256;            /* +10 Number of volume levels supported */
00606             *write++ = x>>8;
00607             *write++ = x;
00608 
00609             x = 6 * 256;        /* +12 buffer size supported by drive in kB */
00610             *write++ = x>>8;
00611             *write++ = x;
00612 
00613             x = 176 * 8;        /* +14 current read speed selected in kB: 8X  (obsolete in MMC-3) */
00614             *write++ = x>>8;
00615             *write++ = x;
00616 
00617             *write++ = 0;       /* +16 Reserved */
00618             *write++ = 0x00;    /* +17 Reserved | Reserved | Length | Length | LSBF | RCK | BCK | Reserved */
00619 
00620             x = 0;              /* +18 maximum write speed supported in kB: 0  (obsolete in MMC-3) */
00621             *write++ = x>>8;
00622             *write++ = x;
00623 
00624             x = 0;              /* +20 current write speed in kB: 0  (obsolete in MMC-3) */
00625             *write++ = x>>8;
00626             *write++ = x;
00627             break;
00628         default:
00629             memset(write,0,6); write += 6;
00630             LOG_MSG("WARNING: MODE SENSE on page 0x%02x not supported\n",PAGE);
00631             break;
00632     }
00633 
00634     /* mode param header, data length */
00635     x = (unsigned int)(write-sector) - 2;
00636     sector[0] = (unsigned char)(x >> 8u);
00637     sector[1] = (unsigned char)x;
00638     /* page length */
00639     sector[8+1] = (unsigned int)(write-sector) - 2 - 8;
00640 
00641     prepare_read(0,MIN((unsigned int)(write-sector),(unsigned int)host_maximum_byte_count));
00642 #if 0
00643     printf("SENSE ");
00644     for (size_t i=0;i < sector_total;i++) printf("%02x ",sector[i]);
00645     printf("\n");
00646 #endif
00647 }
00648 
00649 void IDEATAPICDROMDevice::pause_resume() {
00650     bool Resume = !!(atapi_cmd[8] & 1);
00651 
00652     CDROM_Interface *cdrom = getMSCDEXDrive();
00653     if (cdrom == NULL) {
00654         LOG_MSG("WARNING: ATAPI READ TOC unable to get CDROM drive\n");
00655         sector_total = 0;
00656         return;
00657     }
00658 
00659     cdrom->PauseAudio(Resume);
00660 }
00661 
00662 void IDEATAPICDROMDevice::play_audio_msf() {
00663     uint32_t start_lba,end_lba;
00664 
00665     CDROM_Interface *cdrom = getMSCDEXDrive();
00666     if (cdrom == NULL) {
00667         LOG_MSG("WARNING: ATAPI READ TOC unable to get CDROM drive\n");
00668         sector_total = 0;
00669         return;
00670     }
00671 
00672     if (atapi_cmd[3] == 0xFF && atapi_cmd[4] == 0xFF && atapi_cmd[5] == 0xFF)
00673         start_lba = 0xFFFFFFFF;
00674     else {
00675         start_lba = (atapi_cmd[3] * 60u * 75u) +
00676             (atapi_cmd[4] * 75u) +
00677             atapi_cmd[5];
00678 
00679         if (start_lba >= 150u) start_lba -= 150u; /* LBA sector 0 == M:S:F sector 0:2:0 */
00680         else end_lba = 0;
00681     }
00682 
00683     if (atapi_cmd[6] == 0xFF && atapi_cmd[7] == 0xFF && atapi_cmd[8] == 0xFF)
00684         end_lba = 0xFFFFFFFF;
00685     else {
00686         end_lba = (atapi_cmd[6] * 60u * 75u) +
00687             (atapi_cmd[7] * 75u) +
00688             atapi_cmd[8];
00689 
00690         if (end_lba >= 150u) end_lba -= 150u; /* LBA sector 0 == M:S:F sector 0:2:0 */
00691         else end_lba = 0;
00692     }
00693 
00694     if (start_lba == end_lba) {
00695         /* The play length field specifies the number of contiguous logical blocks that shall
00696          * be played. A play length of zero indicates that no audio operation shall occur.
00697          * This condition is not an error. */
00698         /* TODO: How do we interpret that? Does that mean audio playback stops? Or does it
00699          * mean we do nothing to the state of audio playback? */
00700         sector_total = 0;
00701         return;
00702     }
00703 
00704     /* LBA 0xFFFFFFFF means start playing wherever the optics of the CD sit */
00705     if (start_lba != 0xFFFFFFFF)
00706         cdrom->PlayAudioSector(start_lba,end_lba - start_lba);
00707     else
00708         cdrom->PauseAudio(true);
00709 
00710     sector_total = 0;
00711 }
00712 
00713 void IDEATAPICDROMDevice::play_audio10() {
00714     uint16_t play_length;
00715     uint32_t start_lba;
00716 
00717     CDROM_Interface *cdrom = getMSCDEXDrive();
00718     if (cdrom == NULL) {
00719         LOG_MSG("WARNING: ATAPI READ TOC unable to get CDROM drive\n");
00720         sector_total = 0;
00721         return;
00722     }
00723 
00724     start_lba = ((uint32_t)atapi_cmd[2] << 24) +
00725         ((uint32_t)atapi_cmd[3] << 16) +
00726         ((uint32_t)atapi_cmd[4] << 8) +
00727         ((uint32_t)atapi_cmd[5] << 0);
00728 
00729     play_length = ((uint16_t)atapi_cmd[7] << 8) +
00730         ((uint16_t)atapi_cmd[8] << 0);
00731 
00732     if (play_length == 0) {
00733         /* The play length field specifies the number of contiguous logical blocks that shall
00734          * be played. A play length of zero indicates that no audio operation shall occur.
00735          * This condition is not an error. */
00736         /* TODO: How do we interpret that? Does that mean audio playback stops? Or does it
00737          * mean we do nothing to the state of audio playback? */
00738         sector_total = 0;
00739         return;
00740     }
00741 
00742     /* LBA 0xFFFFFFFF means start playing wherever the optics of the CD sit */
00743     if (start_lba != 0xFFFFFFFF)
00744         cdrom->PlayAudioSector(start_lba,play_length);
00745     else
00746         cdrom->PauseAudio(true);
00747 
00748     sector_total = 0;
00749 }
00750 
00751 #if 0 /* TODO move to library */
00752 static unsigned char dec2bcd(unsigned char c) {
00753     return ((c / 10) << 4) + (c % 10);
00754 }
00755 #endif
00756 
00757 void IDEATAPICDROMDevice::read_toc() {
00758     /* NTS: The SCSI MMC standards say we're allowed to indicate the return data
00759      *      is longer than it's allocation length. But here's the thing: some MS-DOS
00760      *      CD-ROM drivers will ask for the TOC but only provide enough room for one
00761      *      entry (OAKCDROM.SYS) and if we signal more data than it's buffer, it will
00762      *      reject our response and render the CD-ROM drive inaccessible. So to make
00763      *      this emulation work, we have to cut our response short to the driver's
00764      *      allocation length */
00765     unsigned int AllocationLength = ((unsigned int)atapi_cmd[7] << 8) + atapi_cmd[8];
00766     unsigned char Format = atapi_cmd[2] & 0xF;
00767     unsigned char Track = atapi_cmd[6];
00768     bool TIME = !!(atapi_cmd[1] & 2);
00769     unsigned char *write;
00770     int first,last,track;
00771     TMSF leadOut;
00772 
00773     CDROM_Interface *cdrom = getMSCDEXDrive();
00774     if (cdrom == NULL) {
00775         LOG_MSG("WARNING: ATAPI READ TOC unable to get CDROM drive\n");
00776         prepare_read(0,8);
00777         return;
00778     }
00779 
00780     memset(sector,0,8);
00781 
00782     if (!cdrom->GetAudioTracks(first,last,leadOut)) {
00783         LOG_MSG("WARNING: ATAPI READ TOC failed to get track info\n");
00784         prepare_read(0,8);
00785         return;
00786     }
00787 
00788     /* start 2 bytes out. we'll fill in the data length later */
00789     write = sector + 2;
00790 
00791     if (Format == 1) { /* Read multisession info */
00792         unsigned char attr;
00793         TMSF start;
00794 
00795         *write++ = (unsigned char)1;        /* @+2 first complete session */
00796         *write++ = (unsigned char)1;        /* @+3 last complete session */
00797 
00798         if (!cdrom->GetAudioTrackInfo(first,start,attr)) {
00799             LOG_MSG("WARNING: ATAPI READ TOC unable to read track %u information\n",first);
00800             attr = 0x41; /* ADR=1 CONTROL=4 */
00801             start.min = 0;
00802             start.sec = 0;
00803             start.fr = 0;
00804         }
00805 
00806         LOG_MSG("Track %u attr=0x%02x %02u:%02u:%02u\n",first,attr,start.min,start.sec,start.fr);
00807 
00808         *write++ = 0x00;        /* entry+0 RESERVED */
00809         *write++ = (attr >> 4) | 0x10;  /* entry+1 ADR=1 CONTROL=4 (DATA) */
00810         *write++ = (unsigned char)first;/* entry+2 TRACK */
00811         *write++ = 0x00;        /* entry+3 RESERVED */
00812 
00813         /* then, start address of first track in session */
00814         if (TIME) {
00815             *write++ = 0x00;
00816             *write++ = start.min;
00817             *write++ = start.sec;
00818             *write++ = start.fr;
00819         }
00820         else {
00821             uint32_t sec = (start.min*60u*75u)+(start.sec*75u)+start.fr - 150u;
00822             *write++ = (unsigned char)(sec >> 24u);
00823             *write++ = (unsigned char)(sec >> 16u);
00824             *write++ = (unsigned char)(sec >> 8u);
00825             *write++ = (unsigned char)(sec >> 0u);
00826         }
00827     }
00828     else if (Format == 0) { /* Read table of contents */
00829         *write++ = (unsigned char)first;    /* @+2 */
00830         *write++ = (unsigned char)last;     /* @+3 */
00831 
00832         for (track=first;track <= last;track++) {
00833             unsigned char attr;
00834             TMSF start;
00835 
00836             if (!cdrom->GetAudioTrackInfo(track,start,attr)) {
00837                 LOG_MSG("WARNING: ATAPI READ TOC unable to read track %u information\n",track);
00838                 attr = 0x41; /* ADR=1 CONTROL=4 */
00839                 start.min = 0;
00840                 start.sec = 0;
00841                 start.fr = 0;
00842             }
00843 
00844             if (track < Track)
00845                 continue;
00846             if ((write+8) > (sector+AllocationLength))
00847                 break;
00848 
00849             LOG_MSG("Track %u attr=0x%02x %02u:%02u:%02u\n",first,attr,start.min,start.sec,start.fr);
00850 
00851             *write++ = 0x00;        /* entry+0 RESERVED */
00852             *write++ = (attr >> 4) | 0x10; /* entry+1 ADR=1 CONTROL=4 (DATA) */
00853             *write++ = (unsigned char)track;/* entry+2 TRACK */
00854             *write++ = 0x00;        /* entry+3 RESERVED */
00855             if (TIME) {
00856                 *write++ = 0x00;
00857                 *write++ = start.min;
00858                 *write++ = start.sec;
00859                 *write++ = start.fr;
00860             }
00861             else {
00862                 uint32_t sec = (start.min*60u*75u)+(start.sec*75u)+start.fr - 150u;
00863                 *write++ = (unsigned char)(sec >> 24u);
00864                 *write++ = (unsigned char)(sec >> 16u);
00865                 *write++ = (unsigned char)(sec >> 8u);
00866                 *write++ = (unsigned char)(sec >> 0u);
00867             }
00868         }
00869 
00870         if ((write+8) <= (sector+AllocationLength)) {
00871             *write++ = 0x00;
00872             *write++ = 0x14;
00873             *write++ = 0xAA;/*TRACK*/
00874             *write++ = 0x00;
00875             if (TIME) {
00876                 *write++ = 0x00;
00877                 *write++ = leadOut.min;
00878                 *write++ = leadOut.sec;
00879                 *write++ = leadOut.fr;
00880             }
00881             else {
00882                 uint32_t sec = (leadOut.min*60u*75u)+(leadOut.sec*75u)+leadOut.fr - 150u;
00883                 *write++ = (unsigned char)(sec >> 24u);
00884                 *write++ = (unsigned char)(sec >> 16u);
00885                 *write++ = (unsigned char)(sec >> 8u);
00886                 *write++ = (unsigned char)(sec >> 0u);
00887             }
00888         }
00889     }
00890     else {
00891         LOG_MSG("WARNING: ATAPI READ TOC Format=%u not supported\n",Format);
00892         prepare_read(0,8);
00893         return;
00894     }
00895 
00896     /* update the TOC data length field */
00897     {
00898         unsigned int x = (unsigned int)(write-sector) - 2;
00899         sector[0] = x >> 8;
00900         sector[1] = x & 0xFF;
00901     }
00902 
00903     prepare_read(0,MIN(MIN((unsigned int)(write-sector),(unsigned int)host_maximum_byte_count),AllocationLength));
00904 }
00905 
00906 /* when the ATAPI command has been accepted, and the timeout has passed */
00907 void IDEATAPICDROMDevice::on_atapi_busy_time() {
00908     /* if the drive is spinning up, then the command waits */
00909     if (loading_mode == LOAD_DISC_LOADING) {
00910         switch (atapi_cmd[0]) {
00911             case 0x00: /* TEST UNIT READY */
00912             case 0x03: /* REQUEST SENSE */
00913                 allow_writing = true;
00914                 break; /* do not delay */
00915             default:
00916                 PIC_AddEvent(IDE_DelayedCommand,100/*ms*/,controller->interface_index);
00917                 return;
00918         }
00919     }
00920     else if (loading_mode == LOAD_DISC_READIED) {
00921         switch (atapi_cmd[0]) {
00922             case 0x00: /* TEST UNIT READY */
00923             case 0x03: /* REQUEST SENSE */
00924                 allow_writing = true;
00925                 break; /* do not delay */
00926             default:
00927                 if (!common_spinup_response(/*spin up*/true,/*wait*/false)) {
00928                     count = 0x03;
00929                     state = IDE_DEV_READY;
00930                     feature = ((sense[2]&0xF) << 4) | ((sense[2]&0xF) ? 0x04/*abort*/ : 0x00);
00931                     status = IDE_STATUS_DRIVE_READY|((sense[2]&0xF) ? IDE_STATUS_ERROR:IDE_STATUS_DRIVE_SEEK_COMPLETE);
00932                     controller->raise_irq();
00933                     allow_writing = true;
00934                     return;
00935                 }
00936                 break;
00937         }
00938     }
00939 
00940     switch (atapi_cmd[0]) {
00941         case 0x03: /* REQUEST SENSE */
00942             prepare_read(0,MIN((unsigned int)sense_length,(unsigned int)host_maximum_byte_count));
00943             memcpy(sector,sense,sense_length);
00944 
00945             feature = 0x00;
00946             state = IDE_DEV_DATA_READ;
00947             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ|IDE_STATUS_DRIVE_SEEK_COMPLETE;
00948 
00949             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
00950             lba[2] = sector_total >> 8;
00951             lba[1] = sector_total;
00952 
00953             controller->raise_irq();
00954             allow_writing = true;
00955             break;
00956         case 0x1E: /* PREVENT ALLOW MEDIUM REMOVAL */
00957             count = 0x03;
00958             feature = 0x00;
00959             sector_total = 0x00;
00960             state = IDE_DEV_DATA_READ;
00961             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
00962 
00963             /* Don't care. Do nothing. */
00964 
00965             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
00966             lba[2] = sector_total >> 8;
00967             lba[1] = sector_total;
00968 
00969             controller->raise_irq();
00970             allow_writing = true;
00971             break;
00972         case 0x25: /* READ CAPACITY */ {
00973             const unsigned int secsize = 2048;
00974             int first,last;
00975             TMSF leadOut;
00976 
00977             CDROM_Interface *cdrom = getMSCDEXDrive();
00978 
00979             if (!cdrom->GetAudioTracks(first,last,leadOut))
00980                 LOG_MSG("WARNING: ATAPI READ TOC failed to get track info\n");
00981 
00982             uint32_t sec = (leadOut.min*60u*75u)+(leadOut.sec*75u)+leadOut.fr - 150u;
00983 
00984             prepare_read(0,MIN((unsigned int)8,(unsigned int)host_maximum_byte_count));
00985             sector[0] = sec >> 24u;
00986             sector[1] = sec >> 16u;
00987             sector[2] = sec >> 8u;
00988             sector[3] = sec & 0xFF;
00989             sector[4] = secsize >> 24u;
00990             sector[5] = secsize >> 16u;
00991             sector[6] = secsize >> 8u;
00992             sector[7] = secsize & 0xFF;
00993 //          LOG_MSG("sec=%lu secsize=%lu\n",sec,secsize);
00994 
00995             feature = 0x00;
00996             state = IDE_DEV_DATA_READ;
00997             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ|IDE_STATUS_DRIVE_SEEK_COMPLETE;
00998 
00999             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
01000             lba[2] = sector_total >> 8;
01001             lba[1] = sector_total;
01002 
01003             controller->raise_irq();
01004             allow_writing = true;
01005             } break;
01006         case 0x2B: /* SEEK */
01007             count = 0x03;
01008             feature = 0x00;
01009             sector_total = 0x00;
01010             state = IDE_DEV_DATA_READ;
01011             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01012 
01013             /* Don't care. Do nothing. */
01014 
01015             /* Except... Windows 95's CD player expects the SEEK command to interrupt CD audio playback.
01016              * In fact it depends on it to the exclusion of commands explicitly standardized to... you know...
01017              * stop or pause playback. Oh Microsoft, you twits... */
01018             {
01019                 CDROM_Interface *cdrom = getMSCDEXDrive();
01020                 if (cdrom) {
01021                     bool playing,pause;
01022 
01023                     if (!cdrom->GetAudioStatus(playing,pause))
01024                         playing = true;
01025 
01026                     if (playing) {
01027                         LOG_MSG("ATAPI: Interrupting CD audio playback due to SEEK\n");
01028                         cdrom->StopAudio();
01029                     }
01030                 }
01031             }
01032 
01033             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
01034             lba[2] = sector_total >> 8;
01035             lba[1] = sector_total;
01036 
01037             controller->raise_irq();
01038             allow_writing = true;
01039             break;
01040         case 0x12: /* INQUIRY */
01041             /* NTS: the state of atapi_to_host doesn't seem to matter. */
01042             generate_mmc_inquiry();
01043             prepare_read(0,MIN((unsigned int)36,(unsigned int)host_maximum_byte_count));
01044 
01045             feature = 0x00;
01046             state = IDE_DEV_DATA_READ;
01047             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01048 
01049             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
01050             lba[2] = sector_total >> 8;
01051             lba[1] = sector_total;
01052 
01053             controller->raise_irq();
01054             allow_writing = true;
01055             break;
01056         case 0x28: /* READ(10) */
01057         case 0xA8: /* READ(12) */
01058             if (TransferLength == 0) {
01059                 /* this is legal. the SCSI MMC standards say so.
01060                    and apparently, MSCDEX.EXE issues READ(10) commands with transfer length == 0
01061                    to test the drive, so we have to emulate this */
01062                 feature = 0x00;
01063                 count = 0x03; /* no more transfer */
01064                 sector_total = 0;/*nothing to transfer */
01065                 state = IDE_DEV_READY;
01066                 status = IDE_STATUS_DRIVE_READY;
01067             }
01068             else {
01069                 /* OK, try to read */
01070                 CDROM_Interface *cdrom = getMSCDEXDrive();
01071                 bool res = (cdrom != NULL ? cdrom->ReadSectorsHost(/*buffer*/sector,false,LBA,TransferLength) : false);
01072                 if (res) {
01073                     prepare_read(0,MIN((unsigned int)(TransferLength*2048),(unsigned int)host_maximum_byte_count));
01074                     feature = 0x00;
01075                     state = IDE_DEV_DATA_READ;
01076                     status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01077                 }
01078                 else {
01079                     feature = 0xF4; /* abort sense=0xF */
01080                     count = 0x03; /* no more transfer */
01081                     sector_total = 0;/*nothing to transfer */
01082                     state = IDE_DEV_READY;
01083                     status = IDE_STATUS_DRIVE_READY|IDE_STATUS_ERROR;
01084                     LOG_MSG("ATAPI: Failed to read %lu sectors at %lu\n",
01085                         (unsigned long)TransferLength,(unsigned long)LBA);
01086                     /* TODO: write sense data */
01087                 }
01088             }
01089 
01090             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
01091             lba[2] = sector_total >> 8;
01092             lba[1] = sector_total;
01093 
01094             controller->raise_irq();
01095             allow_writing = true;
01096             break;
01097         case 0x42: /* READ SUB-CHANNEL */
01098             read_subchannel();
01099 
01100             feature = 0x00;
01101             state = IDE_DEV_DATA_READ;
01102             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01103 
01104             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
01105             lba[2] = sector_total >> 8;
01106             lba[1] = sector_total;
01107 
01108             controller->raise_irq();
01109             allow_writing = true;
01110             break;
01111         case 0x43: /* READ TOC */
01112             read_toc();
01113 
01114             feature = 0x00;
01115             state = IDE_DEV_DATA_READ;
01116             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01117 
01118             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
01119             lba[2] = sector_total >> 8;
01120             lba[1] = sector_total;
01121 
01122             controller->raise_irq();
01123             allow_writing = true;
01124             break;
01125         case 0x45: /* PLAY AUDIO(10) */
01126             play_audio10();
01127 
01128             count = 0x03;
01129             feature = 0x00;
01130             sector_total = 0x00;
01131             state = IDE_DEV_DATA_READ;
01132             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01133 
01134             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
01135             lba[2] = sector_total >> 8;
01136             lba[1] = sector_total;
01137 
01138             controller->raise_irq();
01139             allow_writing = true;
01140             break;
01141         case 0x47: /* PLAY AUDIO MSF */
01142             play_audio_msf();
01143 
01144             count = 0x03;
01145             feature = 0x00;
01146             sector_total = 0x00;
01147             state = IDE_DEV_DATA_READ;
01148             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01149 
01150             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
01151             lba[2] = sector_total >> 8;
01152             lba[1] = sector_total;
01153 
01154             controller->raise_irq();
01155             allow_writing = true;
01156             break;
01157         case 0x4B: /* PAUSE/RESUME */
01158             pause_resume();
01159 
01160             count = 0x03;
01161             feature = 0x00;
01162             sector_total = 0x00;
01163             state = IDE_DEV_DATA_READ;
01164             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01165 
01166             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
01167             lba[2] = sector_total >> 8;
01168             lba[1] = sector_total;
01169 
01170             controller->raise_irq();
01171             allow_writing = true;
01172             break;
01173         case 0x55: /* MODE SELECT(10) */
01174             /* we need the data written first, will act in I/O completion routine */
01175             {
01176                 unsigned int x;
01177 
01178                 x = (unsigned int)lba[1] + ((unsigned int)lba[2] << 8u);
01179 
01180                 /* Windows 95 likes to set 0xFFFF here for whatever reason.
01181                  * Negotiate it down to a maximum of 512 for sanity's sake */
01182                 if (x > 512) x = 512;
01183                 lba[2] = x >> 8u;
01184                 lba[1] = x;
01185 
01186 //              LOG_MSG("MODE SELECT expecting %u bytes\n",x);
01187                 prepare_write(0,(x+1u)&(~1u));
01188             }
01189 
01190             feature = 0x00;
01191             state = IDE_DEV_DATA_WRITE;
01192             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01193             controller->raise_irq();
01194             allow_writing = true;
01195             break;
01196         case 0x5A: /* MODE SENSE(10) */
01197             mode_sense();
01198 
01199             feature = 0x00;
01200             state = IDE_DEV_DATA_READ;
01201             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01202 
01203             /* ATAPI protocol also says we write back into LBA 23:8 what we're going to transfer in the block */
01204             lba[2] = sector_total >> 8;
01205             lba[1] = sector_total;
01206 
01207             controller->raise_irq();
01208             allow_writing = true;
01209             break;
01210         default:
01211             LOG_MSG("Unknown ATAPI command after busy wait. Why?\n");
01212             abort_error();
01213             controller->raise_irq();
01214             allow_writing = true;
01215             break;
01216     }
01217 
01218 }
01219 
01220 void IDEATAPICDROMDevice::set_sense(unsigned char SK,unsigned char ASC,unsigned char ASCQ,unsigned int len) {
01221     if (len < 18) len = 18;
01222     memset(sense,0,len);
01223     sense_length = len;
01224 
01225     sense[0] = 0x70;    /* RESPONSE CODE */
01226     sense[2] = SK&0xF;  /* SENSE KEY */
01227     sense[7] = len - 18;    /* additional sense length */
01228     sense[12] = ASC;
01229     sense[13] = ASCQ;
01230 }
01231 
01232 IDEATAPICDROMDevice::IDEATAPICDROMDevice(IDEController *c,unsigned char drive_index) : IDEDevice(c) {
01233     this->drive_index = drive_index;
01234     sector_i = sector_total = 0;
01235     atapi_to_host = false;
01236     host_maximum_byte_count = 0;
01237     LBA = 0;
01238     TransferLength = 0;
01239     memset(atapi_cmd, 0, sizeof(atapi_cmd));
01240     atapi_cmd_i = 0;
01241     atapi_cmd_total = 0;
01242     memset(sector, 0, sizeof(sector));
01243 
01244     memset(sense,0,sizeof(sense));
01245     IDEATAPICDROMDevice::set_sense(/*SK=*/0);
01246 
01247     /* FIXME: Spinup/down times should be dosbox.conf configurable, if the DOSBox gamers
01248      *        care more about loading times than emulation accuracy. */
01249     cd_insertion_time = 4000; /* a quick user that can switch CDs in 4 seconds */
01250     if (c->cd_insertion_time > 0) cd_insertion_time = c->cd_insertion_time;
01251 
01252     spinup_time = 1000; /* drive takes 1 second to spin up from idle */
01253     if (c->spinup_time > 0) spinup_time = c->spinup_time;
01254 
01255     spindown_timeout = 10000; /* drive spins down automatically after 10 seconds */
01256     if (c->spindown_timeout > 0) spindown_timeout = c->spindown_timeout;
01257 
01258     loading_mode = LOAD_IDLE;
01259     has_changed = false;
01260 
01261     type = IDE_TYPE_CDROM;
01262     id_serial = "123456789";
01263     id_firmware_rev = "0.83-X";
01264     id_model = "DOSBox-X Virtual CD-ROM";
01265 
01266     /* INQUIRY strings */
01267     id_mmc_vendor_id = "DOSBox-X";
01268     id_mmc_product_id = "Virtual CD-ROM";
01269     id_mmc_product_rev = "0.83-X";
01270 }
01271 
01272 IDEATAPICDROMDevice::~IDEATAPICDROMDevice() {
01273 }
01274 
01275 void IDEATAPICDROMDevice::on_mode_select_io_complete() {
01276     unsigned int AllocationLength = ((unsigned int)atapi_cmd[7] << 8) + atapi_cmd[8];
01277     unsigned char *scan,*fence;
01278     size_t i;
01279 
01280     /* the first 8 bytes are a mode parameter header.
01281      * It's supposed to provide length, density, etc. or whatever the hell
01282      * it means. Windows 95 seems to send all zeros there, so ignore it.
01283      *
01284      * we care about the bytes following it, which contain page_0 mode
01285      * pages */
01286 
01287     scan = sector + 8;
01288     fence = sector + MIN((unsigned int)sector_total,(unsigned int)AllocationLength);
01289 
01290     while ((scan+2) < fence) {
01291         unsigned char PAGE = *scan++;
01292         unsigned int LEN = (unsigned int)(*scan++);
01293 
01294         if ((scan+LEN) > fence) {
01295             LOG_MSG("ATAPI MODE SELECT warning, page_0 length extends %u bytes past buffer\n",(unsigned int)(scan+LEN-fence));
01296             break;
01297         }
01298 
01299         LOG_MSG("ATAPI MODE SELECT, PAGE 0x%02x len=%u\n",PAGE,LEN);
01300         LOG_MSG("  ");
01301         for (i=0;i < LEN;i++) LOG_MSG("%02x ",scan[i]);
01302         LOG_MSG("\n");
01303 
01304         scan += LEN;
01305     }
01306 }
01307 
01308 void IDEATAPICDROMDevice::atapi_io_completion() {
01309     /* for most ATAPI PACKET commands, the transfer is done and we need to clear
01310        all indication of a possible data transfer */
01311 
01312     if (count == 0x00) { /* the command was expecting data. now it can act on it */
01313         switch (atapi_cmd[0]) {
01314             case 0x55: /* MODE SELECT(10) */
01315                 on_mode_select_io_complete();
01316                 break;
01317         }
01318     }
01319 
01320     count = 0x03; /* no more data (command/data=1, input/output=1) */
01321     status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01322     state = IDE_DEV_READY;
01323     allow_writing = true;
01324 
01325     /* Apparently: real IDE ATAPI controllers fire another IRQ after the transfer.
01326        And there are MS-DOS CD-ROM drivers that assume that. */
01327     controller->raise_irq();
01328 }
01329     
01330 void IDEATAPICDROMDevice::io_completion() {
01331     /* lower DRQ */
01332     status &= ~IDE_STATUS_DRQ;
01333 
01334     /* depending on the command, either continue it or finish up */
01335     switch (command) {
01336         case 0xA0:/*ATAPI PACKET*/
01337             atapi_io_completion();
01338             break;
01339         default: /* most commands: signal drive ready, return to ready state */
01340             /* NTS: Some MS-DOS CD-ROM drivers will loop endlessly if we never set "drive seek complete"
01341                     because they like to hit the device with DEVICE RESET (08h) whether or not it's
01342                 a hard disk or CD-ROM drive */
01343             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01344             state = IDE_DEV_READY;
01345             allow_writing = true;
01346             break;
01347     }
01348 }
01349 
01350 bool IDEATADevice::increment_current_address(Bitu count) {
01351     if (count == 0) return false;
01352 
01353     if (drivehead_is_lba(drivehead)) {
01354         /* 28-bit LBA:
01355          *    drivehead: 27:24
01356          *    lba[2]:    23:16
01357          *    lba[1]:    15:8
01358          *    lba[0]:    7:0 */
01359         do {
01360             if (((++lba[0])&0xFF) == 0x00) {
01361                 lba[0] = 0x00;
01362                 if (((++lba[1])&0xFF) == 0x00) {
01363                     lba[1] = 0x00;
01364                     if (((++lba[2])&0xFF) == 0x00) {
01365                         lba[2] = 0x00;
01366                         if (((++drivehead)&0xF) == 0) {
01367                             drivehead -= 0x10;
01368                             return false;
01369                         }
01370                     }
01371                 }
01372             }
01373         } while ((--count) != 0);
01374     }
01375     else {
01376         /* C/H/S increment with rollover */
01377         do {
01378             /* increment sector */
01379             if (((++lba[0])&0xFF) == ((sects+1)&0xFF)) {
01380                 lba[0] = 1;
01381                 /* increment head */
01382                 if (((++drivehead)&0xF) == (heads&0xF)) {
01383                     drivehead &= 0xF0;
01384                     if (heads == 16) drivehead -= 0x10;
01385                     /* increment cylinder */
01386                     if (((++lba[1])&0xFF) == 0x00) {
01387                         if (((++lba[2])&0xFF) == 0x00) {
01388                             return false;
01389                         }
01390                     }
01391                 }
01392 
01393             }
01394         } while ((--count) != 0);
01395     }
01396 
01397     return true;
01398 }
01399 
01400 void IDEATADevice::io_completion() {
01401     /* lower DRQ */
01402     status &= ~IDE_STATUS_DRQ;
01403 
01404     /* depending on the command, either continue it or finish up */
01405     switch (command) {
01406         case 0x20:/* READ SECTOR */
01407             /* OK, decrement count, increment address */
01408             /* NTS: Remember that count == 0 means the host wanted to transfer 256 sectors */
01409             progress_count++;
01410             if ((count&0xFF) == 1) {
01411                 /* end of the transfer */
01412                 count = 0;
01413                 status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01414                 state = IDE_DEV_READY;
01415                 allow_writing = true;
01416                 return;
01417             }
01418             else if ((count&0xFF) == 0) count = 255;
01419             else count--;
01420 
01421             if (!increment_current_address()) {
01422                 LOG_MSG("READ advance error\n");
01423                 abort_error();
01424                 return;
01425             }
01426 
01427             /* cause another delay, another sector read */
01428             state = IDE_DEV_BUSY;
01429             status = IDE_STATUS_BUSY;
01430             PIC_AddEvent(IDE_DelayedCommand,0.00001/*ms*/,controller->interface_index);
01431             break;
01432         case 0x30:/* WRITE SECTOR */
01433             /* this is where the drive has accepted the sector, lowers DRQ, and begins executing the command */
01434             state = IDE_DEV_BUSY;
01435             status = IDE_STATUS_BUSY;
01436             PIC_AddEvent(IDE_DelayedCommand,((progress_count == 0 && !faked_command) ? 0.1 : 0.00001)/*ms*/,controller->interface_index);
01437             break;
01438         case 0xC4:/* READ MULTIPLE */
01439             /* OK, decrement count, increment address */
01440             /* NTS: Remember that count == 0 means the host wanted to transfer 256 sectors */
01441             for (unsigned int cc=0;cc < multiple_sector_count;cc++) {
01442                 progress_count++;
01443                 if ((count&0xFF) == 1) {
01444                     /* end of the transfer */
01445                     count = 0;
01446                     status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01447                     state = IDE_DEV_READY;
01448                     allow_writing = true;
01449                     return;
01450                 }
01451                 else if ((count&0xFF) == 0) count = 255;
01452                 else count--;
01453 
01454                 if (!increment_current_address()) {
01455                     LOG_MSG("READ advance error\n");
01456                     abort_error();
01457                     return;
01458                 }
01459             }
01460 
01461             /* cause another delay, another sector read */
01462             state = IDE_DEV_BUSY;
01463             status = IDE_STATUS_BUSY;
01464             PIC_AddEvent(IDE_DelayedCommand,0.00001/*ms*/,controller->interface_index);
01465             break;
01466         case 0xC5:/* WRITE MULTIPLE */
01467             /* this is where the drive has accepted the sector, lowers DRQ, and begins executing the command */
01468             state = IDE_DEV_BUSY;
01469             status = IDE_STATUS_BUSY;
01470             PIC_AddEvent(IDE_DelayedCommand,((progress_count == 0 && !faked_command) ? 0.1 : 0.00001)/*ms*/,controller->interface_index);
01471             break;
01472         default: /* most commands: signal drive ready, return to ready state */
01473             /* NTS: Some MS-DOS CD-ROM drivers will loop endlessly if we never set "drive seek complete"
01474                     because they like to hit the device with DEVICE RESET (08h) whether or not it's
01475                 a hard disk or CD-ROM drive */
01476             count = 0;
01477             drivehead &= 0xF0;
01478             lba[0] = 0;
01479             lba[1] = lba[2] = 0;
01480             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
01481             state = IDE_DEV_READY;
01482             allow_writing = true;
01483             break;
01484     }
01485 }
01486 
01487 Bitu IDEATAPICDROMDevice::data_read(Bitu iolen) {
01488     Bitu w = ~0u;
01489 
01490     if (state != IDE_DEV_DATA_READ)
01491         return 0xFFFFUL;
01492 
01493     if (!(status & IDE_STATUS_DRQ)) {
01494         LOG_MSG("IDE: Data read when DRQ=0\n");
01495         return 0xFFFFUL;
01496     }
01497 
01498     if (sector_i >= sector_total)
01499         return 0xFFFFUL;
01500 
01501     if (iolen >= 4) {
01502         w = host_readd(sector+sector_i);
01503         sector_i += 4;
01504     }
01505     else if (iolen >= 2) {
01506         w = host_readw(sector+sector_i);
01507         sector_i += 2;
01508     }
01509     /* NTS: Some MS-DOS CD-ROM drivers like OAKCDROM.SYS use byte-wide I/O for the initial identification */
01510     else if (iolen == 1) {
01511         w = sector[sector_i++];
01512     }
01513 
01514     if (sector_i >= sector_total)
01515         io_completion();
01516 
01517     return w;
01518 }
01519 
01520 /* TODO: Your code should also be paying attention to the "transfer length" field
01521          in many of the commands here. Right now it doesn't matter. */
01522 void IDEATAPICDROMDevice::atapi_cmd_completion() {
01523 #if 0
01524     LOG_MSG("ATAPI command %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x to_host=%u\n",
01525         atapi_cmd[ 0],atapi_cmd[ 1],atapi_cmd[ 2],atapi_cmd[ 3],atapi_cmd[ 4],atapi_cmd[ 5],
01526         atapi_cmd[ 6],atapi_cmd[ 7],atapi_cmd[ 8],atapi_cmd[ 9],atapi_cmd[10],atapi_cmd[11],
01527         atapi_to_host);
01528 #endif
01529 
01530     switch (atapi_cmd[0]) {
01531         case 0x00: /* TEST UNIT READY */
01532             if (common_spinup_response(/*spin up*/false,/*wait*/false))
01533                 set_sense(0); /* <- nothing wrong */
01534 
01535             count = 0x03;
01536             state = IDE_DEV_READY;
01537             feature = ((sense[2]&0xF) << 4) | ((sense[2]&0xF) ? 0x04/*abort*/ : 0x00);
01538             status = IDE_STATUS_DRIVE_READY|((sense[2]&0xF) ? IDE_STATUS_ERROR:IDE_STATUS_DRIVE_SEEK_COMPLETE);
01539             controller->raise_irq();
01540             allow_writing = true;
01541             break;
01542         case 0x03: /* REQUEST SENSE */
01543             count = 0x02;
01544             state = IDE_DEV_ATAPI_BUSY;
01545             status = IDE_STATUS_BUSY;
01546             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01547             break;
01548         case 0x1E: /* PREVENT ALLOW MEDIUM REMOVAL */
01549             count = 0x02;
01550             state = IDE_DEV_ATAPI_BUSY;
01551             status = IDE_STATUS_BUSY;
01552             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01553             break;
01554         case 0x25: /* READ CAPACITY */
01555             count = 0x02;
01556             state = IDE_DEV_ATAPI_BUSY;
01557             status = IDE_STATUS_BUSY;
01558             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01559             break;
01560         case 0x2B: /* SEEK */
01561             if (common_spinup_response(/*spin up*/true,/*wait*/true)) {
01562                 set_sense(0); /* <- nothing wrong */
01563                 count = 0x02;
01564                 state = IDE_DEV_ATAPI_BUSY;
01565                 status = IDE_STATUS_BUSY;
01566                 PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01567             }
01568             else {
01569                 count = 0x03;
01570                 state = IDE_DEV_READY;
01571                 feature = ((sense[2]&0xF) << 4) | ((sense[2]&0xF) ? 0x04/*abort*/ : 0x00);
01572                 status = IDE_STATUS_DRIVE_READY|((sense[2]&0xF) ? IDE_STATUS_ERROR:IDE_STATUS_DRIVE_SEEK_COMPLETE);
01573                 controller->raise_irq();
01574                 allow_writing = true;
01575             }
01576             break;
01577         case 0x12: /* INQUIRY */
01578             count = 0x02;
01579             state = IDE_DEV_ATAPI_BUSY;
01580             status = IDE_STATUS_BUSY;
01581             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01582             break;
01583         case 0xA8: /* READ(12) */
01584             if (common_spinup_response(/*spin up*/true,/*wait*/true)) {
01585                 set_sense(0); /* <- nothing wrong */
01586 
01587                 /* FIXME: MSCDEX.EXE appears to test the drive by issuing READ(10) with transfer length == 0.
01588                    This is all well and good but our response seems to cause a temporary 2-3 second
01589                    pause for each attempt. Why? */
01590                 LBA = ((Bitu)atapi_cmd[2] << 24UL) |
01591                     ((Bitu)atapi_cmd[3] << 16UL) |
01592                     ((Bitu)atapi_cmd[4] << 8UL) |
01593                     ((Bitu)atapi_cmd[5] << 0UL);
01594                 TransferLength = ((Bitu)atapi_cmd[6] << 24UL) |
01595                     ((Bitu)atapi_cmd[7] << 16UL) |
01596                     ((Bitu)atapi_cmd[8] << 8UL) |
01597                     ((Bitu)atapi_cmd[9]);
01598 
01599                 /* FIXME: We actually should NOT be capping the transfer length, but instead should
01600                    be breaking the larger transfer into smaller DRQ block transfers like
01601                    most IDE ATAPI drives do. Writing the test IDE code taught me that if you
01602                    go to most drives and request a transfer length of 0xFFFE the drive will
01603                    happily set itself up to transfer that many sectors in one IDE command! */
01604                 /* NTS: In case you're wondering, it's legal to issue READ(10) with transfer length == 0.
01605                    MSCDEX.EXE does it when starting up, for example */
01606                 if ((TransferLength*2048) > sizeof(sector))
01607                     TransferLength = sizeof(sector)/2048;
01608 
01609                 count = 0x02;
01610                 state = IDE_DEV_ATAPI_BUSY;
01611                 status = IDE_STATUS_BUSY;
01612                 /* TODO: Emulate CD-ROM spin-up delay, and seek delay */
01613                 PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 3)/*ms*/,controller->interface_index);
01614             }
01615             else {
01616                 count = 0x03;
01617                 state = IDE_DEV_READY;
01618                 feature = ((sense[2]&0xF) << 4) | ((sense[2]&0xF) ? 0x04/*abort*/ : 0x00);
01619                 status = IDE_STATUS_DRIVE_READY|((sense[2]&0xF) ? IDE_STATUS_ERROR:IDE_STATUS_DRIVE_SEEK_COMPLETE);
01620                 controller->raise_irq();
01621                 allow_writing = true;
01622             }
01623             break;
01624         case 0x28: /* READ(10) */
01625             if (common_spinup_response(/*spin up*/true,/*wait*/true)) {
01626                 set_sense(0); /* <- nothing wrong */
01627 
01628                 /* FIXME: MSCDEX.EXE appears to test the drive by issuing READ(10) with transfer length == 0.
01629                    This is all well and good but our response seems to cause a temporary 2-3 second
01630                    pause for each attempt. Why? */
01631                 LBA = ((Bitu)atapi_cmd[2] << 24UL) |
01632                     ((Bitu)atapi_cmd[3] << 16UL) |
01633                     ((Bitu)atapi_cmd[4] << 8UL) |
01634                     ((Bitu)atapi_cmd[5] << 0UL);
01635                 TransferLength = ((Bitu)atapi_cmd[7] << 8) |
01636                     ((Bitu)atapi_cmd[8]);
01637 
01638                 /* FIXME: We actually should NOT be capping the transfer length, but instead should
01639                    be breaking the larger transfer into smaller DRQ block transfers like
01640                    most IDE ATAPI drives do. Writing the test IDE code taught me that if you
01641                    go to most drives and request a transfer length of 0xFFFE the drive will
01642                    happily set itself up to transfer that many sectors in one IDE command! */
01643                 /* NTS: In case you're wondering, it's legal to issue READ(10) with transfer length == 0.
01644                    MSCDEX.EXE does it when starting up, for example */
01645                 if ((TransferLength*2048) > sizeof(sector))
01646                     TransferLength = sizeof(sector)/2048;
01647 
01648                 count = 0x02;
01649                 state = IDE_DEV_ATAPI_BUSY;
01650                 status = IDE_STATUS_BUSY;
01651                 /* TODO: Emulate CD-ROM spin-up delay, and seek delay */
01652                 PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 3)/*ms*/,controller->interface_index);
01653             }
01654             else {
01655                 count = 0x03;
01656                 state = IDE_DEV_READY;
01657                 feature = ((sense[2]&0xF) << 4) | ((sense[2]&0xF) ? 0x04/*abort*/ : 0x00);
01658                 status = IDE_STATUS_DRIVE_READY|((sense[2]&0xF) ? IDE_STATUS_ERROR:IDE_STATUS_DRIVE_SEEK_COMPLETE);
01659                 controller->raise_irq();
01660                 allow_writing = true;
01661             }
01662             break;
01663         case 0x42: /* READ SUB-CHANNEL */
01664             if (common_spinup_response(/*spin up*/true,/*wait*/true)) {
01665                 set_sense(0); /* <- nothing wrong */
01666 
01667                 count = 0x02;
01668                 state = IDE_DEV_ATAPI_BUSY;
01669                 status = IDE_STATUS_BUSY;
01670                 PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01671             }
01672             else {
01673                 count = 0x03;
01674                 state = IDE_DEV_READY;
01675                 feature = ((sense[2]&0xF) << 4) | ((sense[2]&0xF) ? 0x04/*abort*/ : 0x00);
01676                 status = IDE_STATUS_DRIVE_READY|((sense[2]&0xF) ? IDE_STATUS_ERROR:IDE_STATUS_DRIVE_SEEK_COMPLETE);
01677                 controller->raise_irq();
01678                 allow_writing = true;
01679             }
01680             break;
01681         case 0x43: /* READ TOC */
01682             if (common_spinup_response(/*spin up*/true,/*wait*/true)) {
01683                 set_sense(0); /* <- nothing wrong */
01684 
01685                 count = 0x02;
01686                 state = IDE_DEV_ATAPI_BUSY;
01687                 status = IDE_STATUS_BUSY;
01688                 PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01689             }
01690             else {
01691                 count = 0x03;
01692                 state = IDE_DEV_READY;
01693                 feature = ((sense[2]&0xF) << 4) | ((sense[2]&0xF) ? 0x04/*abort*/ : 0x00);
01694                 status = IDE_STATUS_DRIVE_READY|((sense[2]&0xF) ? IDE_STATUS_ERROR:IDE_STATUS_DRIVE_SEEK_COMPLETE);
01695                 controller->raise_irq();
01696                 allow_writing = true;
01697             }
01698             break;
01699         case 0x45: /* PLAY AUDIO (1) */
01700         case 0x47: /* PLAY AUDIO MSF */
01701         case 0x4B: /* PAUSE/RESUME */
01702             if (common_spinup_response(/*spin up*/true,/*wait*/true)) {
01703                 set_sense(0); /* <- nothing wrong */
01704 
01705                 count = 0x02;
01706                 state = IDE_DEV_ATAPI_BUSY;
01707                 status = IDE_STATUS_BUSY;
01708                 PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01709             }
01710             else {
01711                 count = 0x03;
01712                 state = IDE_DEV_READY;
01713                 feature = ((sense[2]&0xF) << 4) | ((sense[2]&0xF) ? 0x04/*abort*/ : 0x00);
01714                 status = IDE_STATUS_DRIVE_READY|((sense[2]&0xF) ? IDE_STATUS_ERROR:IDE_STATUS_DRIVE_SEEK_COMPLETE);
01715                 controller->raise_irq();
01716                 allow_writing = true;
01717             }
01718             break;
01719         case 0x55: /* MODE SELECT(10) */
01720             count = 0x00;   /* we will be accepting data */
01721             state = IDE_DEV_ATAPI_BUSY;
01722             status = IDE_STATUS_BUSY;
01723             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01724             break;
01725         case 0x5A: /* MODE SENSE(10) */
01726             count = 0x02;
01727             state = IDE_DEV_ATAPI_BUSY;
01728             status = IDE_STATUS_BUSY;
01729             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 1)/*ms*/,controller->interface_index);
01730             break;
01731         default:
01732             /* we don't know the command, immediately return an error */
01733             LOG_MSG("Unknown ATAPI command %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
01734                 atapi_cmd[ 0],atapi_cmd[ 1],atapi_cmd[ 2],atapi_cmd[ 3],atapi_cmd[ 4],atapi_cmd[ 5],
01735                 atapi_cmd[ 6],atapi_cmd[ 7],atapi_cmd[ 8],atapi_cmd[ 9],atapi_cmd[10],atapi_cmd[11]);
01736 
01737             abort_error();
01738             count = 0x03; /* no more data (command/data=1, input/output=1) */
01739             feature = 0xF4;
01740             controller->raise_irq();
01741             allow_writing = true;
01742             break;
01743     }
01744 }
01745 
01746 void IDEATAPICDROMDevice::data_write(Bitu v,Bitu iolen) {
01747     if (state == IDE_DEV_ATAPI_PACKET_COMMAND) {
01748         if (atapi_cmd_i < atapi_cmd_total)
01749             atapi_cmd[atapi_cmd_i++] = v;
01750         if (iolen >= 2 && atapi_cmd_i < atapi_cmd_total)
01751             atapi_cmd[atapi_cmd_i++] = v >> 8;
01752         if (iolen >= 4 && atapi_cmd_i < atapi_cmd_total) {
01753             atapi_cmd[atapi_cmd_i++] = v >> 16;
01754             atapi_cmd[atapi_cmd_i++] = v >> 24;
01755         }
01756 
01757         if (atapi_cmd_i >= atapi_cmd_total)
01758             atapi_cmd_completion();
01759     }
01760     else {
01761         if (state != IDE_DEV_DATA_WRITE) {
01762             LOG_MSG("ide atapi warning: data write when device not in data_write state\n");
01763             return;
01764         }
01765         if (!(status & IDE_STATUS_DRQ)) {
01766             LOG_MSG("ide atapi warning: data write with drq=0\n");
01767             return;
01768         }
01769         if ((sector_i+iolen) > sector_total) {
01770             LOG_MSG("ide atapi warning: sector already full %lu / %lu\n",(unsigned long)sector_i,(unsigned long)sector_total);
01771             return;
01772         }
01773 
01774         if (iolen >= 4) {
01775             host_writed(sector+sector_i,v);
01776             sector_i += 4;
01777         }
01778         else if (iolen >= 2) {
01779             host_writew(sector+sector_i,v);
01780             sector_i += 2;
01781         }
01782         else if (iolen == 1) {
01783             sector[sector_i++] = v;
01784         }
01785 
01786         if (sector_i >= sector_total)
01787             io_completion();
01788     }
01789 }
01790 
01791 Bitu IDEATADevice::data_read(Bitu iolen) {
01792     Bitu w = ~0u;
01793 
01794     if (state != IDE_DEV_DATA_READ)
01795         return 0xFFFFUL;
01796 
01797     if (!(status & IDE_STATUS_DRQ)) {
01798         LOG_MSG("IDE: Data read when DRQ=0\n");
01799         return 0xFFFFUL;
01800     }
01801 
01802     if ((sector_i+iolen) > sector_total) {
01803         LOG_MSG("ide ata warning: sector already read %lu / %lu\n",(unsigned long)sector_i,(unsigned long)sector_total);
01804         return 0xFFFFUL;
01805     }
01806 
01807     if (iolen >= 4) {
01808         w = host_readd(sector+sector_i);
01809         sector_i += 4;
01810     }
01811     else if (iolen >= 2) {
01812         w = host_readw(sector+sector_i);
01813         sector_i += 2;
01814     }
01815     /* NTS: Some MS-DOS CD-ROM drivers like OAKCDROM.SYS use byte-wide I/O for the initial identification */
01816     else if (iolen == 1) {
01817         w = sector[sector_i++];
01818     }
01819 
01820     if (sector_i >= sector_total)
01821         io_completion();
01822 
01823     return w;
01824 }
01825 
01826 void IDEATADevice::data_write(Bitu v,Bitu iolen) {
01827     if (state != IDE_DEV_DATA_WRITE) {
01828         LOG_MSG("ide ata warning: data write when device not in data_write state\n");
01829         return;
01830     }
01831     if (!(status & IDE_STATUS_DRQ)) {
01832         LOG_MSG("ide ata warning: data write with drq=0\n");
01833         return;
01834     }
01835     if ((sector_i+iolen) > sector_total) {
01836         LOG_MSG("ide ata warning: sector already full %lu / %lu\n",(unsigned long)sector_i,(unsigned long)sector_total);
01837         return;
01838     }
01839 
01840     if (iolen >= 4) {
01841         host_writed(sector+sector_i,v);
01842         sector_i += 4;
01843     }
01844     else if (iolen >= 2) {
01845         host_writew(sector+sector_i,v);
01846         sector_i += 2;
01847     }
01848     else if (iolen == 1) {
01849         sector[sector_i++] = v;
01850     }
01851 
01852     if (sector_i >= sector_total)
01853         io_completion();
01854 }
01855         
01856 void IDEATAPICDROMDevice::prepare_read(Bitu offset,Bitu size) {
01857     /* I/O must be WORD ALIGNED */
01858     assert((offset&1) == 0);
01859 //  assert((size&1) == 0);
01860 
01861     sector_i = offset;
01862     sector_total = size;
01863     assert(sector_i <= sector_total);
01864     assert(sector_total <= sizeof(sector));
01865 }
01866 
01867 void IDEATAPICDROMDevice::prepare_write(Bitu offset,Bitu size) {
01868     /* I/O must be WORD ALIGNED */
01869     assert((offset&1) == 0);
01870 //  assert((size&1) == 0);
01871 
01872     sector_i = offset;
01873     sector_total = size;
01874     assert(sector_i <= sector_total);
01875     assert(sector_total <= sizeof(sector));
01876 }
01877 
01878 void IDEATADevice::prepare_write(Bitu offset,Bitu size) {
01879     /* I/O must be WORD ALIGNED */
01880     assert((offset&1) == 0);
01881 //  assert((size&1) == 0);
01882 
01883     sector_i = offset;
01884     sector_total = size;
01885     assert(sector_i <= sector_total);
01886     assert(sector_total <= sizeof(sector));
01887 }
01888 
01889 void IDEATADevice::prepare_read(Bitu offset,Bitu size) {
01890     /* I/O must be WORD ALIGNED */
01891     assert((offset&1) == 0);
01892 //  assert((size&1) == 0);
01893 
01894     sector_i = offset;
01895     sector_total = size;
01896     assert(sector_i <= sector_total);
01897     assert(sector_total <= sizeof(sector));
01898 }
01899 
01900 void IDEATAPICDROMDevice::generate_mmc_inquiry() {
01901     Bitu i;
01902 
01903     /* IN RESPONSE TO ATAPI COMMAND 0x12: INQUIRY */
01904     memset(sector,0,36);
01905     sector[0] = (0 << 5) | 5;   /* Peripheral qualifier=0   device type=5 (CDROM) */
01906     sector[1] = 0x80;       /* RMB=1 removable media */
01907     sector[3] = 0x21;
01908     sector[4] = 36 - 5;     /* additional length */
01909 
01910     for (i=0;i < 8 && i < id_mmc_vendor_id.length();i++)
01911         sector[i+8] = (unsigned char)id_mmc_vendor_id[i];
01912     for (;i < 8;i++)
01913         sector[i+8] = ' ';
01914 
01915     for (i=0;i < 16 && i < id_mmc_product_id.length();i++)
01916         sector[i+16] = (unsigned char)id_mmc_product_id[i];
01917     for (;i < 16;i++)
01918         sector[i+16] = ' ';
01919 
01920     for (i=0;i < 4 && i < id_mmc_product_rev.length();i++)
01921         sector[i+32] = (unsigned char)id_mmc_product_rev[i];
01922     for (;i < 4;i++)
01923         sector[i+32] = ' ';
01924 }
01925 
01926 void IDEATAPICDROMDevice::generate_identify_device() {
01927     unsigned char csum;
01928     Bitu i;
01929 
01930     /* IN RESPONSE TO IDENTIFY DEVICE (0xA1)
01931        GENERATE 512-BYTE REPLY */
01932     memset(sector,0,512);
01933 
01934     host_writew(sector+(0*2),0x85C0U);  /* ATAPI device, command set #5 (what the fuck does that mean?), removable, */
01935 
01936     for (i=0;i < 20 && i < id_serial.length();i++)
01937         sector[(i^1)+(10*2)] = (unsigned char)id_serial[i];
01938     for (;i < 20;i++)
01939         sector[(i^1)+(10*2)] = ' ';
01940 
01941     for (i=0;i < 8 && i < id_firmware_rev.length();i++)
01942         sector[(i^1)+(23*2)] = (unsigned char)id_firmware_rev[i];
01943     for (;i < 8;i++)
01944         sector[(i^1)+(23*2)] = ' ';
01945 
01946     for (i=0;i < 40 && i < id_model.length();i++)
01947         sector[(i^1)+(27*2)] = (unsigned char)id_model[i];
01948     for (;i < 40;i++)
01949         sector[(i^1)+(27*2)] = ' ';
01950 
01951     host_writew(sector+(49*2),
01952         0x0800UL|/*IORDY supported*/
01953         0x0200UL|/*must be one*/
01954         0);
01955     host_writew(sector+(50*2),
01956         0x4000UL);
01957     host_writew(sector+(51*2),
01958         0x00F0UL);
01959     host_writew(sector+(52*2),
01960         0x00F0UL);
01961     host_writew(sector+(53*2),
01962         0x0006UL);
01963     host_writew(sector+(64*2),      /* PIO modes supported */
01964         0x0003UL);
01965     host_writew(sector+(67*2),      /* PIO cycle time */
01966         0x0078UL);
01967     host_writew(sector+(68*2),      /* PIO cycle time */
01968         0x0078UL);
01969     host_writew(sector+(80*2),0x007E); /* major version number. Here we say we support ATA-1 through ATA-8 */
01970     host_writew(sector+(81*2),0x0022); /* minor version */
01971     host_writew(sector+(82*2),0x4008); /* command set: NOP, DEVICE RESET[XXXXX], POWER MANAGEMENT */
01972     host_writew(sector+(83*2),0x0000); /* command set: LBA48[XXXX] */
01973     host_writew(sector+(85*2),0x4208); /* commands in 82 enabled */
01974     host_writew(sector+(86*2),0x0000); /* commands in 83 enabled */
01975 
01976     /* ATA-8 integrity checksum */
01977     sector[510] = 0xA5;
01978     csum = 0; for (i=0;i < 511;i++) csum += sector[i];
01979     sector[511] = 0 - csum;
01980 }
01981 
01982 void IDEATADevice::generate_identify_device() {
01983 //  imageDisk *disk = getBIOSdisk();
01984     unsigned char csum;
01985     uint64_t ptotal;
01986     uint64_t total;
01987     Bitu i;
01988 
01989     /* IN RESPONSE TO IDENTIFY DEVICE (0xEC)
01990        GENERATE 512-BYTE REPLY */
01991     memset(sector,0,512);
01992 
01993     /* total disk capacity in sectors */
01994     total = sects * cyls * heads;
01995     ptotal = phys_sects * phys_cyls * phys_heads;
01996 
01997     host_writew(sector+(0*2),0x0040);   /* bit 6: 1=fixed disk */
01998     host_writew(sector+(1*2),phys_cyls);
01999     host_writew(sector+(3*2),phys_heads);
02000     host_writew(sector+(4*2),phys_sects * 512); /* unformatted bytes per track */
02001     host_writew(sector+(5*2),512);      /* unformatted bytes per sector */
02002     host_writew(sector+(6*2),phys_sects);
02003 
02004     for (i=0;i < 20 && i < id_serial.length();i++)
02005         sector[(i^1)+(10*2)] = (unsigned char)id_serial[i];
02006     for (;i < 20;i++)
02007         sector[(i^1)+(10*2)] = ' ';
02008 
02009     host_writew(sector+(20*2),1);       /* ATA-1: single-ported single sector buffer */
02010     host_writew(sector+(21*2),4);       /* ATA-1: ECC bytes on read/write long */
02011 
02012     for (i=0;i < 8 && i < id_firmware_rev.length();i++)
02013         sector[(i^1)+(23*2)] = (unsigned char)id_firmware_rev[i];
02014     for (;i < 8;i++)
02015         sector[(i^1)+(23*2)] = ' ';
02016 
02017     for (i=0;i < 40 && i < id_model.length();i++)
02018         sector[(i^1)+(27*2)] = (unsigned char)id_model[i];
02019     for (;i < 40;i++)
02020         sector[(i^1)+(27*2)] = ' ';
02021 
02022     if (multiple_sector_max != 0)
02023         host_writew(sector+(47*2),0x80|multiple_sector_max); /* <- READ/WRITE MULTIPLE MAX SECTORS */
02024 
02025     host_writew(sector+(48*2),0x0000);  /* :0  0=we do not support doubleword (32-bit) PIO */
02026     host_writew(sector+(49*2),0x0A00);  /* :13 0=Standby timer values managed by device */
02027                         /* :11 1=IORDY supported */
02028                         /* :10 0=IORDY not disabled */
02029                         /* :9  1=LBA supported */
02030                         /* :8  0=DMA not supported */
02031     host_writew(sector+(50*2),0x4000);  /* FIXME: ??? */
02032     host_writew(sector+(51*2),0x00F0);  /* PIO data transfer cycle timing mode */
02033     host_writew(sector+(52*2),0x00F0);  /* DMA data transfer cycle timing mode */
02034     host_writew(sector+(53*2),0x0007);  /* :2  1=the fields in word 88 are valid */
02035                         /* :1  1=the fields in word (70:64) are valid */
02036                         /* :0  1= ??? */
02037     host_writew(sector+(54*2),cyls);    /* current cylinders */
02038     host_writew(sector+(55*2),heads);   /* current heads */
02039     host_writew(sector+(56*2),sects);   /* current sectors per track */
02040     host_writed(sector+(57*2),total);   /* current capacity in sectors */
02041 
02042     if (multiple_sector_count != 0)
02043         host_writew(sector+(59*2),0x0100|multiple_sector_count); /* :8  multiple sector setting is valid */
02044                         /* 7:0 current setting for number of log. sectors per DRQ of READ/WRITE MULTIPLE */
02045 
02046     host_writed(sector+(60*2),ptotal);  /* total user addressable sectors (LBA) */
02047     host_writew(sector+(62*2),0x0000);  /* FIXME: ??? */
02048     host_writew(sector+(63*2),0x0000);  /* :10 0=Multiword DMA mode 2 not selected */
02049                         /* TODO: Basically, we don't do DMA. Fill out this comment */
02050     host_writew(sector+(64*2),0x0003);  /* 7:0 PIO modes supported (FIXME ???) */
02051     host_writew(sector+(65*2),0x0000);  /* FIXME: ??? */
02052     host_writew(sector+(66*2),0x0000);  /* FIXME: ??? */
02053     host_writew(sector+(67*2),0x0078);  /* FIXME: ??? */
02054     host_writew(sector+(68*2),0x0078);  /* FIXME: ??? */
02055     host_writew(sector+(80*2),0x007E);  /* major version number. Here we say we support ATA-1 through ATA-8 */
02056     host_writew(sector+(81*2),0x0022);  /* minor version */
02057     host_writew(sector+(82*2),0x4208);  /* command set: NOP, DEVICE RESET[XXXXX], POWER MANAGEMENT */
02058     host_writew(sector+(83*2),0x4000);  /* command set: LBA48[XXXX] */
02059     host_writew(sector+(84*2),0x4000);  /* FIXME: ??? */
02060     host_writew(sector+(85*2),0x4208);  /* commands in 82 enabled */
02061     host_writew(sector+(86*2),0x4000);  /* commands in 83 enabled */
02062     host_writew(sector+(87*2),0x4000);  /* FIXME: ??? */
02063     host_writew(sector+(88*2),0x0000);  /* FIXME: ??? */
02064     host_writew(sector+(93*3),0x0000);  /* FIXME: ??? */
02065 
02066     /* ATA-8 integrity checksum */
02067     sector[510] = 0xA5;
02068     csum = 0; for (i=0;i < 511;i++) csum += sector[i];
02069     sector[511] = 0 - csum;
02070 }
02071 
02072 IDEATADevice::IDEATADevice(IDEController *c,unsigned char disk_index)
02073     : IDEDevice(c), id_serial("8086"), id_firmware_rev("8086"), id_model("DOSBox IDE disk"), bios_disk_index(disk_index) {
02074     sector_i = sector_total = 0;
02075 
02076     headshr = 0;
02077     type = IDE_TYPE_HDD;
02078     multiple_sector_max = sizeof(sector) / 512;
02079     multiple_sector_count = 1;
02080     geo_translate = false;
02081     heads = 0;
02082     sects = 0;
02083     cyls = 0;
02084     progress_count = 0;
02085     phys_heads = 0;
02086     phys_sects = 0;
02087     phys_cyls = 0;
02088 }
02089 
02090 IDEATADevice::~IDEATADevice() {
02091 }
02092 
02093 imageDisk *IDEATADevice::getBIOSdisk() {
02094     if (bios_disk_index >= (2 + MAX_HDD_IMAGES)) return NULL;
02095     return imageDiskList[bios_disk_index];
02096 }
02097 
02098 CDROM_Interface *IDEATAPICDROMDevice::getMSCDEXDrive() {
02099     CDROM_Interface *cdrom=NULL;
02100 
02101     if (!GetMSCDEXDrive(drive_index,&cdrom))
02102         return NULL;
02103 
02104     return cdrom;
02105 }
02106 
02107 void IDEATAPICDROMDevice::update_from_cdrom() {
02108     CDROM_Interface *cdrom = getMSCDEXDrive();
02109     if (cdrom == NULL) {
02110         LOG_MSG("WARNING: IDE update from CD-ROM failed, disk not available\n");
02111         return;
02112     }
02113 }
02114 
02115 void IDEATADevice::update_from_biosdisk() {
02116     imageDisk *dsk = getBIOSdisk();
02117     if (dsk == NULL) {
02118         LOG_MSG("WARNING: IDE update from BIOS disk failed, disk not available\n");
02119         return;
02120     }
02121 
02122     headshr = 0;
02123     geo_translate = false;
02124     cyls = dsk->cylinders;
02125     heads = dsk->heads;
02126     sects = dsk->sectors;
02127 
02128     /* One additional correction: The disk image is probably using BIOS-style geometry
02129        translation (such as C/H/S 1024/64/63) which is impossible given that the IDE
02130        standard only allows up to 16 heads. So we have to translate the geometry. */
02131     while (heads > 16 && (heads & 1) == 0) {
02132         cyls <<= 1U;
02133         heads >>= 1U;
02134         headshr++;
02135     }
02136 
02137     /* If we can't divide the heads down, then pick a LBA-like mapping that is good enough.
02138      * Note that if what we pick does not evenly map to the INT 13h geometry, and the partition
02139      * contained within is not an LBA type FAT16/FAT32 partition, then Windows 95's IDE driver
02140      * will ignore this device and fall back to using INT 13h. For user convenience we will
02141      * print a warning to reminder the user of exactly that. */
02142     if (heads > 16) {
02143         unsigned long tmp;
02144 
02145         geo_translate = true;
02146 
02147         tmp = heads * cyls * sects;
02148         sects = 63;
02149         heads = 16;
02150         cyls = (tmp + ((63 * 16) - 1)) / (63 * 16);
02151         LOG_MSG("WARNING: Unable to reduce heads to 16 and below\n");
02152         LOG_MSG("If at all possible, please consider using INT 13h geometry with a head\n");
02153         LOG_MSG("count that is easier to map to the BIOS, like 240 heads or 128 heads/track.\n");
02154         LOG_MSG("Some OSes, such as Windows 95, will not enable their 32-bit IDE driver if\n");
02155         LOG_MSG("a clean mapping does not exist between IDE and BIOS geometry.\n");
02156         LOG_MSG("Mapping BIOS DISK C/H/S %u/%u/%u as IDE %u/%u/%u (non-straightforward mapping)\n",
02157             (unsigned int)dsk->cylinders,
02158             (unsigned int)dsk->heads,
02159             (unsigned int)dsk->sectors,
02160             (unsigned int)cyls,
02161             (unsigned int)heads,
02162             (unsigned int)sects);
02163     }
02164     else {
02165         LOG_MSG("Mapping BIOS DISK C/H/S %u/%u/%u as IDE %u/%u/%u\n",
02166             (unsigned int)dsk->cylinders,
02167             (unsigned int)dsk->heads,
02168             (unsigned int)dsk->sectors,
02169             (unsigned int)cyls,
02170             (unsigned int)heads,
02171             (unsigned int)sects);
02172     }
02173 
02174     phys_heads = heads;
02175     phys_sects = sects;
02176     phys_cyls = cyls;
02177 }
02178 
02179 void IDE_Auto(signed char &index,bool &slave) {
02180     unsigned int i;
02181 
02182     index = -1;
02183     slave = false;
02184     for (i=0;i < MAX_IDE_CONTROLLERS;i++) {
02185         IDEController* c;
02186         if ((c=idecontroller[i]) == NULL) continue;
02187         index = (signed char)i;
02188 
02189         if (c->device[0] == NULL) {
02190             slave = false;
02191             break;
02192         }
02193         if (c->device[1] == NULL) {
02194             slave = true;
02195             break;
02196         }
02197     }
02198 }
02199 
02200 /* drive_index = drive letter 0...A to 25...Z */
02201 void IDE_ATAPI_MediaChangeNotify(unsigned char drive_index) {
02202     for (unsigned int ide=0;ide < MAX_IDE_CONTROLLERS;ide++) {
02203         IDEController *c = idecontroller[ide];
02204         if (c == NULL) continue;
02205         for (unsigned int ms=0;ms < 2;ms++) {
02206             IDEDevice *dev = c->device[ms];
02207             if (dev == NULL) continue;
02208             if (dev->type == IDE_TYPE_CDROM) {
02209                 IDEATAPICDROMDevice *atapi = (IDEATAPICDROMDevice*)dev;
02210                 if (drive_index == atapi->drive_index) {
02211                     LOG_MSG("IDE ATAPI acknowledge media change for drive %c\n",drive_index+'A');
02212                     atapi->has_changed = true;
02213                     atapi->loading_mode = LOAD_INSERT_CD;
02214                     PIC_RemoveSpecificEvents(IDE_ATAPI_SpinDown,c->interface_index);
02215                     PIC_RemoveSpecificEvents(IDE_ATAPI_SpinUpComplete,c->interface_index);
02216                     PIC_RemoveSpecificEvents(IDE_ATAPI_CDInsertion,c->interface_index);
02217                     PIC_AddEvent(IDE_ATAPI_CDInsertion,atapi->cd_insertion_time/*ms*/,c->interface_index);
02218                 }
02219             }
02220         }
02221     }
02222 }
02223 
02224 /* drive_index = drive letter 0...A to 25...Z */
02225 void IDE_CDROM_Attach(signed char index,bool slave,unsigned char drive_index) {
02226     IDEController *c;
02227     IDEATAPICDROMDevice *dev;
02228 
02229     if (index < 0 || index >= MAX_IDE_CONTROLLERS) return;
02230     c = idecontroller[index];
02231     if (c == NULL) return;
02232 
02233     if (c->device[slave?1:0] != NULL) {
02234         LOG_MSG("IDE: Controller %u %s already taken\n",index,slave?"slave":"master");
02235         return;
02236     }
02237 
02238     if (!GetMSCDEXDrive(drive_index,NULL)) {
02239         LOG_MSG("IDE: Asked to attach CD-ROM that does not exist\n");
02240         return;
02241     }
02242 
02243     dev = new IDEATAPICDROMDevice(c,drive_index);
02244     if (dev == NULL) return;
02245     dev->update_from_cdrom();
02246     c->device[slave?1:0] = (IDEDevice*)dev;
02247 }
02248 
02249 /* drive_index = drive letter 0...A to 25...Z */
02250 void IDE_CDROM_Detach(unsigned char drive_index) {
02251     for (int index = 0; index < MAX_IDE_CONTROLLERS; index++) {
02252         IDEController *c = idecontroller[index];
02253         if (c)
02254         for (int slave = 0; slave < 2; slave++) {
02255             IDEATAPICDROMDevice *dev;
02256             dev = dynamic_cast<IDEATAPICDROMDevice*>(c->device[slave]);
02257             if (dev && dev->drive_index == drive_index) {
02258                 delete dev;
02259                 c->device[slave] = NULL;
02260             }
02261         }
02262     }
02263 }
02264 
02265 /* bios_disk_index = index into BIOS INT 13h disk array: imageDisk *imageDiskList[MAX_DISK_IMAGES]; */
02266 void IDE_Hard_Disk_Attach(signed char index,bool slave,unsigned char bios_disk_index/*not INT13h, the index into DOSBox's BIOS drive emulation*/) {
02267     IDEController *c;
02268     IDEATADevice *dev;
02269 
02270     if (index < 0 || index >= MAX_IDE_CONTROLLERS) return;
02271     c = idecontroller[index];
02272     if (c == NULL) return;
02273 
02274     if (c->device[slave?1:0] != NULL) {
02275         LOG_MSG("IDE: Controller %u %s already taken\n",index,slave?"slave":"master");
02276         return;
02277     }
02278 
02279     if (imageDiskList[bios_disk_index] == NULL) {
02280         LOG_MSG("IDE: Asked to attach bios disk that does not exist\n");
02281         return;
02282     }
02283 
02284     dev = new IDEATADevice(c,bios_disk_index);
02285     if (dev == NULL) return;
02286     dev->update_from_biosdisk();
02287     c->device[slave?1:0] = (IDEDevice*)dev;
02288 }
02289 
02290 /* bios_disk_index = index into BIOS INT 13h disk array: imageDisk *imageDiskList[MAX_DISK_IMAGES]; */
02291 void IDE_Hard_Disk_Detach(unsigned char bios_disk_index) {
02292     for (int index = 0; index < MAX_IDE_CONTROLLERS; index++) {
02293         IDEController *c = idecontroller[index];
02294         if (c)
02295         for (int slave = 0; slave < 2; slave++) {
02296             IDEATADevice *dev;
02297             dev = dynamic_cast<IDEATADevice*>(c->device[slave]);
02298             if (dev && dev->bios_disk_index == bios_disk_index) {
02299                 delete dev;
02300                 c->device[slave] = NULL;
02301             }
02302         }
02303     }
02304 }
02305 static IDEController* GetIDEController(Bitu idx) {
02306     if (idx >= MAX_IDE_CONTROLLERS) return NULL;
02307     return idecontroller[idx];
02308 }
02309 
02310 static IDEDevice* GetIDESelectedDevice(IDEController *ide) {
02311     if (ide == NULL) return NULL;
02312     return ide->device[ide->select];
02313 }
02314 
02315 static bool IDE_CPU_Is_Vm86() {
02316     return (cpu.pmode && ((GETFLAG_IOPL<cpu.cpl) || GETFLAG(VM)));
02317 }
02318 
02319 static void ide_baseio_w(Bitu port,Bitu val,Bitu iolen);
02320 
02321 static Bitu IDE_SelfIO_In(IDEController *ide,Bitu port,Bitu len) {
02322     if (ide->int13fakev86io && IDE_CPU_Is_Vm86()) {
02323         /* Trigger I/O in virtual 8086 mode, where the OS can trap it and act on it.
02324          * Windows 95 uses V86 traps to help "autodetect" what IDE drive and port the
02325          * BIOS uses on INT 13h so that it's internal IDE driver can take over, which
02326          * is the whole reason for this hack. */
02327         return CPU_ForceV86FakeIO_In(port,len);
02328     }
02329     else {
02330         return ide_baseio_r(port,len);
02331     }
02332 }
02333 
02334 static void IDE_SelfIO_Out(IDEController *ide,Bitu port,Bitu val,Bitu len) {
02335     if (ide->int13fakev86io && IDE_CPU_Is_Vm86()) {
02336         /* Trigger I/O in virtual 8086 mode, where the OS can trap it and act on it.
02337          * Windows 95 uses V86 traps to help "autodetect" what IDE drive and port the
02338          * BIOS uses on INT 13h so that it's internal IDE driver can take over, which
02339          * is the whole reason for this hack. */
02340         CPU_ForceV86FakeIO_Out(port,val,len);
02341     }
02342     else {
02343         ide_baseio_w(port,val,len);
02344     }
02345 }
02346 
02347 /* INT 13h extensions */
02348 void IDE_EmuINT13DiskReadByBIOS_LBA(unsigned char disk,uint64_t lba) {
02349     IDEController *ide;
02350     IDEDevice *dev;
02351     Bitu idx,ms;
02352 
02353     if (disk < 0x80) return;
02354     if (lba >= (1ULL << 28ULL)) return; /* this code does not support LBA48 */
02355 
02356     for (idx=0;idx < MAX_IDE_CONTROLLERS;idx++) {
02357         ide = GetIDEController(idx);
02358         if (ide == NULL) continue;
02359         if (!ide->int13fakeio && !ide->int13fakev86io) continue;
02360 
02361         /* TODO: Print a warning message if the IDE controller is busy (debug/warning message) */
02362 
02363         /* TODO: Force IDE state to readiness, abort command, etc. */
02364 
02365         /* for master/slave device... */
02366         for (ms=0;ms < 2;ms++) {
02367             dev = ide->device[ms];
02368             if (dev == NULL) continue;
02369 
02370             /* TODO: Print a warning message if the IDE device is busy or in the middle of a command */
02371 
02372             /* TODO: Forcibly device-reset the IDE device */
02373 
02374             /* Issue I/O to ourself to select drive */
02375             dev->faked_command = true;
02376             IDE_SelfIO_In(ide,ide->base_io+7u,1);
02377             IDE_SelfIO_Out(ide,ide->base_io+6u,0x00+(ms<<4u),1);
02378             dev->faked_command = false;
02379 
02380             if (dev->type == IDE_TYPE_HDD) {
02381                 IDEATADevice *ata = (IDEATADevice*)dev;
02382 //              static bool int13_fix_wrap_warned = false;
02383                 bool vm86 = IDE_CPU_Is_Vm86();
02384 
02385                 if ((ata->bios_disk_index-2) == (disk-0x80)) {
02386 //                  imageDisk *dsk = ata->getBIOSdisk();
02387 
02388                     if (ide->int13fakev86io && vm86) {
02389                         dev->faked_command = true;
02390 
02391                         /* we MUST clear interrupts.
02392                          * leaving them enabled causes Win95 (or DOSBox?) to recursively
02393                          * pagefault and DOSBox to crash. In any case it seems Win95's
02394                          * IDE driver assumes the BIOS INT 13h code will do this since
02395                          * it's customary for the BIOS to do it at some point, usually
02396                          * just before reading the sector data. */
02397                         CPU_CLI();
02398 
02399                         /* We're in virtual 8086 mode and we're asked to fake I/O as if
02400                          * executing a BIOS subroutine. Some OS's like Windows 95 rely on
02401                          * executing INT 13h in virtual 8086 mode: on startup, the ESDI
02402                          * driver traps IDE ports and then executes INT 13h to watch what
02403                          * I/O ports it uses. It then uses that information to decide
02404                          * what IDE hard disk and controller corresponds to what DOS
02405                          * drive. So to get 32-bit disk access to work in Windows 95,
02406                          * we have to put on a good show to convince Windows 95 we're
02407                          * a legitimate BIOS INT 13h call doing it's job. */
02408                         IDE_SelfIO_In(ide,ide->base_io+7u,1);        /* dum de dum reading status */
02409                         IDE_SelfIO_Out(ide,ide->base_io+6u,(ms<<4u)+0xE0u+(lba>>24u),1); /* drive and head */
02410                         IDE_SelfIO_In(ide,ide->base_io+7u,1);        /* dum de dum reading status */
02411                         IDE_SelfIO_Out(ide,ide->base_io+2u,0x01,1);  /* sector count */
02412                         IDE_SelfIO_Out(ide,ide->base_io+3u,lba&0xFF,1);  /* sector number */
02413                         IDE_SelfIO_Out(ide,ide->base_io+4u,(lba>>8u)&0xFF,1); /* cylinder lo */
02414                         IDE_SelfIO_Out(ide,ide->base_io+5u,(lba>>16u)&0xFF,1); /* cylinder hi */
02415                         IDE_SelfIO_Out(ide,ide->base_io+6u,(ms<<4u)+0xE0+(lba>>24u),1); /* drive and head */
02416                         IDE_SelfIO_In(ide,ide->base_io+7u,1);        /* dum de dum reading status */
02417                         IDE_SelfIO_Out(ide,ide->base_io+7u,0x20,1);  /* issue READ */
02418 
02419                         do {
02420                             /* TODO: Timeout needed */
02421                             unsigned int i = IDE_SelfIO_In(ide,ide->alt_io,1);
02422                             if ((i&0x80) == 0) break;
02423                         } while (1);
02424                         IDE_SelfIO_In(ide,ide->base_io+7u,1);
02425 
02426                         /* for brevity assume it worked. we're here to bullshit Windows 95 after all */
02427                         for (unsigned int i=0;i < 256;i++)
02428                             IDE_SelfIO_In(ide,ide->base_io+0u,2); /* 16-bit IDE data read */
02429 
02430                         /* one more */
02431                         IDE_SelfIO_In(ide,ide->base_io+7u,1);        /* dum de dum reading status */
02432 
02433                         /* assume IRQ happened and clear it */
02434                         if (ide->IRQ >= 8)
02435                             IDE_SelfIO_Out(ide,0xA0,0x60u+(unsigned int)ide->IRQ-8u,1);     /* specific EOI */
02436                         else
02437                             IDE_SelfIO_Out(ide,0x20,0x60u+(unsigned int)ide->IRQ,1);       /* specific EOI */
02438 
02439                         ata->abort_normal();
02440                         dev->faked_command = false;
02441                     }
02442                     else {
02443                         /* hack IDE state as if a BIOS executing IDE disk routines.
02444                          * This is required if we want IDE emulation to work with Windows 3.11 Windows for Workgroups 32-bit disk access (WDCTRL),
02445                          * because the driver "tests" the controller by issuing INT 13h calls then reading back IDE registers to see if
02446                          * they match the C/H/S it requested */
02447                         dev->feature = 0x00;        /* clear error (WDCTRL test phase 5/C/13) */
02448                         dev->count = 0x00;      /* clear sector count (WDCTRL test phase 6/D/14) */
02449                         dev->lba[0] = lba&0xFF;     /* leave sector number the same (WDCTRL test phase 7/E/15) */
02450                         dev->lba[1] = (lba>>8u)&0xFF;    /* leave cylinder the same (WDCTRL test phase 8/F/16) */
02451                         dev->lba[2] = (lba>>16u)&0xFF;   /* ...ditto */
02452                         ide->drivehead = dev->drivehead = 0xE0u | (ms<<4u) | (lba>>24u); /* drive head and master/slave (WDCTRL test phase 9/10/17) */
02453                         dev->status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE; /* status (WDCTRL test phase A/11/18) */
02454                         dev->allow_writing = true;
02455                         static bool vm86_warned = false;
02456 
02457                         if (vm86 && !vm86_warned) {
02458                             LOG_MSG("IDE warning: INT 13h extensions read from virtual 8086 mode.\n");
02459                             LOG_MSG("             If using Windows 95 OSR2, please set int13fakev86io=true for proper 32-bit disk access\n");
02460                             vm86_warned = true;
02461                         }
02462                     }
02463 
02464                     /* break out, we're done */
02465                     idx = MAX_IDE_CONTROLLERS;
02466                     break;
02467                 }
02468             }
02469         }
02470     }
02471 }
02472 
02473 /* this is called after INT 13h AH=0x02 READ DISK to change IDE state to simulate the BIOS in action.
02474  * this is needed for old "32-bit disk drivers" like WDCTRL in Windows 3.11 Windows for Workgroups,
02475  * which issues INT 13h to read-test and then reads IDE registers to see if they match expectations */
02476 void IDE_EmuINT13DiskReadByBIOS(unsigned char disk,unsigned int cyl,unsigned int head,unsigned sect) {
02477     IDEController *ide;
02478     IDEDevice *dev;
02479     Bitu idx,ms;
02480 
02481     if (disk < 0x80) return;
02482 
02483     for (idx=0;idx < MAX_IDE_CONTROLLERS;idx++) {
02484         ide = GetIDEController(idx);
02485         if (ide == NULL) continue;
02486         if (!ide->int13fakeio && !ide->int13fakev86io) continue;
02487 
02488         /* TODO: Print a warning message if the IDE controller is busy (debug/warning message) */
02489 
02490         /* TODO: Force IDE state to readiness, abort command, etc. */
02491 
02492         /* for master/slave device... */
02493         for (ms=0;ms < 2;ms++) {
02494             dev = ide->device[ms];
02495             if (dev == NULL) continue;
02496 
02497             /* TODO: Print a warning message if the IDE device is busy or in the middle of a command */
02498 
02499             /* TODO: Forcibly device-reset the IDE device */
02500 
02501             /* Issue I/O to ourself to select drive */
02502             dev->faked_command = true;
02503             IDE_SelfIO_In(ide,ide->base_io+7u,1);
02504             IDE_SelfIO_Out(ide,ide->base_io+6u,0x00u+(ms<<4u),1);
02505             dev->faked_command = false;
02506 
02507             if (dev->type == IDE_TYPE_HDD) {
02508                 IDEATADevice *ata = (IDEATADevice*)dev;
02509                 bool vm86 = IDE_CPU_Is_Vm86();
02510 
02511                 if ((ata->bios_disk_index-2) == (disk-0x80)) {
02512                     imageDisk *dsk = ata->getBIOSdisk();
02513 
02514                     /* print warning if INT 13h is being called after the OS changed logical geometry */
02515                     if (ata->sects != ata->phys_sects || ata->heads != ata->phys_heads || ata->cyls != ata->phys_cyls)
02516                         LOG_MSG("INT 13 WARNING: I/O issued on drive attached to IDE emulation with changed logical geometry!\n");
02517 
02518                     /* HACK: src/ints/bios_disk.cpp implementation doesn't correctly
02519                      *       wrap sector numbers across tracks. it fullfills the read
02520                      *       by counting sectors and reading from C,H,S+i which means
02521                      *       that if the OS assumes the ability to read across track
02522                      *       boundaries (as Windows 95 does) we will get invalid
02523                      *       sector numbers, which in turn fouls up our emulation.
02524                      *
02525                      *       Windows 95 OSR2 for example, will happily ask for 63
02526                      *       sectors starting at C/H/S 30/9/42 without regard for
02527                      *       track boundaries. */
02528                     if (sect > dsk->sectors) {
02529 #if 0 /* this warning is pointless */
02530                         static bool int13_fix_wrap_warned = false;
02531                         if (!int13_fix_wrap_warned) {
02532                             LOG_MSG("INT 13h implementation warning: we were given over-large sector number.\n");
02533                             LOG_MSG("This is normally the fault of DOSBox INT 13h emulation that counts sectors\n");
02534                             LOG_MSG("without consideration of track boundaries\n");
02535                             int13_fix_wrap_warned = true;
02536                         }
02537 #endif
02538 
02539                         do {
02540                             sect -= dsk->sectors;
02541                             if ((++head) >= dsk->heads) {
02542                                 head -= dsk->heads;
02543                                 cyl++;
02544                             }
02545                         } while (sect > dsk->sectors);
02546                     }
02547 
02548                     /* translate BIOS INT 13h geometry to IDE geometry */
02549                     if (ata->headshr != 0 || ata->geo_translate) {
02550                         unsigned long lba;
02551 
02552                         if (dsk == NULL) return;
02553                         lba = (head * dsk->sectors) + (cyl * dsk->sectors * dsk->heads) + sect - 1;
02554                         sect = (lba % ata->sects) + 1;
02555                         head = (lba / ata->sects) % ata->heads;
02556                         cyl = (lba / ata->sects / ata->heads);
02557                     }
02558 
02559                     if (ide->int13fakev86io && vm86) {
02560                         dev->faked_command = true;
02561 
02562                         /* we MUST clear interrupts.
02563                          * leaving them enabled causes Win95 (or DOSBox?) to recursively
02564                          * pagefault and DOSBox to crash. In any case it seems Win95's
02565                          * IDE driver assumes the BIOS INT 13h code will do this since
02566                          * it's customary for the BIOS to do it at some point, usually
02567                          * just before reading the sector data. */
02568                         CPU_CLI();
02569 
02570                         /* We're in virtual 8086 mode and we're asked to fake I/O as if
02571                          * executing a BIOS subroutine. Some OS's like Windows 95 rely on
02572                          * executing INT 13h in virtual 8086 mode: on startup, the ESDI
02573                          * driver traps IDE ports and then executes INT 13h to watch what
02574                          * I/O ports it uses. It then uses that information to decide
02575                          * what IDE hard disk and controller corresponds to what DOS
02576                          * drive. So to get 32-bit disk access to work in Windows 95,
02577                          * we have to put on a good show to convince Windows 95 we're
02578                          * a legitimate BIOS INT 13h call doing it's job. */
02579                         IDE_SelfIO_In(ide,ide->base_io+7u,1);        /* dum de dum reading status */
02580                         IDE_SelfIO_Out(ide,ide->base_io+6u,(ms<<4u)+0xA0u+head,1); /* drive and head */
02581                         IDE_SelfIO_In(ide,ide->base_io+7u,1);        /* dum de dum reading status */
02582                         IDE_SelfIO_Out(ide,ide->base_io+2u,0x01,1);  /* sector count */
02583                         IDE_SelfIO_Out(ide,ide->base_io+3u,sect,1);  /* sector number */
02584                         IDE_SelfIO_Out(ide,ide->base_io+4u,cyl&0xFF,1);  /* cylinder lo */
02585                         IDE_SelfIO_Out(ide,ide->base_io+5u,(cyl>>8u)&0xFF,1); /* cylinder hi */
02586                         IDE_SelfIO_Out(ide,ide->base_io+6u,(ms<<4u)+0xA0u+head,1); /* drive and head */
02587                         IDE_SelfIO_In(ide,ide->base_io+7u,1);        /* dum de dum reading status */
02588                         IDE_SelfIO_Out(ide,ide->base_io+7u,0x20u,1);  /* issue READ */
02589 
02590                         do {
02591                             /* TODO: Timeout needed */
02592                             unsigned int i = IDE_SelfIO_In(ide,ide->alt_io,1);
02593                             if ((i&0x80) == 0) break;
02594                         } while (1);
02595                         IDE_SelfIO_In(ide,ide->base_io+7u,1);
02596 
02597                         /* for brevity assume it worked. we're here to bullshit Windows 95 after all */
02598                         for (unsigned int i=0;i < 256;i++)
02599                             IDE_SelfIO_In(ide,ide->base_io+0,2); /* 16-bit IDE data read */
02600 
02601                         /* one more */
02602                         IDE_SelfIO_In(ide,ide->base_io+7u,1);        /* dum de dum reading status */
02603 
02604                         /* assume IRQ happened and clear it */
02605                         if (ide->IRQ >= 8)
02606                             IDE_SelfIO_Out(ide,0xA0,0x60u+(unsigned int)ide->IRQ-8u,1);     /* specific EOI */
02607                         else
02608                             IDE_SelfIO_Out(ide,0x20,0x60u+(unsigned int)ide->IRQ,1);       /* specific EOI */
02609 
02610                         ata->abort_normal();
02611                         dev->faked_command = false;
02612                     }
02613                     else {
02614                         /* hack IDE state as if a BIOS executing IDE disk routines.
02615                          * This is required if we want IDE emulation to work with Windows 3.11 Windows for Workgroups 32-bit disk access (WDCTRL),
02616                          * because the driver "tests" the controller by issuing INT 13h calls then reading back IDE registers to see if
02617                          * they match the C/H/S it requested */
02618                         dev->feature = 0x00;        /* clear error (WDCTRL test phase 5/C/13) */
02619                         dev->count = 0x00;      /* clear sector count (WDCTRL test phase 6/D/14) */
02620                         dev->lba[0] = sect;     /* leave sector number the same (WDCTRL test phase 7/E/15) */
02621                         dev->lba[1] = cyl;      /* leave cylinder the same (WDCTRL test phase 8/F/16) */
02622                         dev->lba[2] = cyl >> 8u;     /* ...ditto */
02623                         ide->drivehead = dev->drivehead = 0xA0u | (ms<<4u) | head; /* drive head and master/slave (WDCTRL test phase 9/10/17) */
02624                         dev->status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE; /* status (WDCTRL test phase A/11/18) */
02625                         dev->allow_writing = true;
02626                         static bool vm86_warned = false;
02627 
02628                         if (vm86 && !vm86_warned) {
02629                             LOG_MSG("IDE warning: INT 13h read from virtual 8086 mode.\n");
02630                             LOG_MSG("             If using Windows 95, please set int13fakev86io=true for proper 32-bit disk access\n");
02631                             vm86_warned = true;
02632                         }
02633                     }
02634 
02635                     /* break out, we're done */
02636                     idx = MAX_IDE_CONTROLLERS;
02637                     break;
02638                 }
02639             }
02640         }
02641     }
02642 }
02643 
02644 /* this is called by src/ints/bios_disk.cpp whenever INT 13h AH=0x00 is called on a hard disk.
02645  * this gives us a chance to update IDE state as if the BIOS had gone through with a full disk reset as requested. */
02646 void IDE_ResetDiskByBIOS(unsigned char disk) {
02647     IDEController *ide;
02648     IDEDevice *dev;
02649     Bitu idx,ms;
02650 
02651     if (disk < 0x80) return;
02652 
02653     for (idx=0;idx < MAX_IDE_CONTROLLERS;idx++) {
02654         ide = GetIDEController(idx);
02655         if (ide == NULL) continue;
02656         if (!ide->int13fakeio && !ide->int13fakev86io) continue;
02657 
02658         /* TODO: Print a warning message if the IDE controller is busy (debug/warning message) */
02659 
02660         /* TODO: Force IDE state to readiness, abort command, etc. */
02661 
02662         /* for master/slave device... */
02663         for (ms=0;ms < 2;ms++) {
02664             dev = ide->device[ms];
02665             if (dev == NULL) continue;
02666 
02667             /* TODO: Print a warning message if the IDE device is busy or in the middle of a command */
02668 
02669             /* TODO: Forcibly device-reset the IDE device */
02670 
02671             /* Issue I/O to ourself to select drive */
02672             IDE_SelfIO_In(ide,ide->base_io+7u,1);
02673             IDE_SelfIO_Out(ide,ide->base_io+6u,0x00+(ms<<4u),1);
02674 
02675             /* TODO: Forcibly device-reset the IDE device */
02676 
02677             if (dev->type == IDE_TYPE_HDD) {
02678                 IDEATADevice *ata = (IDEATADevice*)dev;
02679 
02680                 if ((ata->bios_disk_index-2) == (disk-0x80)) {
02681                     LOG_MSG("IDE %d%c reset by BIOS disk 0x%02x\n",
02682                         (unsigned int)(idx+1),
02683                         ms?'s':'m',
02684                         (unsigned int)disk);
02685 
02686                     if (ide->int13fakev86io && IDE_CPU_Is_Vm86()) {
02687                         /* issue the DEVICE RESET command */
02688                         IDE_SelfIO_In(ide,ide->base_io+7u,1);
02689                         IDE_SelfIO_Out(ide,ide->base_io+7u,0x08,1);
02690 
02691                         IDE_SelfIO_In(ide,ide->base_io+7u,1);
02692 
02693                         /* assume IRQ happened and clear it */
02694                         if (ide->IRQ >= 8)
02695                             IDE_SelfIO_Out(ide,0xA0,0x60u+(unsigned int)ide->IRQ-8u,1);     /* specific EOI */
02696                         else
02697                             IDE_SelfIO_Out(ide,0x20,0x60u+(unsigned int)ide->IRQ,1);       /* specific EOI */
02698                     }
02699                     else {
02700                         /* Windows 3.1 WDCTRL needs this, or else, it will read the
02701                          * status register and see something other than DRIVE_READY|SEEK_COMPLETE */
02702                         dev->writecommand(0x08);
02703 
02704                         /* and then immediately clear the IRQ */
02705                         ide->lower_irq();
02706                     }
02707                 }
02708             }
02709         }
02710     }
02711 }
02712 
02713 static void IDE_DelayedCommand(Bitu idx/*which IDE controller*/) {
02714     IDEDevice *dev = GetIDESelectedDevice(GetIDEController(idx));
02715     if (dev == NULL) return;
02716 
02717     if (dev->type == IDE_TYPE_HDD) {
02718         IDEATADevice *ata = (IDEATADevice*)dev;
02719         uint32_t sectorn = 0;/* FIXME: expand to uint64_t when adding LBA48 emulation */
02720         unsigned int sectcount;
02721         imageDisk *disk;
02722 //      int i;
02723 
02724         switch (dev->command) {
02725             case 0x30:/* WRITE SECTOR */
02726                 disk = ata->getBIOSdisk();
02727                 if (disk == NULL) {
02728                     LOG_MSG("ATA READ fail, bios disk N/A\n");
02729                     ata->abort_error();
02730                     dev->controller->raise_irq();
02731                     return;
02732                 }
02733 
02734                 sectcount = ata->count & 0xFF;
02735                 if (sectcount == 0) sectcount = 256;
02736                 if (drivehead_is_lba(ata->drivehead)) {
02737                     /* LBA */
02738                     sectorn = ((ata->drivehead & 0xFu) << 24u) | (unsigned int)ata->lba[0] |
02739                         ((unsigned int)ata->lba[1] << 8u) |
02740                         ((unsigned int)ata->lba[2] << 16u);
02741                 }
02742                 else {
02743                     /* C/H/S */
02744                     if (ata->lba[0] == 0) {
02745                         LOG_MSG("ATA sector 0 does not exist\n");
02746                         ata->abort_error();
02747                         dev->controller->raise_irq();
02748                         return;
02749                     }
02750                     else if ((unsigned int)(ata->drivehead & 0xFu) >= (unsigned int)ata->heads ||
02751                         (unsigned int)ata->lba[0] > (unsigned int)ata->sects ||
02752                         (unsigned int)(ata->lba[1] | (ata->lba[2] << 8u)) >= (unsigned int)ata->cyls) {
02753                         LOG_MSG("C/H/S %u/%u/%u out of bounds %u/%u/%u\n",
02754                             (unsigned int)(ata->lba[1] | (ata->lba[2] << 8u)),
02755                             (unsigned int)(ata->drivehead&0xFu),
02756                             (unsigned int)(ata->lba[0]),
02757                             (unsigned int)ata->cyls,
02758                             (unsigned int)ata->heads,
02759                             (unsigned int)ata->sects);
02760                         ata->abort_error();
02761                         dev->controller->raise_irq();
02762                         return;
02763                     }
02764 
02765                     sectorn = ((ata->drivehead & 0xF) * ata->sects) +
02766                         (((unsigned int)ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)) * ata->sects * ata->heads) +
02767                         ((unsigned int)ata->lba[0] - 1u);
02768                 }
02769 
02770                 if (disk->Write_AbsoluteSector(sectorn, ata->sector) != 0) {
02771                     LOG_MSG("Failed to write sector\n");
02772                     ata->abort_error();
02773                     dev->controller->raise_irq();
02774                     return;
02775                 }
02776 
02777                 /* NTS: the way this command works is that the drive writes ONE sector, then fires the IRQ
02778                         and lets the host read it, then reads another sector, fires the IRQ, etc. One
02779                     IRQ signal per sector. We emulate that here by adding another event to trigger this
02780                     call unless the sector count has just dwindled to zero, then we let it stop. */
02781                 if ((ata->count&0xFF) == 1) {
02782                     /* end of the transfer */
02783                     ata->count = 0;
02784                     ata->status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
02785                     dev->controller->raise_irq();
02786                     ata->state = IDE_DEV_READY;
02787                     ata->allow_writing = true;
02788                     return;
02789                 }
02790                 else if ((ata->count&0xFF) == 0) ata->count = 255;
02791                 else ata->count--;
02792                 ata->progress_count++;
02793 
02794                 if (!ata->increment_current_address()) {
02795                     LOG_MSG("READ advance error\n");
02796                     ata->abort_error();
02797                     return;
02798                 }
02799 
02800                 /* begin another sector */
02801                 dev->state = IDE_DEV_DATA_WRITE;
02802                 dev->status = IDE_STATUS_DRQ|IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
02803                 ata->prepare_write(0,512);
02804                 dev->controller->raise_irq();
02805                 break;
02806 
02807             case 0x20:/* READ SECTOR */
02808                 disk = ata->getBIOSdisk();
02809                 if (disk == NULL) {
02810                     LOG_MSG("ATA READ fail, bios disk N/A\n");
02811                     ata->abort_error();
02812                     dev->controller->raise_irq();
02813                     return;
02814                 }
02815 
02816                 sectcount = ata->count & 0xFF;
02817                 if (sectcount == 0) sectcount = 256;
02818                 if (drivehead_is_lba(ata->drivehead)) {
02819                     /* LBA */
02820                     sectorn = (((unsigned int)ata->drivehead & 0xFu) << 24u) | (unsigned int)ata->lba[0] |
02821                         ((unsigned int)ata->lba[1] << 8u) |
02822                         ((unsigned int)ata->lba[2] << 16u);
02823                 }
02824                 else {
02825                     /* C/H/S */
02826                     if (ata->lba[0] == 0) {
02827                         LOG_MSG("WARNING C/H/S access mode and sector==0\n");
02828                         ata->abort_error();
02829                         dev->controller->raise_irq();
02830                         return;
02831                     }
02832                     else if ((unsigned int)(ata->drivehead & 0xF) >= (unsigned int)ata->heads ||
02833                         (unsigned int)ata->lba[0] > (unsigned int)ata->sects ||
02834                         (unsigned int)(ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)) >= (unsigned int)ata->cyls) {
02835                         LOG_MSG("C/H/S %u/%u/%u out of bounds %u/%u/%u\n",
02836                             (unsigned int)(ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)),
02837                             (unsigned int)(ata->drivehead&0xF),
02838                             (unsigned int)ata->lba[0],
02839                             (unsigned int)ata->cyls,
02840                             (unsigned int)ata->heads,
02841                             (unsigned int)ata->sects);
02842                         ata->abort_error();
02843                         dev->controller->raise_irq();
02844                         return;
02845                     }
02846 
02847                     sectorn = ((ata->drivehead & 0xFu) * ata->sects) +
02848                         (((unsigned int)ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)) * ata->sects * ata->heads) +
02849                         ((unsigned int)ata->lba[0] - 1u);
02850                 }
02851 
02852                 if (disk->Read_AbsoluteSector(sectorn, ata->sector) != 0) {
02853                     LOG_MSG("ATA read failed\n");
02854                     ata->abort_error();
02855                     dev->controller->raise_irq();
02856                     return;
02857                 }
02858 
02859                 /* NTS: the way this command works is that the drive reads ONE sector, then fires the IRQ
02860                         and lets the host read it, then reads another sector, fires the IRQ, etc. One
02861                     IRQ signal per sector. We emulate that here by adding another event to trigger this
02862                     call unless the sector count has just dwindled to zero, then we let it stop. */
02863                 /* NTS: The sector advance + count decrement is done in the I/O completion function */
02864                 dev->state = IDE_DEV_DATA_READ;
02865                 dev->status = IDE_STATUS_DRQ|IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
02866                 ata->prepare_read(0,512);
02867                 dev->controller->raise_irq();
02868                 break;
02869 
02870             case 0x40:/* READ SECTOR VERIFY WITH RETRY */
02871             case 0x41: /* READ SECTOR VERIFY WITHOUT RETRY */
02872                 disk = ata->getBIOSdisk();
02873                 if (disk == NULL) {
02874                     LOG_MSG("ATA READ fail, bios disk N/A\n");
02875                     ata->abort_error();
02876                     dev->controller->raise_irq();
02877                     return;
02878                 }
02879 
02880                 sectcount = ata->count & 0xFF;
02881                 if (sectcount == 0) sectcount = 256;
02882                 if (drivehead_is_lba(ata->drivehead)) {
02883                     /* LBA */
02884                     sectorn = (((unsigned int)ata->drivehead & 0xFu) << 24u) | (unsigned int)ata->lba[0] |
02885                         ((unsigned int)ata->lba[1] << 8u) |
02886                         ((unsigned int)ata->lba[2] << 16u);
02887                 }
02888                 else {
02889                     /* C/H/S */
02890                     if (ata->lba[0] == 0) {
02891                         LOG_MSG("WARNING C/H/S access mode and sector==0\n");
02892                         ata->abort_error();
02893                         dev->controller->raise_irq();
02894                         return;
02895                     }
02896                     else if ((unsigned int)(ata->drivehead & 0xF) >= (unsigned int)ata->heads ||
02897                         (unsigned int)ata->lba[0] > (unsigned int)ata->sects ||
02898                         (unsigned int)(ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)) >= (unsigned int)ata->cyls) {
02899                         LOG_MSG("C/H/S %u/%u/%u out of bounds %u/%u/%u\n",
02900                             (unsigned int)(ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)),
02901                             (unsigned int)(ata->drivehead&0xFu),
02902                             (unsigned int)ata->lba[0],
02903                             (unsigned int)ata->cyls,
02904                             (unsigned int)ata->heads,
02905                             (unsigned int)ata->sects);
02906                         ata->abort_error();
02907                         dev->controller->raise_irq();
02908                         return;
02909                     }
02910 
02911                     sectorn = (((unsigned int)ata->drivehead & 0xFu) * ata->sects) +
02912                         (((unsigned int)ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)) * ata->sects * ata->heads) +
02913                         ((unsigned int)ata->lba[0] - 1u);
02914                 }
02915 
02916                 if (disk->Read_AbsoluteSector(sectorn, ata->sector) != 0) {
02917                     LOG_MSG("ATA read failed\n");
02918                     ata->abort_error();
02919                     dev->controller->raise_irq();
02920                     return;
02921                 }
02922 
02923                 if ((ata->count&0xFF) == 1) {
02924                     /* end of the transfer */
02925                     ata->count = 0;
02926                     ata->status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
02927                     dev->controller->raise_irq();
02928                     ata->state = IDE_DEV_READY;
02929                     ata->allow_writing = true;
02930                     return;
02931                 }
02932                 else if ((ata->count&0xFF) == 0) ata->count = 255;
02933                 else ata->count--;
02934                 ata->progress_count++;
02935 
02936                 if (!ata->increment_current_address()) {
02937                     LOG_MSG("READ advance error\n");
02938                     ata->abort_error();
02939                     return;
02940                 }
02941 
02942                 ata->state = IDE_DEV_BUSY;
02943                 ata->status = IDE_STATUS_BUSY;
02944                 PIC_AddEvent(IDE_DelayedCommand,0.00001/*ms*/,dev->controller->interface_index);
02945                 break;
02946 
02947             case 0xC4:/* READ MULTIPLE */
02948                 disk = ata->getBIOSdisk();
02949                 if (disk == NULL) {
02950                     LOG_MSG("ATA READ fail, bios disk N/A\n");
02951                     ata->abort_error();
02952                     dev->controller->raise_irq();
02953                     return;
02954                 }
02955 
02956                 sectcount = ata->count & 0xFF;
02957                 if (sectcount == 0) sectcount = 256;
02958                 if (drivehead_is_lba(ata->drivehead)) {
02959                     /* LBA */
02960                     sectorn = (((unsigned int)ata->drivehead & 0xFu) << 24u) | (unsigned int)ata->lba[0] |
02961                         ((unsigned int)ata->lba[1] << 8u) |
02962                         ((unsigned int)ata->lba[2] << 16u);
02963                 }
02964                 else {
02965                     /* C/H/S */
02966                     if (ata->lba[0] == 0) {
02967                         LOG_MSG("WARNING C/H/S access mode and sector==0\n");
02968                         ata->abort_error();
02969                         dev->controller->raise_irq();
02970                         return;
02971                     }
02972                     else if ((unsigned int)(ata->drivehead & 0xF) >= (unsigned int)ata->heads ||
02973                         (unsigned int)ata->lba[0] > (unsigned int)ata->sects ||
02974                         (unsigned int)(ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)) >= (unsigned int)ata->cyls) {
02975                         LOG_MSG("C/H/S %u/%u/%u out of bounds %u/%u/%u\n",
02976                             (unsigned int)(ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)),
02977                             (unsigned int)(ata->drivehead&0xF),
02978                             (unsigned int)ata->lba[0],
02979                             (unsigned int)ata->cyls,
02980                             (unsigned int)ata->heads,
02981                             (unsigned int)ata->sects);
02982                         ata->abort_error();
02983                         dev->controller->raise_irq();
02984                         return;
02985                     }
02986 
02987                     sectorn = ((ata->drivehead & 0xF) * ata->sects) +
02988                         (((unsigned int)ata->lba[1] | ((unsigned int)ata->lba[2] << 8u)) * ata->sects * ata->heads) +
02989                         ((unsigned int)ata->lba[0] - 1);
02990                 }
02991 
02992                 if ((512*ata->multiple_sector_count) > sizeof(ata->sector))
02993                     E_Exit("SECTOR OVERFLOW");
02994 
02995                 for (unsigned int cc=0;cc < MIN((Bitu)ata->multiple_sector_count,(Bitu)sectcount);cc++) {
02996                     /* it would be great if the disk object had a "read multiple sectors" member function */
02997                     if (disk->Read_AbsoluteSector(sectorn+cc, ata->sector+(cc*512)) != 0) {
02998                         LOG_MSG("ATA read failed\n");
02999                         ata->abort_error();
03000                         dev->controller->raise_irq();
03001                         return;
03002                     }
03003                 }
03004 
03005                 /* NTS: the way this command works is that the drive reads ONE sector, then fires the IRQ
03006                         and lets the host read it, then reads another sector, fires the IRQ, etc. One
03007                     IRQ signal per sector. We emulate that here by adding another event to trigger this
03008                     call unless the sector count has just dwindled to zero, then we let it stop. */
03009                 /* NTS: The sector advance + count decrement is done in the I/O completion function */
03010                 dev->state = IDE_DEV_DATA_READ;
03011                 dev->status = IDE_STATUS_DRQ|IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
03012                 ata->prepare_read(0,512*MIN((Bitu)ata->multiple_sector_count,(Bitu)sectcount));
03013                 dev->controller->raise_irq();
03014                 break;
03015 
03016             case 0xC5:/* WRITE MULTIPLE */
03017                 disk = ata->getBIOSdisk();
03018                 if (disk == NULL) {
03019                     LOG_MSG("ATA READ fail, bios disk N/A\n");
03020                     ata->abort_error();
03021                     dev->controller->raise_irq();
03022                     return;
03023                 }
03024 
03025                 sectcount = ata->count & 0xFF;
03026                 if (sectcount == 0) sectcount = 256;
03027                 if (drivehead_is_lba(ata->drivehead)) {
03028                     /* LBA */
03029                     sectorn = (((unsigned int)ata->drivehead & 0xF) << 24) | (unsigned int)ata->lba[0] |
03030                         ((unsigned int)ata->lba[1] << 8) |
03031                         ((unsigned int)ata->lba[2] << 16);
03032                 }
03033                 else {
03034                     /* C/H/S */
03035                     if (ata->lba[0] == 0) {
03036                         LOG_MSG("ATA sector 0 does not exist\n");
03037                         ata->abort_error();
03038                         dev->controller->raise_irq();
03039                         return;
03040                     }
03041                     else if ((unsigned int)(ata->drivehead & 0xF) >= (unsigned int)ata->heads ||
03042                         (unsigned int)ata->lba[0] > (unsigned int)ata->sects ||
03043                         (unsigned int)(ata->lba[1] | ((unsigned int)ata->lba[2] << 8)) >= (unsigned int)ata->cyls) {
03044                         LOG_MSG("C/H/S %u/%u/%u out of bounds %u/%u/%u\n",
03045                             (unsigned int)(ata->lba[1] | ((unsigned int)ata->lba[2] << 8)),
03046                             (unsigned int)(ata->drivehead&0xF),
03047                             (unsigned int)ata->lba[0],
03048                             (unsigned int)ata->cyls,
03049                             (unsigned int)ata->heads,
03050                             (unsigned int)ata->sects);
03051                         ata->abort_error();
03052                         dev->controller->raise_irq();
03053                         return;
03054                     }
03055 
03056                     sectorn = ((unsigned int)(ata->drivehead & 0xF) * ata->sects) +
03057                         (((unsigned int)ata->lba[1] | ((unsigned int)ata->lba[2] << 8)) * ata->sects * ata->heads) +
03058                         ((unsigned int)ata->lba[0] - 1);
03059                 }
03060 
03061                 for (unsigned int cc=0;cc < MIN((Bitu)ata->multiple_sector_count,(Bitu)sectcount);cc++) {
03062                     /* it would be great if the disk object had a "write multiple sectors" member function */
03063                     if (disk->Write_AbsoluteSector(sectorn+cc, ata->sector+(cc*512)) != 0) {
03064                         LOG_MSG("Failed to write sector\n");
03065                         ata->abort_error();
03066                         dev->controller->raise_irq();
03067                         return;
03068                     }
03069                 }
03070 
03071                 for (unsigned int cc=0;cc < MIN((Bitu)ata->multiple_sector_count,(Bitu)sectcount);cc++) {
03072                     if ((ata->count&0xFF) == 1) {
03073                         /* end of the transfer */
03074                         ata->count = 0;
03075                         ata->status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
03076                         dev->controller->raise_irq();
03077                         ata->state = IDE_DEV_READY;
03078                         ata->allow_writing = true;
03079                         return;
03080                     }
03081                     else if ((ata->count&0xFF) == 0) ata->count = 255;
03082                     else ata->count--;
03083                     ata->progress_count++;
03084 
03085                     if (!ata->increment_current_address()) {
03086                         LOG_MSG("READ advance error\n");
03087                         ata->abort_error();
03088                         return;
03089                     }
03090                 }
03091 
03092                 /* begin another sector */
03093                 sectcount = ata->count & 0xFF;
03094                 if (sectcount == 0) sectcount = 256;
03095                 dev->state = IDE_DEV_DATA_WRITE;
03096                 dev->status = IDE_STATUS_DRQ|IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
03097                 ata->prepare_write(0,512*MIN((Bitu)ata->multiple_sector_count,(Bitu)sectcount));
03098                 dev->controller->raise_irq();
03099                 break;
03100 
03101             case 0xEC:/*IDENTIFY DEVICE (CONTINUED) */
03102                 dev->state = IDE_DEV_DATA_READ;
03103                 dev->status = IDE_STATUS_DRQ|IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
03104                 ata->generate_identify_device();
03105                 ata->prepare_read(0,512);
03106                 dev->count = 0x01;
03107                 dev->lba[0] = 0x00;
03108                 dev->feature = 0x00;
03109                 dev->lba[1] = 0x00;
03110                 dev->lba[2] = 0x00;
03111                 dev->controller->raise_irq();
03112                 break;
03113             default:
03114                 LOG_MSG("Unknown delayed IDE/ATA command\n");
03115                 dev->abort_error();
03116                 dev->controller->raise_irq();
03117                 break;
03118         }
03119     }
03120     else if (dev->type == IDE_TYPE_CDROM) {
03121         IDEATAPICDROMDevice *atapi = (IDEATAPICDROMDevice*)dev;
03122 
03123         if (dev->state == IDE_DEV_ATAPI_BUSY) {
03124             switch (dev->command) {
03125                 case 0xA0:/*ATAPI PACKET*/
03126                     atapi->on_atapi_busy_time();
03127                     break;
03128                 default:
03129                     LOG_MSG("Unknown delayed IDE/ATAPI busy wait command\n");
03130                     dev->abort_error();
03131                     dev->controller->raise_irq();
03132                     break;
03133             }
03134         }
03135         else {
03136             switch (dev->command) {
03137                 case 0xA0:/*ATAPI PACKET*/
03138                     dev->state = IDE_DEV_ATAPI_PACKET_COMMAND;
03139                     dev->status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE|IDE_STATUS_DRQ;
03140                     dev->count = 0x01;  /* input/output == 0, command/data == 1 */
03141                     atapi->atapi_cmd_total = 12; /* NTS: do NOT raise IRQ */
03142                     atapi->atapi_cmd_i = 0;
03143                     break;
03144                 case 0xA1:/*IDENTIFY PACKET DEVICE (CONTINUED) */
03145                     dev->state = IDE_DEV_DATA_READ;
03146                     dev->status = IDE_STATUS_DRQ|IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
03147                     atapi->generate_identify_device();
03148                     atapi->prepare_read(0,512);
03149                     dev->controller->raise_irq();
03150                     break;
03151                 default:
03152                     LOG_MSG("Unknown delayed IDE/ATAPI command\n");
03153                     dev->abort_error();
03154                     dev->controller->raise_irq();
03155                     break;
03156             }
03157         }
03158     }
03159     else {
03160         LOG_MSG("Unknown delayed command\n");
03161         dev->abort_error();
03162         dev->controller->raise_irq();
03163     }
03164 }
03165 
03166 void PC98_IDE_UpdateIRQ(void);
03167 
03168 void IDEController::raise_irq() {
03169     irq_pending = true;
03170     if (IS_PC98_ARCH) {
03171         PC98_IDE_UpdateIRQ();
03172     }
03173     else {
03174         if (IRQ >= 0 && interrupt_enable) PIC_ActivateIRQ((unsigned int)IRQ);
03175     }
03176 }
03177 
03178 void IDEController::lower_irq() {
03179     irq_pending = false;
03180     if (IS_PC98_ARCH) {
03181         PC98_IDE_UpdateIRQ();
03182     }
03183     else {
03184         if (IRQ >= 0) PIC_DeActivateIRQ((unsigned int)IRQ);
03185     }
03186 }
03187 
03188 unsigned int pc98_ide_select = 0;
03189 
03190 IDEController *match_ide_controller(Bitu port) {
03191     if (IS_PC98_ARCH) {
03192         return idecontroller[pc98_ide_select];
03193     }
03194     else {
03195         for (unsigned int i=0;i < MAX_IDE_CONTROLLERS;i++) {
03196             IDEController *ide = idecontroller[i];
03197             if (ide == NULL) continue;
03198             if (ide->base_io != 0U && ide->base_io == (port&0xFFF8U)) return ide;
03199             if (ide->alt_io != 0U && ide->alt_io == (port&0xFFFEU)) return ide;
03200         }
03201     }
03202 
03203     return NULL;
03204 }
03205 
03206 Bitu IDEDevice::data_read(Bitu iolen) {
03207     (void)iolen;//UNUSED
03208     return 0xAAAAU;
03209 }
03210 
03211 void IDEDevice::data_write(Bitu v,Bitu iolen) {
03212     (void)iolen;//UNUSED
03213     (void)v;//UNUSED
03214 }
03215 
03216 IDEDevice::IDEDevice(IDEController *c) {
03217     type = IDE_TYPE_NONE;
03218     status = 0x00;
03219     controller = c;
03220     asleep = false;
03221     motor_on = true;
03222     allow_writing = true;
03223     state = IDE_DEV_READY;
03224     feature = count = lba[0] = lba[1] = lba[2] = command = drivehead = 0;
03225 
03226     faked_command = false;
03227     ide_select_delay = 0.5; /* 500us */
03228     ide_spinup_delay = 3000; /* 3 seconds */
03229     ide_spindown_delay = 1000; /* 1 second */
03230     ide_identify_command_delay = 0.01; /* 10us */
03231 }
03232 
03233 /* IDE controller -> upon writing bit 2 of alt (0x3F6) */
03234 void IDEDevice::host_reset_complete() {
03235     status = 0x00;
03236     asleep = false;
03237     allow_writing = true;
03238     state = IDE_DEV_READY;
03239 }
03240 
03241 void IDEDevice::host_reset_begin() {
03242     status = 0xFF;
03243     asleep = false;
03244     allow_writing = true;
03245     state = IDE_DEV_BUSY;
03246 }
03247 
03248 IDEDevice::~IDEDevice() {
03249 }
03250 
03251 void IDEDevice::abort_silent() {
03252     assert(controller != NULL);
03253 
03254     /* a command was written while another is in progress */
03255     state = IDE_DEV_READY;
03256     allow_writing = true;
03257     command = 0x00;
03258     status = IDE_STATUS_ERROR | IDE_STATUS_DRIVE_READY | IDE_STATUS_DRIVE_SEEK_COMPLETE;
03259 }
03260 
03261 void IDEDevice::abort_error() {
03262     assert(controller != NULL);
03263     LOG_MSG("IDE abort dh=0x%02x with error on 0x%03x\n",drivehead,controller->base_io);
03264 
03265     /* a command was written while another is in progress */
03266     state = IDE_DEV_READY;
03267     allow_writing = true;
03268     command = 0x00;
03269     status = IDE_STATUS_ERROR | IDE_STATUS_DRIVE_READY | IDE_STATUS_DRIVE_SEEK_COMPLETE;
03270 }
03271 
03272 void IDEDevice::abort_normal() {
03273     /* a command was written while another is in progress */
03274     state = IDE_DEV_READY;
03275     allow_writing = true;
03276     command = 0x00;
03277     status = IDE_STATUS_DRIVE_READY | IDE_STATUS_DRIVE_SEEK_COMPLETE;
03278 }
03279 
03280 void IDEDevice::interface_wakeup() {
03281     if (asleep) {
03282         asleep = false;
03283     }
03284 }
03285 
03286 bool IDEDevice::command_interruption_ok(uint8_t cmd) {
03287     /* apparently this is OK, if the Linux kernel is doing it:
03288      * writing the same command byte as the one in progress, OR, issuing
03289      * Device Reset while another command is waiting for data read/write */
03290     if (cmd == command) return true;
03291     if (state != IDE_DEV_READY && state != IDE_DEV_BUSY && cmd == 0x08) {
03292         LOG_MSG("Device reset while another (%02x) is in progress (state=%u). Aborting current command to begin another\n",command,state);
03293         abort_silent();
03294         return true;
03295     }
03296 
03297     if (state != IDE_DEV_READY) {
03298         LOG_MSG("Command %02x written while another (%02x) is in progress (state=%u). Aborting current command\n",cmd,command,state);
03299         abort_error();
03300         return false;
03301     }
03302 
03303     return true;
03304 }
03305 
03306 void IDEDevice::writecommand(uint8_t cmd) {
03307     if (!command_interruption_ok(cmd))
03308         return;
03309 
03310     /* if the drive is asleep, then writing a command wakes it up */
03311     interface_wakeup();
03312 
03313     /* drive is ready to accept command */
03314     switch (cmd) {
03315         default:
03316             LOG_MSG("Unknown IDE command %02X\n",cmd);
03317             abort_error();
03318             break;
03319     }
03320 }
03321 
03322 void IDEATAPICDROMDevice::writecommand(uint8_t cmd) {
03323     if (!command_interruption_ok(cmd))
03324         return;
03325 
03326     /* if the drive is asleep, then writing a command wakes it up */
03327     interface_wakeup();
03328 
03329     /* drive is ready to accept command */
03330     allow_writing = false;
03331     command = cmd;
03332     switch (cmd) {
03333         case 0x08: /* DEVICE RESET */
03334             status = 0x00;
03335             drivehead &= 0x10; controller->drivehead = drivehead;
03336             count = 0x01;
03337             lba[0] = 0x01;
03338             feature = 0x01;
03339             lba[1] = 0x14;  /* <- magic ATAPI identification */
03340             lba[2] = 0xEB;
03341             /* NTS: Testing suggests that ATAPI devices do NOT trigger an IRQ on receipt of this command */
03342             allow_writing = true;
03343             break;
03344         case 0x20: /* READ SECTOR */
03345             abort_normal();
03346             status = IDE_STATUS_ERROR|IDE_STATUS_DRIVE_READY;
03347             drivehead &= 0x30; controller->drivehead = drivehead;
03348             count = 0x01;
03349             lba[0] = 0x01;
03350             feature = 0x04; /* abort */
03351             lba[1] = 0x14;  /* <- magic ATAPI identification */
03352             lba[2] = 0xEB;
03353             controller->raise_irq();
03354             allow_writing = true;
03355             break;
03356         case 0xA0: /* ATAPI PACKET */
03357             if (feature & 1) {
03358                 /* this code does not support DMA packet commands */
03359                 LOG_MSG("Attempted DMA transfer\n");
03360                 abort_error();
03361                 count = 0x03; /* no more data (command/data=1, input/output=1) */
03362                 feature = 0xF4;
03363                 controller->raise_irq();
03364             }
03365             else {
03366                 state = IDE_DEV_BUSY;
03367                 status = IDE_STATUS_BUSY;
03368                 atapi_to_host = (feature >> 2) & 1; /* 0=to device 1=to host */
03369                 host_maximum_byte_count = ((unsigned int)lba[2] << 8) + (unsigned int)lba[1]; /* LBA field bits 23:8 are byte count */
03370                 if (host_maximum_byte_count == 0) host_maximum_byte_count = 0x10000UL;
03371                 PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 0.25)/*ms*/,controller->interface_index);
03372             }
03373             break;
03374         case 0xA1: /* IDENTIFY PACKET DEVICE */
03375             state = IDE_DEV_BUSY;
03376             status = IDE_STATUS_BUSY;
03377             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : ide_identify_command_delay),controller->interface_index);
03378             break;
03379         case 0xEC: /* IDENTIFY DEVICE */
03380             /* "devices that implement the PACKET command set shall post command aborted and place PACKET command feature
03381                set in the appropriate fields". We have to do this. Unlike OAKCDROM.SYS Windows 95 appears to autodetect
03382                IDE devices by what they do when they're sent command 0xEC out of the blue---Microsoft didn't write their
03383                IDE drivers to use command 0x08 DEVICE RESET. */
03384             abort_normal();
03385             status = IDE_STATUS_ERROR|IDE_STATUS_DRIVE_READY;
03386             drivehead &= 0x30; controller->drivehead = drivehead;
03387             count = 0x01;
03388             lba[0] = 0x01;
03389             feature = 0x04; /* abort */
03390             lba[1] = 0x14;  /* <- magic ATAPI identification */
03391             lba[2] = 0xEB;
03392             controller->raise_irq();
03393             allow_writing = true;
03394             break;
03395         default:
03396             LOG_MSG("Unknown IDE/ATAPI command %02X\n",cmd);
03397             abort_error();
03398             allow_writing = true;
03399             count = 0x03; /* no more data (command/data=1, input/output=1) */
03400             feature = 0xF4;
03401             controller->raise_irq();
03402             break;
03403     }
03404 }
03405 
03406 void IDEATADevice::writecommand(uint8_t cmd) {
03407     if (!command_interruption_ok(cmd))
03408         return;
03409 
03410     if (!faked_command) {
03411         if (drivehead_is_lba(drivehead)) {
03412             uint64_t n;
03413 
03414             n = ((unsigned int)(drivehead&0xF)<<24)+((unsigned int)lba[2]<<16)+((unsigned int)lba[1]<<8)+(unsigned int)lba[0];
03415             LOG(LOG_SB,LOG_DEBUG)("IDE ATA command %02x dh=0x%02x count=0x%02x lba=%07llx/%07llx\n",cmd,
03416                 drivehead,count,(unsigned long long)n,
03417                 (unsigned long long)(phys_sects * phys_cyls * phys_heads));
03418         }
03419         else {
03420             LOG(LOG_SB,LOG_DEBUG)("IDE ATA command %02x dh=0x%02x count=0x%02x chs=%02x/%02x/%02x\n",cmd,
03421                 drivehead,count,((unsigned int)lba[2]<<8)+(unsigned int)lba[1],(unsigned int)(drivehead&0xF),(unsigned int)lba[0]);
03422         }
03423 
03424         LOG(LOG_SB,LOG_NORMAL)("IDE ATA command %02x",cmd);
03425     }
03426 
03427     /* if the drive is asleep, then writing a command wakes it up */
03428     interface_wakeup();
03429 
03430     /* FIXME: OAKCDROM.SYS is sending the hard disk command 0xA0 (ATAPI packet) for some reason. Why? */
03431 
03432     /* drive is ready to accept command */
03433     allow_writing = false;
03434     command = cmd;
03435     switch (cmd) {
03436         case 0x00: /* NOP */
03437             feature = 0x04;
03438             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_ERROR;
03439             controller->raise_irq();
03440             allow_writing = true;
03441             break;
03442         case 0x08: /* DEVICE RESET */
03443             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
03444             drivehead &= 0x10; controller->drivehead = drivehead;
03445             count = 0x01; lba[0] = 0x01; feature = 0x00;
03446             lba[1] = lba[2] = 0;
03447             /* NTS: Testing suggests that ATA hard drives DO fire an IRQ at this stage.
03448                     In fact, Windows 95 won't detect hard drives that don't fire an IRQ in desponse */
03449             controller->raise_irq();
03450             allow_writing = true;
03451             break;
03452         case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: /* RECALIBRATE (1xh) */
03453         case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F:
03454             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
03455             /* "if the command is executed in CHS mode, then ... sector number register shall be 1.
03456              *  if executed in LAB mode, then ... sector number register shall be 0" */
03457             if (drivehead_is_lba(drivehead)) lba[0] = 0x00;
03458             else lba[0] = 0x01;
03459             drivehead &= 0x10; controller->drivehead = drivehead;
03460             lba[1] = lba[2] = 0;
03461             feature = 0x00;
03462             controller->raise_irq();
03463             allow_writing = true;
03464             break;
03465         case 0x20: /* READ SECTOR */
03466             progress_count = 0;
03467             state = IDE_DEV_BUSY;
03468             status = IDE_STATUS_BUSY;
03469             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 0.1)/*ms*/,controller->interface_index);
03470             break;
03471         case 0x30: /* WRITE SECTOR */
03472             /* the drive does NOT signal an interrupt. it sets DRQ and waits for a sector
03473              * to be transferred to it before executing the command */
03474             progress_count = 0;
03475             state = IDE_DEV_DATA_WRITE;
03476             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ;
03477             prepare_write(0,512);
03478             break;
03479         case 0x40: /* READ SECTOR VERIFY WITH RETRY */
03480         case 0x41: /* READ SECTOR VERIFY WITHOUT RETRY */
03481             progress_count = 0;
03482             state = IDE_DEV_BUSY;
03483             status = IDE_STATUS_BUSY;
03484             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 0.1)/*ms*/,controller->interface_index);
03485             break;
03486         case 0x91: /* INITIALIZE DEVICE PARAMETERS */
03487             if ((unsigned int)count != (unsigned int)sects || (unsigned int)((drivehead&0xF)+1) != (unsigned int)heads) {
03488                 if (count == 0) {
03489                     LOG_MSG("IDE warning: OS attempted to change geometry to invalid H/S %u/%u\n",
03490                         count,(drivehead&0xF)+1);
03491                     abort_error();
03492                     allow_writing = true;
03493                     return;
03494                 }
03495                 else {
03496                     unsigned int ncyls;
03497 
03498                     ncyls = (phys_cyls * phys_heads * phys_sects);
03499                     ncyls += (count * ((unsigned int)(drivehead&0xF)+1u)) - 1u;
03500                     ncyls /= count * ((unsigned int)(drivehead&0xF)+1u);
03501 
03502                     /* the OS is changing logical disk geometry, so update our head/sector count (needed for Windows ME) */
03503                     LOG_MSG("IDE warning: OS is changing logical geometry from C/H/S %u/%u/%u to logical H/S %u/%u/%u\n",
03504                         (int)cyls,(int)heads,(int)sects,
03505                         (int)ncyls,(int)((drivehead&0xF)+1),(int)count);
03506                     LOG_MSG("             Compatibility issues may occur if the OS tries to use INT 13 at the same time!\n");
03507 
03508                     cyls = ncyls;
03509                     sects = count;
03510                     heads = (drivehead&0xFu)+1u;
03511                 }
03512             }
03513 
03514             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
03515             allow_writing = true;
03516             break;
03517         case 0xC4: /* READ MULTIPLE */
03518             progress_count = 0;
03519             state = IDE_DEV_BUSY;
03520             status = IDE_STATUS_BUSY;
03521             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : 0.1)/*ms*/,controller->interface_index);
03522             break;
03523         case 0xC5: /* WRITE MULTIPLE */
03524             /* the drive does NOT signal an interrupt. it sets DRQ and waits for a sector
03525              * to be transferred to it before executing the command */
03526             progress_count = 0;
03527             state = IDE_DEV_DATA_WRITE;
03528             status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRQ;
03529             prepare_write(0UL,512UL*MIN((unsigned long)multiple_sector_count,(unsigned long)(count == 0 ? 256 : count)));
03530             break;
03531         case 0xC6: /* SET MULTIPLE MODE */
03532             /* only sector counts 1, 2, 4, 8, 16, 32, 64, and 128 are legal by standard.
03533              * NTS: There's a bug in VirtualBox that makes 0 legal too! */
03534             if (count != 0 && count <= multiple_sector_max && is_power_of_2(count)) {
03535                 multiple_sector_count = count;
03536                 status = IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE;
03537             }
03538             else {
03539                 feature = 0x04; /* abort error */
03540                 abort_error();
03541             }
03542             controller->raise_irq();
03543             allow_writing = true;
03544             break;
03545         case 0xA0:/*ATAPI PACKET*/
03546             /* We're not an ATAPI packet device!
03547              * Windows 95 seems to issue this at startup to hard drives. Duh. */
03548             /* fall through */
03549         case 0xA1: /* IDENTIFY PACKET DEVICE */
03550             /* We are not an ATAPI packet device.
03551              * Most MS-DOS drivers and Windows 95 like to issue both IDENTIFY ATA and IDENTIFY ATAPI commands.
03552              * I also gather from some contributers on the github comments that people think our "Unknown IDE/ATA command"
03553              * error message is part of some other error in the emulation. Rather than put up with that, we'll just
03554              * silently abort the command with an error. */
03555             abort_normal();
03556             status = IDE_STATUS_ERROR|IDE_STATUS_DRIVE_READY;
03557             drivehead &= 0x30; controller->drivehead = drivehead;
03558             count = 0x01;
03559             lba[0] = 0x01;
03560             feature = 0x04; /* abort */
03561             lba[1] = 0x00;
03562             lba[2] = 0x00;
03563             controller->raise_irq();
03564             allow_writing = true;
03565             break;
03566         case 0xEC: /* IDENTIFY DEVICE */
03567             state = IDE_DEV_BUSY;
03568             status = IDE_STATUS_BUSY;
03569             PIC_AddEvent(IDE_DelayedCommand,(faked_command ? 0.000001 : ide_identify_command_delay),controller->interface_index);
03570             break;
03571         default:
03572             LOG_MSG("Unknown IDE/ATA command %02X\n",cmd);
03573             abort_error();
03574             allow_writing = true;
03575             controller->raise_irq();
03576             break;
03577     }
03578 }
03579 
03580 void IDEDevice::deselect() {
03581 }
03582 
03583 /* the hard disk or CD-ROM class override of this member is responsible for checking
03584    the head value and clamping within range if C/H/S mode is selected */
03585 void IDEDevice::select(uint8_t ndh,bool switched_to) {
03586     (void)switched_to;//UNUSED
03587     (void)ndh;//UNUSED
03588     /* NTS: I thought there was some delay between selecting a drive and sending a command.
03589         Apparently I was wrong. */
03590     if (allow_writing) drivehead = ndh;
03591 //  status = (!asleep)?(IDE_STATUS_DRIVE_READY|IDE_STATUS_DRIVE_SEEK_COMPLETE):0;
03592 //  allow_writing = !asleep;
03593 //  state = IDE_DEV_READY;
03594 }
03595 
03596 IDEController::IDEController(Section* configuration,unsigned char index):Module_base(configuration){
03597     Section_prop * section=static_cast<Section_prop *>(configuration);
03598     int i;
03599 
03600     register_pnp = section->Get_bool("pnp");
03601     int13fakeio = section->Get_bool("int13fakeio");
03602     int13fakev86io = section->Get_bool("int13fakev86io");
03603     enable_pio32 = section->Get_bool("enable pio32");
03604     ignore_pio32 = section->Get_bool("ignore pio32");
03605     spinup_time = section->Get_int("cd-rom spinup time");
03606     spindown_timeout = section->Get_int("cd-rom spindown timeout");
03607     cd_insertion_time = section->Get_int("cd-rom insertion delay");
03608 
03609     status = 0x00;
03610     host_reset = false;
03611     irq_pending = false;
03612     interrupt_enable = true;
03613     interface_index = index;
03614     device[0] = NULL;
03615     device[1] = NULL;
03616     base_io = 0;
03617     select = 0;
03618     alt_io = 0;
03619     IRQ = -1;
03620     drivehead = 0;
03621 
03622     i = section->Get_int("irq");
03623     if (i > 0 && i <= 15) IRQ = i;
03624 
03625     i = section->Get_hex("io");
03626     if (i >= 0x100 && i <= 0x3FF) base_io = (unsigned int)(i & ~7);
03627 
03628     i = section->Get_hex("altio");
03629     if (i >= 0x100 && i <= 0x3FF) alt_io = (unsigned int)(i & ~1);
03630 
03631     if (IS_PC98_ARCH) {
03632         /* PC-98 evidently maps all IDE controllers to one set of I/O ports and allows
03633          * "bank switching" between them through I/O ports 430h-435h. This is also why
03634          * the IDE emulation will NOT register I/O ports per controller in PC-98 mode.
03635          * If PC-98 supports IDE controllers outside this scheme, then that shall be
03636          * implemented later. */
03637         IRQ = 9; // INT 8+9 = 17 = 11h
03638         alt_io = 0x74C; // even
03639         base_io = 0x640; // even
03640     }
03641     else if (index < sizeof(IDE_default_IRQs)) {
03642         if (IRQ < 0) IRQ = IDE_default_IRQs[index];
03643         if (alt_io == 0) alt_io = IDE_default_alts[index];
03644         if (base_io == 0) base_io = IDE_default_bases[index];
03645     }
03646     else {
03647         if (IRQ < 0 || alt_io == 0 || base_io == 0)
03648             LOG_MSG("WARNING: IDE interface %u: Insufficient resources assigned by dosbox.conf, and no appropriate default resources for this interface.",index);
03649     }
03650 }
03651 
03652 void IDEController::register_isapnp() {
03653     if (IS_PC98_ARCH)
03654         return;
03655 
03656     if (register_pnp && base_io > 0 && alt_io > 0) {
03657         unsigned char tmp[256];
03658         unsigned int i;
03659 
03660         const unsigned char h1[9] = {
03661             ISAPNP_SYSDEV_HEADER(
03662                 ISAPNP_ID('P','N','P',0x0,0x6,0x0,0x0), /* PNP0600 Generic ESDI/IDE/ATA compatible hard disk controller */
03663                 ISAPNP_TYPE(0x01,0x01,0x00),        /* type: Mass Storage Device / IDE / Generic */
03664                 0x0001 | 0x0002)
03665         };
03666 
03667         i = 0;
03668         memcpy(tmp+i,h1,9); i += 9;         /* can't disable, can't configure */
03669         /*----------allocated--------*/
03670         tmp[i+0] = (8 << 3) | 7;            /* IO resource */
03671         tmp[i+1] = 0x01;                /* 16-bit decode */
03672         host_writew(tmp+i+2,base_io);           /* min */
03673         host_writew(tmp+i+4,base_io);           /* max */
03674         tmp[i+6] = 0x08;                /* align */
03675         tmp[i+7] = 0x08;                /* length */
03676         i += 7+1;
03677 
03678         tmp[i+0] = (8 << 3) | 7;            /* IO resource */
03679         tmp[i+1] = 0x01;                /* 16-bit decode */
03680         host_writew(tmp+i+2,alt_io);            /* min */
03681         host_writew(tmp+i+4,alt_io);            /* max */
03682         tmp[i+6] = 0x01;                /* align */
03683         if (alt_io == 0x3F6 && fdc_takes_port_3F7())
03684             tmp[i+7] = 0x01;            /* length 1 (so as not to conflict with floppy controller at 0x3F7) */
03685         else
03686             tmp[i+7] = 0x02;            /* length 2 */
03687         i += 7+1;
03688 
03689         if (IRQ > 0) {
03690             tmp[i+0] = (4 << 3) | 3;        /* IRQ resource */
03691             host_writew(tmp+i+1,1 << IRQ);
03692             tmp[i+3] = 0x09;            /* HTE=1 LTL=1 */
03693             i += 3+1;
03694         }
03695 
03696         tmp[i+0] = 0x79;                /* END TAG */
03697         tmp[i+1] = 0x00;
03698         i += 2;
03699         /*-------------possible-----------*/
03700         tmp[i+0] = 0x79;                /* END TAG */
03701         tmp[i+1] = 0x00;
03702         i += 2;
03703         /*-------------compatible---------*/
03704         tmp[i+0] = 0x79;                /* END TAG */
03705         tmp[i+1] = 0x00;
03706         i += 2;
03707 
03708         if (!ISAPNP_RegisterSysDev(tmp,i))
03709             LOG_MSG("ISAPNP register failed\n");
03710     }
03711 }
03712 
03713 void IDEController::install_io_port(){
03714     if (IS_PC98_ARCH)
03715         return;
03716 
03717     if (base_io != 0) {
03718         for (unsigned int i=0;i < 8;i++) {
03719             WriteHandler[i].Install(base_io+i,ide_baseio_w,IO_MA);
03720             ReadHandler[i].Install(base_io+i,ide_baseio_r,IO_MA);
03721         }
03722     }
03723 
03724     if (alt_io != 0) {
03725         WriteHandlerAlt[0].Install(alt_io,ide_altio_w,IO_MA);
03726         ReadHandlerAlt[0].Install(alt_io,ide_altio_r,IO_MA);
03727 
03728         /* the floppy controller might take port 0x3F7.
03729          * don't claim it if so */
03730         if (alt_io == 0x3F6 && fdc_takes_port_3F7()) {
03731             LOG_MSG("IDE: Not registering port 3F7h, FDC will occupy it.\n");
03732         }
03733         else {
03734             WriteHandlerAlt[1].Install(alt_io+1u,ide_altio_w,IO_MA);
03735             ReadHandlerAlt[1].Install(alt_io+1u,ide_altio_r,IO_MA);
03736         }
03737     }
03738 }
03739 
03740 IDEController::~IDEController() {
03741     unsigned int i;
03742 
03743     for (i=0;i < 2;i++) {
03744         if (device[i] != NULL) {
03745             delete device[i];
03746             device[i] = NULL;
03747         }
03748     }
03749 }
03750 
03751 static void IDE_PC98_Select(Bitu val) {
03752     val &= 1;
03753     pc98_ide_select = val;
03754     // TODO: IRQ raise by signal
03755 }
03756 
03757 static void ide_pc98ctlio_w(Bitu port,Bitu val,Bitu iolen) {
03758     (void)iolen;
03759 
03760     switch (port & 7) {
03761         case 0:     // 430h
03762             // ???
03763             break;
03764         case 2:     // 432h
03765             if (val & 0x80) {
03766                 // test write?
03767             }
03768             else {
03769                 IDE_PC98_Select(val & 1);
03770             }
03771             break;
03772         case 5:     // 435h
03773             // ???
03774             break;
03775     }
03776 }
03777 
03778 static Bitu ide_pc98ctlio_r(Bitu port,Bitu iolen) {
03779     (void)iolen;
03780 
03781     switch (port & 7) {
03782         case 0:     // 430h
03783             return pc98_ide_select;
03784         case 2:     // 432h
03785             return pc98_ide_select;
03786         case 5:     // 435h
03787             {
03788                 Bitu bf = ~0ul;
03789                 if (idecontroller[0] != NULL)
03790                     bf &= ~(1u << 0u);
03791                 if (idecontroller[1] != NULL)
03792                     bf &= ~(1u << 1u);
03793 
03794                 return bf;
03795             }
03796     }
03797 
03798     return ~0ul;
03799 }
03800 
03801 static void ide_altio_w(Bitu port,Bitu val,Bitu iolen) {
03802     IDEController *ide = match_ide_controller(port);
03803     if (ide == NULL) {
03804         LOG_MSG("WARNING: port read from I/O port not registered to IDE, yet callback triggered\n");
03805         return;
03806     }
03807 
03808     if (!ide->enable_pio32 && iolen == 4) {
03809         ide_altio_w(port,val&0xFFFF,2);
03810         ide_altio_w(port+2u,val>>16u,2);
03811         return;
03812     }
03813     else if (ide->ignore_pio32 && iolen == 4)
03814         return;
03815 
03816     if (IS_PC98_ARCH)
03817         port = (port >> 1) & 1;
03818     else
03819         port &= 1;
03820 
03821     if (port == 0) {/*3F6*/
03822         ide->interrupt_enable = (val&2u)?0:1;
03823         if (ide->interrupt_enable) {
03824             if (ide->irq_pending) ide->raise_irq();
03825         }
03826         else {
03827             if (IS_PC98_ARCH) {
03828                 PC98_IDE_UpdateIRQ();
03829             }
03830             else {
03831                 if (ide->IRQ >= 0) PIC_DeActivateIRQ((unsigned int)ide->IRQ);
03832             }
03833         }
03834 
03835         if ((val&4) && !ide->host_reset) {
03836             if (ide->device[0]) ide->device[0]->host_reset_begin();
03837             if (ide->device[1]) ide->device[1]->host_reset_begin();
03838             ide->host_reset=1;
03839         }
03840         else if (!(val&4) && ide->host_reset) {
03841             if (ide->device[0]) ide->device[0]->host_reset_complete();
03842             if (ide->device[1]) ide->device[1]->host_reset_complete();
03843             ide->host_reset=0;
03844         }
03845     }
03846 }
03847 
03848 static Bitu ide_altio_r(Bitu port,Bitu iolen) {
03849     IDEController *ide = match_ide_controller(port);
03850     IDEDevice *dev;
03851 
03852     if (ide == NULL) {
03853         LOG_MSG("WARNING: port read from I/O port not registered to IDE, yet callback triggered\n");
03854         return ~(0UL);
03855     }
03856 
03857     if (!ide->enable_pio32 && iolen == 4)
03858         return ide_altio_r(port,2) + (ide_altio_r(port+2u,2) << 16u);
03859     else if (ide->ignore_pio32 && iolen == 4)
03860         return ~0ul;
03861 
03862     dev = ide->device[ide->select];
03863 
03864     if (IS_PC98_ARCH)
03865         port = (port >> 1) & 1;
03866     else
03867         port &= 1;
03868 
03869     if (port == 0)/*3F6(R) status, does NOT clear interrupt*/
03870         return (dev != NULL) ? dev->status : ide->status;
03871     else /*3F7(R) Drive Address Register*/
03872         return 0x80u|(ide->select==0?0u:1u)|(ide->select==1?0u:2u)|
03873             ((dev != NULL) ? (((dev->drivehead&0xFu)^0xFu) << 2u) : 0x3Cu);
03874 
03875     return ~(0UL);
03876 }
03877 
03878 static Bitu ide_baseio_r(Bitu port,Bitu iolen) {
03879     IDEController *ide = match_ide_controller(port);
03880     IDEDevice *dev;
03881     Bitu ret = ~0ul;
03882 
03883     if (ide == NULL) {
03884         LOG_MSG("WARNING: port read from I/O port not registered to IDE, yet callback triggered\n");
03885         return ~(0UL);
03886     }
03887 
03888     if (!ide->enable_pio32 && iolen == 4)
03889         return ide_baseio_r(port,2) + (ide_baseio_r(port+2,2) << 16);
03890     else if (ide->ignore_pio32 && iolen == 4)
03891         return ~0ul;
03892 
03893     dev = ide->device[ide->select];
03894 
03895     if (IS_PC98_ARCH)
03896         port = (port >> 1) & 7;
03897     else
03898         port &= 7;
03899 
03900     switch (port) {
03901         case 0: /* 1F0 */
03902             ret = (dev != NULL) ? dev->data_read(iolen) : 0xFFFFFFFFUL;
03903             break;
03904         case 1: /* 1F1 */
03905             ret = (dev != NULL) ? dev->feature : 0x00;
03906             break;
03907         case 2: /* 1F2 */
03908             ret = (dev != NULL) ? dev->count : 0x00;
03909             break;
03910         case 3: /* 1F3 */
03911             ret = (dev != NULL) ? dev->lba[0] : 0x00;
03912             break;
03913         case 4: /* 1F4 */
03914             ret = (dev != NULL) ? dev->lba[1] : 0x00;
03915             break;
03916         case 5: /* 1F5 */
03917             ret = (dev != NULL) ? dev->lba[2] : 0x00;
03918             break;
03919         case 6: /* 1F6 */
03920             ret = ide->drivehead;
03921             break;
03922         case 7: /* 1F7 */
03923             /* if an IDE device exists at selection return it's status, else return our status */
03924             if (dev && dev->status & IDE_STATUS_BUSY) {
03925             }
03926             else if (dev == NULL && ide->status & IDE_STATUS_BUSY) {
03927             }
03928             else {
03929                 ide->lower_irq();
03930             }
03931 
03932             ret = (dev != NULL) ? dev->status : ide->status;
03933             break;
03934     }
03935 
03936     return ret;
03937 }
03938 
03939 static void ide_baseio_w(Bitu port,Bitu val,Bitu iolen) {
03940     IDEController *ide = match_ide_controller(port);
03941     IDEDevice *dev;
03942 
03943     if (ide == NULL) {
03944         LOG_MSG("WARNING: port read from I/O port not registered to IDE, yet callback triggered\n");
03945         return;
03946     }
03947 
03948     if (!ide->enable_pio32 && iolen == 4) {
03949         ide_baseio_w(port,val&0xFFFF,2);
03950         ide_baseio_w(port+2,val>>16,2);
03951         return;
03952     }
03953     else if (ide->ignore_pio32 && iolen == 4)
03954         return;
03955 
03956     dev = ide->device[ide->select];
03957 
03958     if (IS_PC98_ARCH)
03959         port = (port >> 1) & 7;
03960     else
03961         port &= 7;
03962 
03963     /* ignore I/O writes if the controller is busy */
03964     if (dev) {
03965         if (dev->status & IDE_STATUS_BUSY) {
03966             if (port == 6 && ((val>>4)&1) == ide->select) {
03967                 /* some MS-DOS drivers like ATAPICD.SYS are just very pedantic about writing to port +6 to ensure the right drive is selected */
03968                 return;
03969             }
03970             else {
03971                 LOG_MSG("W-%03X %02X BUSY DROP [DEV]\n",(int)(port+ide->base_io),(int)val);
03972                 return;
03973             }
03974         }
03975     }
03976     else if (ide->status & IDE_STATUS_BUSY) {
03977         if (port == 6 && ((val>>4)&1) == ide->select) {
03978             /* some MS-DOS drivers like ATAPICD.SYS are just very pedantic about writing to port +6 to ensure the right drive is selected */
03979             return;
03980         }
03981         else {
03982             LOG_MSG("W-%03X %02X BUSY DROP [IDE]\n",(int)(port+ide->base_io),(int)val);
03983             return;
03984         }
03985     }
03986 
03987 #if 0
03988     if (ide == idecontroller[1])
03989         LOG_MSG("IDE: baseio write port %u val %02x\n",(unsigned int)port,(unsigned int)val);
03990 #endif
03991 
03992     if (port >= 1 && port <= 5 && dev && !dev->allow_writing) {
03993         LOG_MSG("IDE WARNING: Write to port %u val %02x when device not ready to accept writing\n",
03994             (unsigned int)port,(unsigned int)val);
03995     }
03996 
03997     switch (port) {
03998         case 0: /* 1F0 */
03999             if (dev) dev->data_write(val,iolen); /* <- TODO: what about 32-bit PIO modes? */
04000             break;
04001         case 1: /* 1F1 */
04002             if (dev && dev->allow_writing) /* TODO: LBA48 16-bit wide register */
04003                 dev->feature = val;
04004             break;
04005         case 2: /* 1F2 */
04006             if (dev && dev->allow_writing) /* TODO: LBA48 16-bit wide register */
04007                 dev->count = val;
04008             break;
04009         case 3: /* 1F3 */
04010             if (dev && dev->allow_writing) /* TODO: LBA48 16-bit wide register */
04011                 dev->lba[0] = val;
04012             break;
04013         case 4: /* 1F4 */
04014             if (dev && dev->allow_writing) /* TODO: LBA48 16-bit wide register */
04015                 dev->lba[1] = val;
04016             break;
04017         case 5: /* 1F5 */
04018             if (dev && dev->allow_writing) /* TODO: LBA48 16-bit wide register */
04019                 dev->lba[2] = val;
04020             break;
04021         case 6: /* 1F6 */
04022             if (((val>>4)&1) != ide->select) {
04023                 ide->lower_irq();
04024                 /* update select pointer if bit 4 changes.
04025                    also emulate IDE busy state when changing drives */
04026                 if (dev) dev->deselect();
04027                 ide->select = (val>>4)&1;
04028                 dev = ide->device[ide->select];
04029                 if (dev) dev->select(val,1);
04030                 else ide->status = 0; /* NTS: if there is no drive there you're supposed to not have anything set */
04031             }
04032             else if (dev) {
04033                 dev->select(val,0);
04034             }
04035             else {
04036                 ide->status = 0; /* NTS: if there is no drive there you're supposed to not have anything set */
04037             }
04038 
04039             ide->drivehead = val;
04040             break;
04041         case 7: /* 1F7 */
04042             if (dev) dev->writecommand(val);
04043             break;
04044     }
04045 }
04046 
04047 static void IDE_Destroy(Section* sec) {
04048     (void)sec;//UNUSED
04049     for (unsigned int i=0;i < MAX_IDE_CONTROLLERS;i++) {
04050         if (idecontroller[i] != NULL) {
04051             delete idecontroller[i];
04052             idecontroller[i] = NULL;
04053         }
04054     }
04055 
04056     init_ide = 0;
04057 }
04058 
04059 static void IDE_Init(Section* sec,unsigned char ide_interface) {
04060     Section_prop *section=static_cast<Section_prop *>(sec);
04061     IDEController *ide;
04062 
04063     assert(ide_interface < MAX_IDE_CONTROLLERS);
04064 
04065     if (IS_PC98_ARCH && ide_interface >= 2)
04066         return;
04067 
04068     if (!section->Get_bool("enable"))
04069         return;
04070 
04071     if (!init_ide) {
04072         AddExitFunction(AddExitFunctionFuncPair(IDE_Destroy));
04073         init_ide = 1;
04074     }
04075 
04076     LOG(LOG_MISC,LOG_DEBUG)("Initializing IDE controller %u",ide_interface);
04077 
04078     if (idecontroller[ide_interface] != NULL) {
04079         delete idecontroller[ide_interface];
04080         idecontroller[ide_interface] = NULL;
04081     }
04082 
04083     ide = idecontroller[ide_interface] = new IDEController(sec,ide_interface);
04084     ide->install_io_port();
04085 
04086     PIC_SetIRQMask((unsigned int)ide->IRQ,false);
04087 }
04088 
04089 void IDE_Primary_Init(Section *sec) {
04090     IDE_Init(sec,0);
04091 }
04092 
04093 void IDE_Secondary_Init(Section *sec) {
04094     IDE_Init(sec,1);
04095 }
04096 
04097 void IDE_Tertiary_Init(Section *sec) {
04098     IDE_Init(sec,2);
04099 }
04100 
04101 void IDE_Quaternary_Init(Section *sec) {
04102     IDE_Init(sec,3);
04103 }
04104 
04105 void IDE_Quinternary_Init(Section *sec) {
04106     IDE_Init(sec,4);
04107 }
04108 
04109 void IDE_Sexternary_Init(Section *sec) {
04110     IDE_Init(sec,5);
04111 }
04112 
04113 void IDE_Septernary_Init(Section *sec) {
04114     IDE_Init(sec,6);
04115 }
04116 
04117 void IDE_Octernary_Init(Section *sec) {
04118     IDE_Init(sec,7);
04119 }
04120 
04121 const char *ide_names[MAX_IDE_CONTROLLERS] = {
04122     "ide, primary",
04123     "ide, secondary",
04124     "ide, tertiary",
04125     "ide, quaternary",
04126     "ide, quinternary",
04127     "ide, sexternary",
04128     "ide, septernary",
04129     "ide, octernary"
04130 };
04131 void (*ide_inits[MAX_IDE_CONTROLLERS])(Section *) = {
04132     &IDE_Primary_Init,
04133     &IDE_Secondary_Init,
04134     &IDE_Tertiary_Init,
04135     &IDE_Quaternary_Init,
04136     &IDE_Quinternary_Init,
04137     &IDE_Sexternary_Init,
04138     &IDE_Septernary_Init,
04139     &IDE_Octernary_Init
04140 };
04141 
04142 IO_ReadHandleObject  PC98_ReadHandler[8], PC98_ReadHandlerAlt[2], PC98_ReadHandlerSel[3];
04143 IO_WriteHandleObject PC98_WriteHandler[8],PC98_WriteHandlerAlt[2],PC98_WriteHandlerSel[3];
04144 
04145 void PC98_IDE_UpdateIRQ(void) {
04146     if (IS_PC98_ARCH) {
04147         bool raise = false;
04148         IDEController *ide = match_ide_controller(0);
04149         if (ide != NULL)
04150             raise = ide->irq_pending && ide->interrupt_enable;
04151 
04152         if (raise)
04153             PIC_ActivateIRQ(9);
04154         else
04155             PIC_DeActivateIRQ(9);
04156     }
04157 }
04158 
04159 void IDE_OnReset(Section *sec) {
04160     (void)sec;//UNUSED
04161 
04162     for (size_t i=0;i < MAX_IDE_CONTROLLERS;i++) ide_inits[i](control->GetSection(ide_names[i]));
04163 
04164     if (IS_PC98_ARCH) {//TODO: Only if any IDE interfaces are enabled
04165         for (size_t i=0;i < 8;i++) {
04166             PC98_WriteHandler[i].Uninstall();
04167             PC98_ReadHandler[i].Uninstall();
04168             PC98_WriteHandler[i].Install(0x640+(i*2),ide_baseio_w,IO_MA);
04169             PC98_ReadHandler[i].Install(0x640+(i*2),ide_baseio_r,IO_MA);
04170         }
04171 
04172         for (size_t i=0;i < 2;i++) {
04173             PC98_WriteHandlerAlt[i].Uninstall();
04174             PC98_ReadHandlerAlt[i].Uninstall();
04175         }
04176 
04177         PC98_WriteHandlerAlt[0].Install(0x74C,ide_altio_w,IO_MA);
04178         PC98_ReadHandlerAlt[0].Install(0x74C,ide_altio_r,IO_MA);
04179 
04180         PC98_WriteHandlerAlt[1].Install(0x74E,ide_altio_w,IO_MA);
04181         PC98_ReadHandlerAlt[1].Install(0x74E,ide_altio_r,IO_MA);
04182 
04183         for (size_t i=0;i < 3;i++) {
04184             PC98_WriteHandlerSel[i].Uninstall();
04185             PC98_ReadHandlerSel[i].Uninstall();
04186         }
04187 
04188         PC98_WriteHandlerSel[0].Install(0x430,ide_pc98ctlio_w,IO_MA);
04189         PC98_ReadHandlerSel[0].Install(0x430,ide_pc98ctlio_r,IO_MA);
04190 
04191         PC98_WriteHandlerSel[1].Install(0x432,ide_pc98ctlio_w,IO_MA);
04192         PC98_ReadHandlerSel[1].Install(0x432,ide_pc98ctlio_r,IO_MA);
04193 
04194         PC98_WriteHandlerSel[2].Install(0x435,ide_pc98ctlio_w,IO_MA);
04195         PC98_ReadHandlerSel[2].Install(0x435,ide_pc98ctlio_r,IO_MA);
04196     }
04197 }
04198 
04199 void IDE_Init() {
04200     LOG(LOG_MISC,LOG_DEBUG)("Initializing IDE controllers");
04201 
04202     AddVMEventFunction(VM_EVENT_RESET,AddVMEventFunctionFuncPair(IDE_OnReset));
04203 }
04204 
04205 void BIOS_Post_register_IDE() {
04206     for (size_t i=0;i < MAX_IDE_CONTROLLERS;i++) {
04207         if (idecontroller[i] != NULL)
04208             idecontroller[i]->register_isapnp();
04209     }
04210 }
04211